Swift - Modifying a variable with the variable name stored in a variable - swift

The title of this question is most probably confusing but I have no idea what to name this question. I am writing a program in swift and I want to modify a property of an object (in this case a UIImageView) but I'm not sure of which object I'm going to modify, I only know the type.
An example of what I'm talking about is shown below:
Inside the ViewController class
#IBOutlet weak var LeftImage: UIImageView!
#IBOutlet weak var RightImage: UIImageView!
// A function to change the image inside a UIImageView
func ChangeImage(imageViewLocation: UIImageView, newImage: String) {
// Change the image
self.imageViewLocation.image = UIImage(named: newImage))
}
// Call the function
ChangeImage(LeftImage, "smileyFace")
Can this be done?

Related

why do we need to foreUnwrap the dataType while creating an object? Swift 5

whenever I go to internet or check projects on online while creating any object in ViewController class I see an exclamation mark(!) at end of data type why is that? for example:#IBOutlet weak var Label:UILabel!
so why is that '!' mark or why are we force unwrapping it?
And also when I remove it , it gives an error , we can also write like this #IBOutlet weak var Label=UILabel()
so why don't we use this?
You need to understand the things step by step to get an answer.
#IBOutlet: This is a property wrapper that tells Xcode to connect an element on the storyboard with the one in .swift file.
The ! mark: This force-unwrap thing is recommended because when the .swift file needs the instance, it's sure to find the connected element in storyboard. We can also write #IBOutlet weak var Label: UILabel? In this case the instance Label would be optional.
#IBOutlet weak var Label=UILabel(): In this case the instance Label's value is overridden with UILabel() immediately after initialization. The #IBOutlet weak var Label! and Label after Label = UILabel() are not the same instances.
#IBOutlet weak var label: UILabel is equivalent of writing var label: UILabel. Therefore the i-val does not have an initial value and Swift does not allow that. In Swift either you have to assign a value to a variable or make it optional/unwrapped to explicitly deal with nil values. And also when you unwrap the instance with #IBOutlet, you can use it with ? later on like label?.text = "Some text".
So, we are forced to use ! or ? for an outlet to explicitly make the variable optional as in for other variable declarations. And we don't use = UILabel() after declaration because it overrides the instance created from the Storyboard (initialized with an NSCoder/Coder from the nib).

How can I create a function for multiple labels in a stack?

I have 3 labels and I want to generate random numbers for each of them. I use GKRandomSource class in function, thats ok. The problem is, if I want to have much more labels (ie. 30) and all with same action, I need to reference all labels one by one to IBAction, I need to state all labels one by one in func code… I’ve been searching for a shorter way, maybe put them all in 3 stacks (10 labels for each stacks) and trigger, but I got nothing. I tried outlet collections (as we use in UIButtons) but it doesn’t let me to change label text.
How can I use a function for multiple labels with no-repeat?
Example;
let allNumbers = [Int](1...99)
var shuffledNum = [Int]()
#IBOutlet weak var labelOne: UILabel!
#IBOutlet weak var labelTwo: UILabel!
#IBOutlet weak var labelThree: UILabel!
func generateNumbers() {
shuffledNum = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: allNumbers) as! [Int]
let threeNumbers = shuffledNum.prefix(3).sorted()
labelOne.text = String(threeNumbers[0])
labelTwo.text = String(threeNumbers[1])
labelThree.text = String(threeNumbers[2])
}
you can make the array of UILabel's and put all the outlets in the same array then you can use for loop to do operations on each of them.
for example:
#IBOutlet var formLabels: [UILabel]!
and can do as:
formLabels.forEach { label in
label.text = ""//put your random number function here
}
see its working after adding both outlets I have also shown the connection in the storyboard the connection exists

How to add a custom uiview to a view controller programmatically SWIFT

I am trying to add a custom view programmatically to my view controller. I used this snippet of code with no success of it appearing in front of my main view controller.
var DynamicView = CustomFilter()
DynamicView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addSubview(DynamicView)
CustomFilter Class:
import UIKit
class CustomFilter:
UIView {
#IBOutlet weak var party: UIButton!
#IBOutlet weak var outdoors: UIButton!
#IBOutlet weak var sports: UIButton!
#IBOutlet weak var diner: UIButton!
#IBOutlet weak var music: UIButton!
#IBOutlet weak var gaming: UIButton!
}
The custom filter is connected to a xib file.
Xib File:
Is there a possibility that the custom view maybe out of placed? I'm not sure what I'm doing wrong.
In order to use a view we designed in a xib, we most load from the xib.
if
let bundle = NSBundle(forClass: CustomFilter.self),
let nib = bundle.loadNibNamed("<#Xib File Name#>", owner: self, options: nil),
let dynamicView = nib.first as? CustomFilter {
self.view.addSubview(dynamicView)
}
An alternative approach would be to write your CustomFilter's init to load the view from the xib itself.
More clearly, the problem you're having is that none of your CustomFilter's initializers are going to care about the xib file you made unless you write them and tell them to care about it. Your current code is returning a 0x0 view with probably a white or clear background. If you modified your current code to set the CustomFilter's frame to something other than 0x0 size and set the background color to something like UIColor.greenColor(), you'd see it clear as day.
Also, you could use Xcode's visual debugger to find it.
It's probably zero height and zero width, and may be off-screen also.
You need to give it height and width constraints and x and y position constraints.
You should probably also use CustomFilter(frame: someFrameRect), since as I recall initWithFrame is the designated initializer for UIView.
As an aside, variable names should start with a lower-case letter, so DynamicView should be dynamicView

Swift: Generate Identifier for Variable

I have a large list of NSButtons (80+) that I assign to an array. I've used a numbering scheme to name them and I'd like to generate the identifiers for them instead of calling them directly by name one at a time.
#IBOutlet weak var button120: NSButton!
#IBOutlet weak var button121: NSButton!
var buttons [NSButton]()
Currently (in ViewDidLoad()) I'm doing the equivalent of:
buttons = [ button120, button121 ]
I'd prefer to do something like:
for index in 120...121 {
buttons.append("button\(index)".toIdentifier)
}
Can this be done in Swift?
This might be an easier solution, view is the parent view of the buttons
let buttons = view.subviews.filter { $0 is NSButton}

Swift - Using UIGestureRecognizer with UIImage

class ViewController: UIViewController {
#IBOutlet weak var grayView: UIView!
#IBOutlet weak var lightGrayView: UIView!
#IBOutlet weak var smileyFaceIMG: UIImageView!
#IBAction func smileyMove(sender: UIPanGestureRecognizer) {
var point = sender.locationInView(view)
smileyFaceIMG.center = point
if CGRectContainsPoint(lightGrayView.frame, smileyFaceIMG.center) {
smileyFaceIMG.image = UIImage(named: "Smiley_Face.jpg")
}
}
}
I have set up a UIImage which is supposed to change the image after I go over another UIView. This method seems to work with a regular UIView, however not with UIImage. How can I move the UIImage with the UIPanGestureRecognizer.
I learned what my mistake was. I needed to create a regular UIView, and then drag the UIImgView onto it. Then replace the code from the UIImageView to the UIView. Now everything works properly.