How do I loop back to the first item in an Array? - arrays

I'm sure this is very simple, but I'm using a button to go to the next item in an array and display it in a label. That much works just fine, however once the end of the array is reached the app crashes since there are no items left to display. How do I get it to go back to the first item? I've tried an If statement but had no luck.
import UIKit
class ViewController: UIViewController {
var firstQuote = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBOutlet weak var quotesLabel: UILabel!
var quotes = ["","Quote 1", "Quote 2", "Quote 3"]
#IBAction func nextButton(_ sender: UIButton) {
firstQuote = firstQuote + 1
quotesLabel.text = quotes[firstQuote]
}
}
This is the If Statement I tried
#IBAction func nextButton(_ sender: UIButton) {
if firstQuote < quotes.count{
firstQuote = firstQuote + 1
quotesLabel.text = quotes[firstQuote]
}
if firstQuote == quotes.count{
firstQuote = 0
quotesLabel.text = quotes[firstQuote]
}
}

A common solution is to use % (the remainder operator) to wrap firstQuote back to 0 when it is equal to quotes.count:
firstQuote = (firstQuote + 1) % quotes.count

This works for me😁
class ViewController: UIViewController {
var quotes = ["Quote 0","Quote 1", "Quote 2", "Quote 3"]
var quotesNum = 0
#IBOutlet weak var result: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
result.text = quotes[quotesNum]
}
#IBAction func incrementButton(_ sender: Any) {
if quotesNum < quotes.count {
quotesNum += 1
if quotesNum == quotes.count {
quotesNum = 0
}
result.text = quotes[quotesNum]
}
}

With This Code Beside Fixing Your Problem, You Can Understand How property observer Can Work
class ViewController: UIViewController {
var quotes = ["Quote 0","Quote 1", "Quote 2", "Quote 3"]
var quotesNum: Int = 0 {
didSet {
result.text = quotes[quotesNum]
}
}
#IBOutlet weak var result: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
result.text = quotes[quotesNum]
}
#IBAction func incrementButton(_ sender: Any) {
if quotesNum < quotes.count - 1 {
if quotesNum == quotes.count - 1 {
quotesNum = 0
} else {
quotesNum += 1
}
} else {
quotesNum = 0
}
}

Related

How to have two variables depending on each other

I have this problem: I have two text fields, one pickerView containing an array and another text field where you need to put in a specific code depending on the selection you made in the pickerView to be able to press the button. This is what I got
var SchoolsArray = ["Option 1",
"Option 2",
"Option 3",
"Option 4"]
var code1 = "zxy" // code for Option 1
var code2 = "gbv" // code for Option 2
var code3 = "jwn" // code for Option 3
var code4 = "hqc" // code for Option 4
#IBOutlet weak var firstNameTxtField: UITextField!
#IBOutlet weak var schoolNameTxtField: UITextField!
#IBOutlet weak var schoolCodeTxtField: UITextField!
#IBAction func createAccountBtnPressed(_ sender: Any) {
if firstNameTxtField.text != nil && schoolNameTxtField.text != nil && schoolCodeTxtField.text != nil {
if schoolNameTxtField.text == "Option 1" && schoolCodeTxtField.text == code1 {
//do something here
} else {
}
} else {
}
}
As you can see this only works if you select Option 1. How can I make this work so if you select "Option 1" and in schoolCodeTxtField put in "zxy" it will proceed and if you select "Option 2" and put in "gbv" it will also proceed and so on. I hope you understand what I mean. I appreciate all help
Just like SchoolArray, you can use an array for the codes as well, and use following method:
var CodesArray = ["zxy", "gbv", "jwn", "hqc"]
#IBAction func createAccountBtnPressed(_ sender: Any) {
guard
firstNameTxtField.text != nil,
let option = schoolNameTxtField.text,
let index = SchoolsArray.index(where: { $0 == option }),
CodesArray[index] == schoolCodeTxtField.text
else {
return
}
// Code & Option both matched
}
How about use a dictionary that contains your options as keys and your codes as values. Something like this:
var SchoolsOptions = ["Option 1": "zxy",
"Option 2": "gbv",
"Option 3": "jwn",
"Option 4": "hqc"]
#IBAction func createAccountBtnPressed(_ sender: Any) {
if firstNameTxtField.text != nil && schoolNameTxtField.text != nil && schoolCodeTxtField.text != nil {
for (option, code) in SchoolsOptions {
if schoolNameTxtField.text == option && schoolCodeTxtField.text == code {
//do something here
// You only get here if the option and code match for that given school. If you need specific logic for each school you'll have to check which option you're on.
}
}
} else {
}
}
This is the cleanest solution I can think of right off the bat.
#IBOutlet weak var firstNameTxtField: UITextField!
#IBOutlet weak var schoolNameTxtField: UITextField!
#IBOutlet weak var schoolCodeTxtField: UITextField!
var codeArray: [String] = [
"zxy",
"gbv",
"jwn",
"hqc"
]
var selectedCode: String!
override func viewDidLoad() {
super.viewDidLoad()
setupPickerViewAndAssignItsDelegateAndDatasource()
guard let selectedCode = codeArray.first else { return }
self.selectedCode = selectedCode
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return codeArray.count
}
public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return "Option \(row + 1)"
}
public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedCode = codeArray[row]
}
#IBAction func createAccountBtnPressed(_ sender: Any) {
if firstNameTxtField.text != nil && schoolNameTxtField.text != nil && schoolCodeTxtField.text != nil {
if schoolNameTxtField.text == selectedCode {
//do something here
} else {
}
} else {
}
}

