Swift- How to dynamically create labels - arrays

I have created some code which reads through an array and saves data for each index into variables which I then pass onto to a created label.
Below is the code:
example of data arr content :
["2,5","5,1"] two indexes inside array
for i in 0..<dataArr.count {
let element = dataArr[i]
let labelNum = UILabel()
label split = element.components(separatedBy: ",")
let num1 = split[0]
let num2 = split[1]
let num1Nnum2 = "number 1 :" + num1 + " number 2:" + num2
labelnum.text = num1Nnum2
labelnum.textAlignment = .center
labelnum.frame = CGRect( x:10, y:90, width:250, height: 80)
self.view.addSubview(labelnum)
}
how can I create it so that when the label is created the second time when it reads index[1] it creates a new label with same code but drop the label under the first label. I have tried to do :
labelnum[i] to attempt to create a new label using the value of index for example labelnum1 when i is = 1.
Any help will be Appreciated.

There is UIStackView in iOS which lets you add elements dynamically at the bottom or top of the existing views. You can always add a new label which automatically appears at the bottom of the view. You can also accomplish this with UITableView or UIScrollView.
Here is an example of UIStackView, dynamically appending new label below previous one. I hope you can infer this for your use case,
class ViewController: UIViewController {
var lastLabelCount = 0
var stackView: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
let tap = UITapGestureRecognizer(target: self,
action: #selector(tapped))
view.addGestureRecognizer(tap)
createViews()
}
func createViews() {
stackView = UIStackView(frame: .zero)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .top
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.leftAnchor.constraint(equalTo: view.leftAnchor),
stackView.rightAnchor.constraint(equalTo: view.rightAnchor),
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
])
}
#objc func tapped() {
let label = UILabel(frame: .zero)
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = UIColor.black
label.text = "Hi I am label \(lastLabelCount)"
stackView.addArrangedSubview(label)
lastLabelCount += 1
}
}

Create a variable to hold Y Position of The Label. and in each iteration add the height of previous label in Y Position variable to drop new label to below previous one.
class ViewController: UIViewController {
let dataArr = ["2,5","5,1"]
override func viewDidLoad() {
super.viewDidLoad()
var yPos = 90
for i in 0..<dataArr.count {
let element = dataArr[i]
let labelNum = UILabel()
let split = element.components(separatedBy: ",")
let num1 = split[0]
let num2 = split[1]
let num1Nnum2 = "number 1 :" + num1 + " number 2:" + num2
labelNum.text = num1Nnum2
labelNum.textAlignment = .center
labelNum.frame = CGRect( x:10, y:yPos, width:250, height: 80)
yPos += 80
self.view.addSubview(labelNum)
}
}

Related

Swift: Create multiple views through iteration with spacing without using StackView

I'm trying to create multiple labels with padding of 20 between each item without using stackView. My current logic has them all aligned on top of each other. Any thoughts whats wrong with the current code? Im not seeing it.
let sections = ["List", "Items", "News"]
var previousLabel: UILabel?
var sectionsArray = [UILabel]()
var leadConstraint: NSLayoutConstraint?
let navigationView = UIView(frame: CGRect(x: 20, y: 100, width: 100, height: 30))
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
view.addSubview(navigationView)
navigationView.backgroundColor = .red
for label in sections {
let newLabel = UILabel(frame: CGRect.zero)
newLabel.text = label
newLabel.textColor = .white
newLabel.backgroundColor = .systemBlue
newLabel.sizeToFit()
navigationView.addSubview(newLabel)
if let previous = previousLabel {
leadConstraint = newLabel.leftAnchor.constraint(equalTo: previous.rightAnchor, constant: 20)
leadConstraint?.isActive = true
newLabel.topAnchor.constraint(equalTo: navigationView.topAnchor, constant: 0).isActive = true
newLabel.bottomAnchor.constraint(equalTo: navigationView.bottomAnchor, constant: 0).isActive = true
} else {
//1st item in section
newLabel.leftAnchor.constraint(equalTo: navigationView.leftAnchor, constant: 20).isActive = true
newLabel.topAnchor.constraint(equalTo: navigationView.topAnchor, constant: 0).isActive = true
newLabel.bottomAnchor.constraint(equalTo: navigationView.bottomAnchor, constant: 0).isActive = true
}
sectionsArray.append(newLabel)
previousLabel = newLabel
}
This is a image of the error message, i couldnt make out what exactly what constraint was having a problem.
Change
let newLabel = UILabel(frame: CGRect.zero)
To
let newLabel = UILabel(frame: CGRect.zero)
newLabel.translatesAutoresizingMaskIntoConstraints = false
This will expose other flaws in your implementation, but at least the labels will line up horizontally in the way you expect.

use #objc func to place a empty array of imageViews

I want to use my swift code to place a imageview everytime the func moveRight is called. I want each new imageView to be separated by a 50 on the y axis. Right now my code compiles but nothing is changing when the function is called. But in the debug area I am seeing the count increasing.
import UIKit
class ViewController: UIViewController {
var myArray = [UIImageView]()
var bt = UIButton()
var count : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(bt)
bt.backgroundColor = UIColor.systemOrange
bt.frame = CGRect(x: view.center.x - 0, y: view.center.y , width: 50, height: 50)
bt.addTarget(self, action: #selector(moveRight), for: .touchUpInside)
}
#objc func moveRight() {
print("Yes")
myArray.forEach({
$0.backgroundColor = UIColor.systemTeal
self.view.addSubview($0)
})
var ht = 50
myArray.insert(UIImageView(), at: count)
print("Your Count is ", count)
myArray[count].frame = CGRect(x: view.center.x - 0, y: view.center.y + CGFloat(ht), width: 50, height: 50)
count += 1
ht += 50
}
}
You need to move the ht variable outside the moveRight() method.
Currently every time you run the method you recreate the variable and set it's initial value to 50, and then use that to set your location.
You need to do
class ViewController: UIViewController {
var myArray = [UIImageView]()
var bt = UIButton()
var count : Int = 0
var ht = 50 //initialise it here, then update it in the moveRight() method
//etc
and then remove the equivalent line from the method.

Swift- How to add onto arraylist next index everytime save button is pressed

Hi my question is how can I store a string value which contails all textfield input into an array with new index every time I press save. I have created some code below however I think its overriding the first index.
#IBAction func Save (_ sender: UIButton){
let firstextfield = textfield1.text
let secondtextfield = textfield2.text
let allText = firsttextfield! + "," + secondtextfield!
var myArray = [String]()
var index : Int = 0
while (myArray.count) <= index {
myArray.insert(allText, at: index)
}
index +=
for element in myArray{
print(element)
}
}
input: firsttextfield = 9.22 and secondtextfield = 91.2
save button is then pressed.
output:
Optional ("9.22,91.2")
Optional ("")
if i were to then change the values of my textfields to firsttextfield = 0.2 and secondtextfield = 20.2
I get output :
Optional ("0.2,20.2")
Optional ("")
I dont want it to overide the array but to add onto it so expected output:
Optional ("9.22,91.2")
Optional ("0.2,20.2")
Any tips are welcome as I am new to coding.
//Just Declare outside of button action
var index = 0
var myArray = [String?]()
//Button action
#IBAction func btnShareTapped(_ sender: UIButton) {
let firstextfield = "textfield1.text"
let secondtextfield = "textfield2.text"
let allText = firstextfield + "," + secondtextfield
while (myArray.count) <= index {
myArray.append("")
}
myArray.insert(allText, at: index)
index = index + 1
for element in myArray{
print(element)
}
print(myArray)
}
Output
[Optional("textfield1.text,textfield2.text"), Optional("")]
[Optional("textfield1.text,textfield2.text"), Optional("textfield1.text,textfield2.text"), Optional("")]
//your last comment answer is
let a : String = myArray[0]!
let b = a.split(separator: ",")
label.text = b[0] as! String
label1.text = b[1] as! String
I think your emptying the array here:
var myArray = [String?]()
var index = 0
while (myArray.count) <= index {
myArray.append("")
}
declare and initialise it outside the function and then use this to insert values to array:
let allText = firsttextfield! + "," + secondtextfield!
anArray.append(allText)

