In a Swift + SQLite project I'm trying to populate an array of 4 buttons in my UI with a SQL query. The best I could do so far is as the code below shows, but I'm sure it can be done in a cleaner way. I tried to do both the SQL query result reading and button change in the same loop but got all sorts of type mismatch and reference errors.
Any suggestion will be much appreciated.
var answerText: Array<String?> = ["","","",""]
class ViewController: UIViewController {
#IBOutlet var answerButton: Array<UIButton> = []
func displayQuestion(questionNumber: Int){
let querySQL = "SELECT answer FROM answers WHERE answers.question = '\(questionNumber)'"
let results:FMResultSet? = myDatabase.executeQuery(querySQL,
withArgumentsInArray: nil)
var j=0
while results?.next() == true {
answerText[j] = results?.stringForColumn("answer")
j=j+1
}
j=0
for item in answerButton{
var button:UIButton = item as UIButton
button.setTitle(answerText[j], forState: UIControlState.Normal)
j=j+1
}
}
}
you are getting reference error because you are declaring an array as a IBoutlet . if your answerButton having objects of UIButton than that should not be #IBOutlet var answerButton: Array = [].
answerButton declared like this var answerButton: Array = [].
please modify below code according to you code if you want to test the below code than just copy and past it into func viewDidLoad() of your viewcontroller and this will show you four buttons on you view
var answerText: Array<String?> = ["Button1","Button2","Button3","Button4"]
var answerButton: Array<UIButton> = []
for var i = 0; i<=answerText.count; i++ {
var button = UIButton.buttonWithType(.System) as! UIButton
button.titleLabel!.font = UIFont.systemFontOfSize(12)
button.titleLabel!.lineBreakMode = .ByTruncatingTail
var numberOfButton = 5
let j = i
var y:CGFloat = (CGFloat)(j*690/(numberOfButton+1)-21);
button.frame.size.height = 42
button.frame.size.width = 150
button.frame.origin.y = y
button.frame.origin.x = 250.0
answerButton .insert(button, atIndex: i)
}
for var i = 0; i<answerText.count; i++ {
var button:UIButton = answerButton [i]
button.setTitle(answerText[i], forState: UIControlState.Normal)
self.view .addSubview(button)
}
}
var buttons: [UIButton?] {
return [self.firstButton, self.secondButton, self.thirdButton]
}
Related
I'm building swift quiz app I want to show random questions with no repeat.
var sorular: Array = ["soru1","soru2","soru3","soru4","soru5"]
var gorulensoru = [Int]()
var sayac: Int = 0
var sorularcevaplar = ["D","Y","D","Y","D"]
var cevaplar: Array<Any> = []
var dogru: Int = 0
var yanlis: Int = 0
func chooseRandom() -> String {
if gorulensoru.count == sorular.count { return "" }
let randomItem = Int(arc4random() % UInt32(sorular.count)) //get
if (gorulensoru.contains(randomItem)) {
return chooseRandom()
}
let requiredItem = sorular[randomItem]
gorulensoru.append(randomItem)
return requiredItem
}
override func viewDidLoad() {
super.viewDidLoad()
soruText.text = chooseRandom()
}
What is the problem in my code? I'm tried insert selected random item to inside gorulensoru array but it shows again selected item
if (gorulensoru.contains(randomItem)) {
return chooseRandom()
}
This statement doesn't run.
Your code only runs once.
Also, you shouldn't include potential infinite recursive calls because it can easily get to a level where it causes a hang or crash.
Use shuffle() and then iterate over the array.
Change this and it may work:
let requiredItem = sorular[randomItem]
gorulensoru.append(requiredItem)
#IBOutlet weak var enterName: UITextField!
#IBOutlet weak var presentName: UITextView!
#IBOutlet weak var independceStatue: UITextField!
#IBOutlet weak var driverSelection: UITextField!
var entity : [Entity] = []
var nameList : [String] = []
var period1 = ""
var counting = 0
override func viewDidLoad() {
super.viewDidLoad()
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let request = NSFetchRequest(entityName: "Entity")
var results : [AnyObject]?
do{
results = try context.executeFetchRequest(request)
} catch {
results = nil
}
if results != nil {
self.entity = results as! [Entity]
}
if !entity.isEmpty{
presentName.text = entity.last?.period1Core
}
}
func setValues() {
nameList = [enterName.text!]
}
#IBAction func setName(sender: UIButton) {
setValues()
for item in nameList{
period1 += (item + " ")
}
presentName.text = period1
enterName.text = ""
}
#IBAction func start(sender: UIButton) {
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let entity = NSEntityDescription.insertNewObjectForEntityForName("Entity", inManagedObjectContext: context) as! Entity
entity.period1Core = presentName.text
do {
try context.save()
print("Item Saved")
} catch _ {
print("Saved Failed")
}
**Problem ->** let randomIndex = Int(arc4random_uniform(UInt32(nameList.count)))
driverSelection.text! = nameList[randomIndex]
print(randomIndex)
}
I was trying to randomly pick an element out from the array name nameList, but when I run the program and print the randomIndex, after first time I press the button it will always return last element in the array.
If I exit the simulator and run it again, when I press the button it will return me fatal error Array Index is out of range. Is there somethings wrong with my code, why am I not able to make it randomly select an element from my array?
Your setValues() function always replaces the entire array with the last name entered. That's why it seems to return the last value.
you probably meant to use nameList.append(enterName.text!) in it.
The crash upon starting may occur because nameList has not yet received a name and arc4random_uniform is being called with a parameter value of zero
I have created an array called "questions" that is full of instances of the struct "QuizQuestion" - Basically I want the "nextQuestion" function to pull the next question from the array of structs (questions) and display it to the user (I understand how to present the data through labels etc, I just don`t know how to access it).
I have tried calling the array index and then the instance but that doesnt seem to work. I have also tried creating an instance of "QuizQuestion" as a variable and using that in the "NextQuestion" function which works but I don`t know how to automatically draw questions from "questions".
Thanks
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var answerLabel: UILabel!
#IBOutlet weak var explanationLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
questionVariable()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
struct QuizQuestion {
let question: String
let answer: Bool
let explanation: String
}
let questions: [QuizQuestion] = [
QuizQuestion(question: "Red is a four letter word", answer: false, explanation: "Red is not a four letter word"),
QuizQuestion(question: "Dog is a three letter word", answer: true, explanation: "Dog is most likely a three letter word"),
QuizQuestion(question: "Cow is a three letter word", answer: true, explanation: "Cow is most likely a three letter word")
]
var nextQuestion = QuizQuestion.self[1]
func questionVariable() {
if nextQuestion.answer == true {
questionLabel.text = nextQuestion.question
explanationLabel.text = nextQuestion.explanation
answerLabel.text = "Correct"
}
}
}
You can define a nested function (the simplest form of a closure in Swift) as below:
func getNextQuestion() -> (Int) -> QuizQuestion!
{
func incrementor(var index:Int) -> QuizQuestion! {
if index < questions.count && index >= 0 {
return questions[index]
}
else {
return nil
}
}
return incrementor
}
Then you can access your question list as below
let nextQuestion = getNextQuestion()
var question_1 = nextQuestion(0)
var question_2 = nextQuestion(1)
var question_3 = nextQuestion(2)
println("1.question text: \(question_1.question)")
println("2.question text: \(question_2.question)")
println("3.question text: \(question_3.question)")
A simple function to retrieve the question from the array. Declare a instance variable to hold the current index.
var currentIndex = 0
func nextQuestion() -> QuizQuestion {
// initialize current question
var currentQuestion: QuizQuestion = QuizQuestion(question: "", answer: false, explanation: "")
if currentIndex < questions.count {
currentQuestion = questions[currentIndex]
}
currentIndex++
return currentQuestion
}
I have set of images that need to be set as left icon in leftcalloutaccessoryview in MKAnnotation. I already done it using if else statement. My problem is, instead of using 'if else' statement, it will be great if I can code it in 'for' statement using loop of array. Can anybody help me on this?How can I code the 'leftcalloutaccessoryview' using for loop array using set of images and coordinate that have in my set of arrays? I have been face this code for a month :(...thank you guys
//Define nearby Place of Interest
let latArray = [24.469546, 24.469450]
let longArray = [39.609105, 39.613062]
let poiTitle = ["An-Nisa 1","An-Nisa 2"]
let poiSubTitle = ["Gate 1","Gate 2"]
// let imageName = ["Jons.png","Locus.png"]
for var i=0;i<poiSubTitle.count;i++
{
var latPoi: CLLocationDegrees = latArray[i]
var longPoi: CLLocationDegrees = longArray[i]
var locationPoiAnnot = MKPointAnnotation()
locationPoiAnnot.title = poiTitle[i]
locationPoiAnnot.subtitle = poiSubTitle[i]
var locationPoi : CLLocationCoordinate2D = CLLocationCoordinate2DMake(latPoi,longPoi)
locationPoiAnnot.coordinate = locationPoi
self.mapView.addAnnotation(locationPoiAnnot)
}
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
let arrowButton = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
arrowButton.frame.size.width = 44
arrowButton.frame.size.height = 44
arrowButton.setImage(UIImage(named: "arrow.jpeg"), forState: .Normal)
pinView!.rightCalloutAccessoryView = arrowButton
var imageview = UIImageView(frame: CGRectMake(0, 0, 45, 45))
if(annotation.subtitle == "I am here!")
{
imageview.image=UIImage(named: "Locus.png")
}
else if(annotation.subtitle == "Gate 1")
{
imageview.image=UIImage(named: "Jons.png")
}
else if(annotation.subtitle == "Gate 2")
{
imageview.image=UIImage(named: "Katara.png")
}
pinView!.leftCalloutAccessoryView = imageview
}
else {
pinView!.annotation = annotation
}
return pinView }
Wondering if this helps:
let poiSubTitle = ["Gate 1","Gate 2"]
let imageName = ["Jons.png","Locus.png"]
for(var i = 0 ; i < imageName.count ; i++)
{
if(annotation.subtitle == poiSubTitle[i])
{
imageview.image = UIImage(named: imageName[i])
}
}
pinView!.leftCalloutAccessoryView = imageview
So just add all the 30 POI title to poiSubTitle and image path to imageName without changing the for loops...
I have a for loop that creates a dictionary and then I append the dictionary to an array. I append the dictionary to an array because I don't know how to add more than one value with the same key, when I do that in the for loop the key / value pair is just updated and the old key / value pair is deleted What is the best way to change the array back to a dictionary?
import UIKit
class ViewController: UIViewController {
var jobTitle = ""
var jobDescription = ""
var dict:[String: AnyObject] = ["jobTitle": "jobTitle", "jobDescription": "jobDescription"]
var tArray = [[String: AnyObject]]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for var i = 0; i < 3; ++i {
jobTitle = "job1"
jobDescription = "Desc1"
dict["jobTitle"] = "job1"
dict["jobDescription"] = "Desc1"
tArray.append(dict)
}
println("\(tArray)")
}
}
Like such, where you have more than one value associated with each key:
let jobnames = ["j1", "j2", "j3"]
let jobdescs = ["d1", "d2", "d3"]
var dict : [String:[String]] = [:]
for index in 0..<3 {
if nil == dict["jobTitle"] { dict["jobTitle"] = [] }
if nil == dict["jobDesc" ] { dict["jobDesc" ] = [] }
dict["jobTitle"]!.append(jobnames[index])
dict["jobDesc" ]!.append(jobdescs[index])
}
Here is the output:
You call the same assignmenta such as
jobTitle = "job1"
at every iteration of the loop. Of course the variable will always contain the same value. The same is true for dict. It is an ivar, so you keep overwriting it.
What you want is to create a new collection of type [String: AnyObject] to add to your array.
let newDict:[String : AnyObject] = [titleKey : titleText,
descriptionKey : descriptionText]
tArray.append(newDict)