Swift 3 JSON to array of objects is very slow

I am upgrading my app from swift 2 to swift 3 and have a significant performance loss when building an array of custom objects. In swift 2 this took a few seconds while in swift 3 it takes around 30 seconds. I am using alamofire to return swiftyJSON, returning about 3000 rows of data. the alamofire return is quick, its looping through this json to build array of custom objects thats slow. These objects greatly simplify the code written when building table cells and passing data to new views.
Code:
class Customer {
var ID: String!
var sysName: String!
var address: String!
var contactID: String!
required init(_name:String?, _id: String?, _address:String?, _contactID:String?) {
//print(json)
if _id != nil {
self.ID = _id
}else{
self.ID = ""
}
if _name != nil {
self.sysName = _name
}else{
self.sysName = ""
}
if _address != nil {
self.address = _address
}else{
self.address = "No Address on File"
}
if _contactID != nil {
self.contactID = _contactID
}else{
self.contactID = ""
}
}
}
Alamofire.request(API.Router.customerList()).responseJSON() {
response in
print(response.request ?? "") // original URL request
print(response.response ?? "") // URL response
print(response.data ?? "") // server data
print(response.result) // result of response serialization
if let json = response.result.value {
print("JSON: \(json)")
self.customers = JSON(json)
self.parseJSON()
}
}
func parseJSON(){
let jsonCount = self.customers["customers"].count
self.totalCustomers = jsonCount
for i in 0 ..< jsonCount {
self.loadedCustomers = i
print("customer = \(self.customers["customers"][i] ["sysName"].string!)")
//VERY SLOW
//create a customer object
let customer = Customer( _name: self.customers["customers"][i]["sysName"].string!, _id: self.customers["customers"][i]["ID"].string!, _address: self.customers["customers"][i]["mainAddr"].string!, _contactID: self.customers["customers"][i]["contactID"].string!)
//add customer to customer array
self.customersArray.append(customer)
}
self.layoutViews() //build view, call all table methods
}
Thanks
Improved code:
import Foundation
import UIKit
import Alamofire
import SwiftyJSON
enum SearchMode{
case name
case address
}
class CustomerListViewController: ViewControllerWithMenu, UITableViewDelegate, UITableViewDataSource, UISearchControllerDelegate, UISearchBarDelegate, UISearchDisplayDelegate, UISearchResultsUpdating{
var indicator: SDevIndicator!
var totalCustomers:Int!
//data arrays
var ids = [String]()
var names = [String]()
var addresses = [String]()
var searchController:UISearchController!
var currentSearchMode = SearchMode.name
var customerTableView:TableView = TableView()
var layoutVars:LayoutVars = LayoutVars()
var sections : [(index: Int, length :Int, title: String)] = Array()
var customersSearchResults:[String] = []
var shouldShowSearchResults:Bool = false
let viewsConstraint_V:NSArray = []
let viewsConstraint_V2:NSArray = []
override func viewDidLoad() {
super.viewDidLoad()
title = "Customer List"
view.backgroundColor = layoutVars.backgroundColor
getCustomerList()
}
func getCustomerList() {
//remove any added views (needed for table refresh
for view in self.view.subviews{
view.removeFromSuperview()
}
// Show Indicator
indicator = SDevIndicator.generate(self.view)!
Alamofire.request(API.Router.customerList()).responseJSON() {
response in
//print(response.request ?? "") // original URL request
//print(response.response ?? "") // URL response
//print(response.data ?? "") // server data
//print(response.result) // result of response serialization
do {
if let data = response.data,
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let customers = json["customers"] as? [[String: Any]] {
for customer in customers {
if let id = customer["ID"] as? String {
self.ids.append(id)
}
if let name = customer["sysName"] as? String {
self.names.append(name)
}
if let address = customer["mainAddr"] as? String {
self.addresses.append(address)
}
}
}
} catch {
print("Error deserializing JSON: \(error)")
}
// build sections based on first letter(json is already sorted alphabetically)
var index = 0;
var firstCharacterArray:[String] = [" "]
for i in 0 ..< self.names.count {
let stringToTest = self.names[i].uppercased()
let firstCharacter = String(stringToTest[stringToTest.startIndex])
if(i == 0){
firstCharacterArray.append(firstCharacter)
}
if !firstCharacterArray.contains(firstCharacter) {
let title = firstCharacterArray[firstCharacterArray.count - 1]
firstCharacterArray.append(firstCharacter)
let newSection = (index: index, length: i - index, title: title)
self.sections.append(newSection)
index = i;
}
if(i == self.names.count - 1){
let title = firstCharacterArray[firstCharacterArray.count - 1]
let newSection = (index: index, length: i - index, title: title)
self.sections.append(newSection)
}
}
self.layoutViews()
}
}
func layoutViews(){
indicator.dismissIndicator()
searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.placeholder = "Search Customers"
searchController.searchResultsUpdater = self
searchController.delegate = self
searchController.searchBar.delegate = self
searchController.dimsBackgroundDuringPresentation = false
searchController.hidesNavigationBarDuringPresentation = false
navigationItem.titleView = searchController.searchBar
let items = ["Name","Address"]
let customSC = SegmentedControl(items: items)
customSC.selectedSegmentIndex = 0
customSC.addTarget(self, action: #selector(self.changeSearchOptions(sender:)), for: .valueChanged)
self.view.addSubview(customSC)
self.customerTableView.delegate = self
self.customerTableView.dataSource = self
self.customerTableView.register(CustomerTableViewCell.self, forCellReuseIdentifier: "cell")
self.view.addSubview(self.customerTableView)
//auto layout group
let viewsDictionary = [
"view2":customSC,
"view3":self.customerTableView
]as [String:AnyObject]
let sizeVals = ["fullWidth": layoutVars.fullWidth,"width": layoutVars.fullWidth - 30,"navBottom":layoutVars.navAndStatusBarHeight,"height": self.view.frame.size.height - 100] as [String:Any]
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view2(fullWidth)]", options: [], metrics: sizeVals, views: viewsDictionary))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view3(fullWidth)]", options: [], metrics: sizeVals, views: viewsDictionary))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-navBottom-[view2(40)][view3(height)]", options: [], metrics: sizeVals, views: viewsDictionary))
}
/////////////// Search Methods ///////////////////////
func changeSearchOptions(sender: UISegmentedControl) {
switch sender.selectedSegmentIndex {
case 0:
currentSearchMode = .name
break
case 1:
currentSearchMode = .address
break
default:
currentSearchMode = .name
break
}
filterSearchResults()
}
func updateSearchResults(for searchController: UISearchController) {
filterSearchResults()
}
func filterSearchResults(){
customersSearchResults = []
switch currentSearchMode {
case .name:
self.customersSearchResults = self.names.filter({( aCustomer: String ) -> Bool in
return (aCustomer.lowercased().range(of: self.searchController.searchBar.text!.lowercased()) != nil) })
break
case .address:
self.customersSearchResults = self.addresses.filter({( aCustomer: String) -> Bool in
return (aCustomer.lowercased().range(of: self.searchController.searchBar.text!.lowercased()) != nil)
})
break
}
self.customerTableView.reloadData()
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
//print("searchBarTextDidBeginEditing")
shouldShowSearchResults = true
self.customerTableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
shouldShowSearchResults = false
self.customerTableView.reloadData()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
if !shouldShowSearchResults {
shouldShowSearchResults = true
self.customerTableView.reloadData()
}
searchController.searchBar.resignFirstResponder()
}
/////////////// TableView Delegate Methods ///////////////////////
func numberOfSections(in tableView: UITableView) -> Int {
if shouldShowSearchResults{
return 1
}else{
return sections.count
}
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
//print("titleForHeaderInSection")
if shouldShowSearchResults{
return nil
}else{
if(sections[section].title == "#"){
return " # \(self.totalCustomers) Customers Found"
}else{
return " " + sections[section].title //hack way of indenting section text
}
}
}
func sectionIndexTitles(for tableView: UITableView) -> [String]?{
print("sectionIndexTitlesForTableView 1")
if shouldShowSearchResults{
return nil
}else{
//print("sectionIndexTitlesForTableView \(sections.map { $0.title })")
return sections.map { $0.title }
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
//print("heightForHeaderInSection")
if shouldShowSearchResults{
return 0
}else{
return 50
}
}
func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
return index
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//print("numberOfRowsInSection")
if shouldShowSearchResults{
return self.customersSearchResults.count
} else {
return sections[section].length
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = customerTableView.dequeueReusableCell(withIdentifier: "cell") as! CustomerTableViewCell
customerTableView.rowHeight = 50.0
if shouldShowSearchResults{
let searchString = self.searchController.searchBar.text!.lowercased()
if(currentSearchMode == .name){
cell.nameLbl.text = self.customersSearchResults[indexPath.row]
cell.name = self.customersSearchResults[indexPath.row]
if let i = self.names.index(of: cell.nameLbl.text!) {
//print("\(cell.nameLbl.text!) is at index \(i)")
cell.addressLbl.text = self.addresses[i]
cell.address = self.addresses[i]
cell.id = self.ids[i]
} else {
cell.addressLbl.text = ""
cell.address = ""
cell.id = ""
}
//text highlighting
let baseString:NSString = cell.name as NSString
let highlightedText = NSMutableAttributedString(string: cell.name)
var error: NSError?
let regex: NSRegularExpression?
do {
regex = try NSRegularExpression(pattern: searchString, options: .caseInsensitive)
} catch let error1 as NSError {
error = error1
regex = nil
}
if let regexError = error {
print("Oh no! \(regexError)")
} else {
for match in (regex?.matches(in: baseString as String, options: NSRegularExpression.MatchingOptions(), range: NSRange(location: 0, length: baseString.length)))! as [NSTextCheckingResult] {
highlightedText.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellow, range: match.range)
}
}
cell.nameLbl.attributedText = highlightedText
}else{//address search mode
cell.addressLbl.text = self.customersSearchResults[indexPath.row]
cell.address = self.customersSearchResults[indexPath.row]
if let i = self.addresses.index(of: cell.addressLbl.text!) {
cell.nameLbl.text = self.names[i]
cell.name = self.names[i]
cell.id = self.ids[i]
} else {
cell.nameLbl.text = ""
cell.name = ""
cell.id = ""
}
//text highlighting
let baseString:NSString = cell.address as NSString
let highlightedText = NSMutableAttributedString(string: cell.address)
var error: NSError?
let regex: NSRegularExpression?
do {
regex = try NSRegularExpression(pattern: searchString, options: .caseInsensitive)
} catch let error1 as NSError {
error = error1
regex = nil
}
if let regexError = error {
print("Oh no! \(regexError)")
} else {
for match in (regex?.matches(in: baseString as String, options: NSRegularExpression.MatchingOptions(), range: NSRange(location: 0, length: baseString.length)))! as [NSTextCheckingResult] {
highlightedText.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellow, range: match.range)
}
}
cell.addressLbl.attributedText = highlightedText
}
} else {
//print("make cell")
cell.id = self.ids[sections[indexPath.section].index + indexPath.row]
cell.name = self.names[sections[indexPath.section].index + indexPath.row]
cell.address = self.addresses[sections[indexPath.section].index + indexPath.row]
cell.nameLbl.text = self.names[sections[indexPath.section].index + indexPath.row]
cell.addressLbl.text = self.addresses[sections[indexPath.section].index + indexPath.row]
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let indexPath = tableView.indexPathForSelectedRow;
let currentCell = tableView.cellForRow(at: indexPath!) as! CustomerTableViewCell
let customerViewController = CustomerViewController(_customerID: currentCell.id)
navigationController?.pushViewController(customerViewController, animated: false )
tableView.deselectRow(at: indexPath!, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

My loop to grab number of results within an array in swift is not working

Greetings dear fans and programmers of the Swift language. I have tried to formulate an algorithm number of times an element shows up within an array with a for loop, but it doesn't seem to be working.
My code is as follows:
else if indexPath.section == 1 {
cell = tableView.dequeueReusableCellWithIdentifier("GreenCell", forIndexPath: indexPath)
for item in theModel.userAnswer {
numOfCoincidences[item] = (numOfCoincidences[item] ?? 0) + 1
}
for (numLangs, value) in numOfCoincidences {
txtSummary = "#languages spoken: \(numLangs)"
txtSummary2 = "# of People: \(value)"
}
cell.textLabel?.text = txtSummary
cell.detailTextLabel?.text = txtSummary2
I am trying to display this information in a table Cell but it is not working. I thought that my algorithm was spot on. Any suggestions?
I'm getting the following output: I have a navigation controller in effect where I input data on one screen and it outputs the data on a table. It's a bit of a survey where I prompt the user to enter their name and the number of languages spoken. I'm using an MVC programming methodology.
so in the model, here is the code:
import Foundation
class Model {
var userName = [String]()
var userAnswer = [String]()
var userInfo = [String]()
var name:String
var answer:String
init(){
self.name = ""
self.answer = ""
}
func addUserInfo(name:String, answer:String) -> Void {
userName.append(name)
userAnswer.append(answer)
}
}
In the input screen, I have 2 text boxes that prompt for username and number of languages spoken. So on the output screen, if 2 people speak 4 languages, the output should reflect that, but it's not. If 1 person speaks 3 languages, it should display that and so on. The output is coming out completely incorrectly. Here is the for the data entry code:
import UIKit
class ViewController: UIViewController {
var model = Model()
#IBOutlet var txtName: UITextField!
#IBOutlet var lblStatus: UILabel!
#IBOutlet var txtAnswer: UITextField!
#IBAction func btnAnswer(sender: UIButton) {
model.answer = txtAnswer.text!
model.name = txtName.text!
if ((txtName.text)! == "" || (txtAnswer.text)! == "") {
lblStatus.text = "Name and answer are both required"
}else if model.userName.contains(model.name) {
lblStatus.text = "Answer already recorded for \(model.name)"
} else {
model.addUserInfo(model.name, answer: model.answer)
lblStatus.text = "Ok, \(model.name) answered \(model.answer)"
}
txtAnswer.text = ""
txtName.text = ""
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toReesultsController" {
let vc = segue.destinationViewController as! TableViewController
vc.theModel = self.model
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
The code for the table to display the data inputted from the data entry screen is presented in a table as shown below:
import UIKit
class TableViewController: UITableViewController {
var theModel = Model()
var numOfCoincidences:[String:Int] = [:]
var txtSummary:String = ""
var txtSummary2:String = ""
var greatest:Int = 0
/* override func viewDidLoad() {
for index in 0..<theModel.userName.count {
}
}*/
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return theModel.userAnswer.count
} else if section == 1 {
return theModel.userAnswer.count
} else if section == 2{
return theModel.userAnswer.count
} else {
return 0
}
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Answer Log"
} else if section == 1 {
return "Summary"
} else if section == 2 {
return "Top Answers"
} else {
return nil
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell! = nil
if indexPath.section == 0 {
cell = tableView.dequeueReusableCellWithIdentifier("BlueCell", forIndexPath: indexPath)
cell.textLabel?.text = "\(theModel.userName[indexPath.row]):\(theModel.userAnswer[indexPath.row])"
} else if indexPath.section == 1 {
cell = tableView.dequeueReusableCellWithIdentifier("GreenCell", forIndexPath: indexPath)
for item in theModel.userAnswer {
numOfCoincidences[item] = (numOfCoincidences[item] ?? 0) + 1
}
for (numLangs, value) in numOfCoincidences {
txtSummary = "#languages spoken: \(numLangs)"
txtSummary2 = "# of People: \(value)"
}
cell.textLabel?.text = txtSummary
cell.detailTextLabel?.text = txtSummary2
} else if indexPath.section == 2 {
cell = tableView.dequeueReusableCellWithIdentifier("OrangeCell", forIndexPath: indexPath)
greatest = 0
for index in 0..<theModel.userAnswer.count {
if Int(theModel.userAnswer[index])! > greatest {
greatest = Int(theModel.userAnswer[index])!
}
}
cell.textLabel?.text = "Answer with most votes is \(greatest) languages spoken."
}
return cell
}
}
Based on what you have shared, and making some assumptions on your input this seems to do what you want.
If each item is a dictionary with the keys shown below. Then you would walk through the array and get the number of languages spoken by the person. I chose to define that as a number(Int) since that is what it really is.
This is almost the same as your original code so I have to conclude that your idea was correct, but your implementation was missing something.
Assuming this is your input:
let a = [["name":"carla", "langs" : 3], ["name":"scott", "langs" : 3], ["name":"brad", "langs" : 1], ["name":"cynthia", "langs":2]]
var numOfCoincidences = [Int: Int]()
for item in a {
let numLangs = item["langs"] as! Int
numOfCoincidences[numLangs] = (numOfCoincidences[numLangs] ?? 0) + 1
}
var txtSummary = ""
var txtSummary2 = ""
for (numLangs, value) in numOfCoincidences {
// You should also note that you are overwriting values here.
txtSummary = "#languages spoken: \(numLangs)"
txtSummary2 = "# of People: \(value)"
print(txtSummary)
print(txtSummary2)
}
numOfCoincidences
Output:
// key := number of languages spoken
// value := number of people who speak that many languages
[2: 1, 3: 2, 1: 1]
You do have a problem in your cellForRowAtIndexPath.
After you loop through all the data, you do this:
cell.textLabel?.text = txtSummary
cell.detailTextLabel?.text = txtSummary2
Therefore, every cell is going to have the last values from the loop.

Swift PickerView does not show array elements

My "picker2" pickerview does not show data from "modelArray" array. When I dup the array I have data in it. But no data shown in pickerview at all.
I did everything on mind and did my research how to do it. But no success.
Any help will be highly appreciated :)
import UIKit
class MakeViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet weak var txt_make: UITextField!
#IBOutlet weak var txt_model: UITextField!
var makeArray = [String]()
var modelArray = [String]()
var picker = UIPickerView()
var picker2 = UIPickerView()
var numberOfRowsMake = 0
var numberOfRowsModel = 0
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
picker.dataSource = self
picker2.delegate = self
picker2.dataSource = self
txt_make.inputView = picker
txt_model.inputView = picker2
txt_make.clearButtonMode = .Always
txt_model.clearButtonMode = .Always
parseJSON2()
}
func parseJSON2() {
let path : String = NSBundle.mainBundle().pathForResource("json2", ofType: "json")! as String
let jsonDATA = NSData(contentsOfFile: path) as NSData!
numberOfRowsMake = readableJSON["Cars"].count
for var i = 0; i < numberOfRowsMake; ++i {
let make = readableJSON["Cars"][i]["Manufacturer"].stringValue
makeArray.append(make)
}
}
func parseJSON3() {
let path : String = NSBundle.mainBundle().pathForResource("json2", ofType: "json")! as String
let jsonDATA = NSData(contentsOfFile: path) as NSData!
numberOfRowsMake = readableJSON["Cars"].count
for var i = 0; i < numberOfRowsMake; ++i {
let make = readableJSON["Cars"][i]["Manufacturer"].stringValue
let model = readableJSON["Cars"][i]["Model"].stringValue
print(txt_make.text)
if make == txt_make.text {
modelArray.append(model)
}
}
dump(modelArray)
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == picker {
return numberOfRowsMake
}
if pickerView == picker2 {
return numberOfRowsModel
}
return 1
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == picker {
txt_make.text = makeArray[row]
}
if pickerView == picker2 {
self.picker2.reloadAllComponents()
parseJSON3()
txt_model.text = modelArray[row]
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == picker {
return makeArray[row]
}
if pickerView == picker2 {
return modelArray[row]
}
return ""
}
}
Here is the local JSON file.
{
"Cars" :
[{
"Manufacturer": "ABARTH1",
"Model": "500, 2012 onwards",
}, {
"Manufacturer": "ABARTH1",
"Model": "500, 2012 onwards",
}, {
"Manufacturer": "ABARTH1",
"Model": "500, 2012 onwards",
}, {
"Manufacturer": "ABARTH2",
"Model": "500, 2012 onwards",
}, {
"Manufacturer": "ABARTH2",
"Model": "500, 2012 onwards",
}, {
"Manufacturer": "ABARTH2",
"Model": "500, 2012 onwards",
}
]
}