remove matching images from two Arrays

I'm making a snap game were I'm trying to remove two images from an array so they don't reappear again when first random card and second random card match. Is there any way I can do this? Thanks
var cardNamesArray: [String] = ["sad", "sleepy","angry"]
var cardNamesArray2: [String] = ["triste", "cansado","enfadado"]
Generates a random card for the first Array
firstRandomNumber = Int (arc4random_uniform(3))
let firstCardString:String = self.cardNamesArray[firstRandomNumber]
self.FirstCardImageView.image = UIImage(named: firstCardString)
Generates a random card for the second Array
SecondRandomNumber = Int (arc4random_uniform(3))
let SecondCardString:String = self.cardNamesArray2[SecondRandomNumber]
self.SecondCardImageView.image = UIImage(named: SecondCardString)
If they match player score 1 point
#IBAction func SnapButtonTapped(sender: UIButton) {
if firstRandomNumber == SecondRandomNumber {
print("index match")
self.playerScore += 1
self.playerScoreLabel.text = String(self.playerScore
}
Why don't you try to remove images from an Array itself. Once the random number matches, you can do that!
if firstRandomNumber == SecondRandomNumber {
print("index match")
self.playerScore += 1
self.playerScoreLabel.text = String(self.playerScore
cardNamesArray.removeAtIndex(firstRandomNumber)
cardNamesArray2.removeAtIndex(SecondRandomNumber)
if cardNamesArray.count == 0 && cardNamesArray2.count == 0{
print("User Won")
}else{
print("Continue Playing")
}
}
Crash Update:
Replace the below two lines in your code with mine
firstRandomNumber = Int (arc4random_uniform(UInt32(cardNamesArray.count)))
SecondRandomNumber = Int(arc4random_uniform(UInt32(cardNamesArray2.count)))
You may use a dictionary object in the Array.
Instead of
var cardNamesArray: [String] = ["sad", "sleepy","angry"]
You may use
Class CardItem{
var name = ""
var isDisplayed:Boolean?
}
And now
var cardNamesArray: [CardItem] = [CardItem(name:"sad",isDisplayed:false), CardItem(name:"sleepy",isDisplayed:false),CardItem(name:"angry",isDisplayed:false)]
Here is your random chunk:
SecondRandomNumber = Int (arc4random_uniform(3))
var uniqueItem = self.cardNamesArray2[SecondRandomNumber]
let SecondCardString:String = uniqueItem.name
self.SecondCardImageView.image = UIImage(named: SecondCardString)
uniqueItem.isDisplayed = true
So when you next time generate random number just check item's isDisplayed property.

set unique images in leftcalloutaccessoryview using for loop array in annotation map swift

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...

Resources