Swift count string size in for loop

for my homework assignment I have to convert the sentence the user has typed in 3 different ways.
Convert all letters to uppercase(completed)
Convert all letters to lowercase(completed)
Convert the uppercase letters to lowercase and vice versa(having trouble)
I believe my logic is correct but I don't know where I am wrong.
This is my code:
//
// ViewController.swift
// Lower Upper Converter
//
// Created by Mac User on 9/27/15.
// Copyright © 2015 Omid Nassir. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
private var input = ""
private var i = 0
var sentense = [String]()
//var sentenseChar: [Character] = []
//input fields
#IBOutlet weak var input1: UITextField!
#IBOutlet weak var input2: UITextField!
//caps button
#IBAction func capsBtn(sender: AnyObject)
{
if input1.text != nil
{
input = input1.text!.uppercaseString
input2.text = input
}
else
{
input2.text = ""
}
}
//lower case button
#IBAction func lowsBtn(sender: AnyObject)
{
if input1.text != nil
{
input = input1.text!.lowercaseString
input2.text = input
}
else
{
input2.text = ""
}
}
//word converter button
#IBAction func capsLowsBtn(sender: AnyObject)
{
if input1.text != nil
{
for i=0; i < count(input1.text); i++
{
input = advance(input1.startIndex, i)
str[input]
sentense[i] = advance(input.startIndex, i)
}
}
}//end of convert function
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I am getting an error message:
Cannot invoke 'count' with an argument list of type '(String?)'
for this statement: for i=0; i < count(input1.text); i++
Note! With Swift 2 you have to use a new syntax:
Change your code to:
for var i = 0; i < input1.text!.characters.count; i++
{
...
}
A better way of doing this will be: (Tested in Swift 3.x)
for i in 0 ..< input1.text!.characters.count
{
...
}

Resources