Swift - access array from another class - ios

In my project I have an array where the user can append elements. My problem right now is that I have another class with a tableView where I want to display all the elements dynamically so if the user adds and element to the array it is also in my tableView.
Class A
var wishListTitlesArray: [String] = [String]()
Class B
var dropDownOptions = [String]() // TableView data -> here I would like to access `wishListTitlesArray`
Update
So thanks for the comments so far, I got the main problem I had but I am still struggling.
My setup:
I create my dropDownButton (which contain a dropDownView) in my ViewController-Class where I also have my var wishListTitlesArray.
I tried dropDownButton.dropView.dropDownOptions = wishListTitlesArray . However that does not do the full job.
#objc func addWishButtonTapped(notification : Notification){
popUpView.popUpTextField.text = ""
self.popUpView.popUpTextField.becomeFirstResponder()
view.addSubview(visualEffectView)
view.addSubview(popUpView)
view.addSubview(wishButton)
self.view.addSubview(dropDownButton)
// constrain blurrEffectView
visualEffectView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
visualEffectView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
visualEffectView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
visualEffectView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
// constrain popUpView
popUpView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
popUpView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -50).isActive = true
popUpView.heightAnchor.constraint(equalToConstant: 230).isActive = true
popUpView.widthAnchor.constraint(equalToConstant: view.frame.width - 85).isActive = true
// constrain wishButton
wishButton.centerXAnchor.constraint(equalTo: popUpView.centerXAnchor).isActive = true
wishButton.centerYAnchor.constraint(equalTo: popUpView.centerYAnchor, constant: 70).isActive = true
wishButton.heightAnchor.constraint(equalToConstant: 72).isActive = true
wishButton.widthAnchor.constraint(equalToConstant: 72).isActive = true
// constrain DropDownButton
dropDownButton.centerXAnchor.constraint(equalTo: self.popUpView.centerXAnchor).isActive = true
dropDownButton.centerYAnchor.constraint(equalTo: self.popUpView.centerYAnchor).isActive = true
dropDownButton.widthAnchor.constraint(equalToConstant: 100).isActive = true
dropDownButton.heightAnchor.constraint(equalToConstant: 40).isActive = true
// set the drop down menu's options
dropDownButton.dropView.dropDownOptions = wishListTitlesArray
self.view.bringSubviewToFront(visualEffectView)
self.view.bringSubviewToFront(popUpView)
self.view.bringSubviewToFront(wishButton)
self.view.bringSubviewToFront(dropDownButton)
self.view.bringSubviewToFront(dropDownButton.dropView)
This is where the user can add an element to the wishListTitlesArray:
if let txt = listNameTextfield.text {
self.newListTextfield.resignFirstResponder()
// append user-entered text to the data array
self.wishListTitlesArray.append(txt)
self.wishListImagesArray.append(self.image!)
// DonMag3 - append new empty wish array
self.userWishListData.append([Wish]())
let theCustomWishlistView = createCustomWishlistView()
self.view.addSubview(theCustomWishlistView)
// constrain CustomWishlistView
theCustomWishlistView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 120.0).isActive = true
theCustomWishlistView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
theCustomWishlistView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 30.0).isActive = true
theCustomWishlistView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -30.0).isActive = true
theCustomWishlistView.wishlistImage.image = self.image
theCustomWishlistView.wishlistLabel.text = txt
theCustomWishlistView.transform = CGAffineTransform(translationX: 0, y: 1000)
self.view.bringSubviewToFront(containerView)
// reload the collection view
theCollectionView.reloadData()
theCollectionView.performBatchUpdates(nil, completion: {
(result) in
// scroll to make newly added row visible (if needed)
let i = self.theCollectionView.numberOfItems(inSection: 0) - 1
let idx = IndexPath(item: i, section: 0)
self.theCollectionView.scrollToItem(at: idx, at: .bottom, animated: true)
// close (hide) the "New List" view
self.closeButtonTappedNewList(nil)
})
and the problem right now is that if the user adds an element, dropDownOptions is not updating the data accordingly. So how can I access the updated list? Thanks for all the comments so far!

This is fairly straightforward OO programming. As somebody pointed out, you're dealing with instance variables and instances of classes, not classes.
An analogy:
Instances: If you want one instance of a class to get a value from an instance of another class, it's like having your Toyota car request the radio station presets from your friend's Honda and set your radio the same way.
Classes: The Toyota motor company decides they like the radio presets that Honda uses, so they read the radio station presets from the Honda company and the Toyota factory uses those settings for all new Toyotas.
In class A, make wishListTitlesArray public:
public var wishListTitlesArray: [String] = [String]()
Then, your Class B object will need a pointer to the Class A object. There are various ways to do that. Let's say you set up Class B to take a Class A object at init time:
Class B {
var myAObject: A
var dropDownOptions: [String]
init(aObject: A) {
myAObject = anObject
dropDownOptions = myAObject.wishListTitlesArray
}
//more code here
}

Related

Is this an iOS 14 UISplitViewController bug?

In my app, I want a three-column UISplitViewController. I create it like this:
let svc = UISplitViewController(style: .tripleColumn)
svc.preferredDisplayMode = .twoOverSecondary
svc.setViewController(TestViewController(), for: .primary)
svc.setViewController(TestViewController(), for: .supplementary)
svc.setViewController(TestViewController(), for: .secondary)
svc.primaryBackgroundStyle = .sidebar
This ViewController that I'm presenting is a really simple viewController. It doesn't do anything except, present a centered red square.
class TestViewController: UIViewController {
private var redView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
redView.backgroundColor = .red
redView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(redView)
redView.widthAnchor.constraint(equalToConstant: 30).isActive = true
redView.heightAnchor.constraint(equalToConstant: 30).isActive = true
redView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
redView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
}
}
Now, when I run this code, I get the following result.
As you can see, 2 of the 3 squares are off-center. Anyone know, what I'm doing wrong here? Or is this a known bug?
You should use "Safe Area" instead of "self.view" when setting to center.
The detail view here has a push-away effect. You just need to click on it and the primary view controller will hide, like below.

Find the generic type passed into a function

I have created a generic function that passes in, one specific type and another 'generic' type.
func initializeCategory<T: UIView> (category: Category, type: T) {
//Find which type 'type' is
//If type is of type, 'UIView' -> do something
//else if type is of type, 'Category' or another type -> Do something else
}
What I'm trying to do is find what type is passed in as a generic type in my function?
Is there a better way to create a generic function that can query the different types passed into it?
Or should I set it like this <T: Any>??
P.S Category is a subclass of UIView
Thanks
UPDATE
Essentially what I'm trying to accomplish is a generic constraint function.
Here is the constraints:
view.addSubview(categoryOne)
categoryOne.delegate = self
categoryOne.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16).isActive = true
categoryOne.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16).isActive = true
categoryOne.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16).isActive = true
categoryOne.heightConstraint = categoryOne.heightAnchor.constraint(equalToConstant: 40)
categoryOne.heightConstraint?.isActive = true
What I need is the ability to change the 'top Anchor' constraint. So if I pass in the type of UIView, it would be set as is = constraint(equalTo: view.safeAreaLayoutGuide.topAnchor etc
However if I pass in type of Category (which subclasses UIView), then I need to change the constraint(equalTo: category.bottomAnchor etc
-- I thought if have a generic function they querying which type is passed in, I could get a result.
Don't use type as an argument as it is a keyword. The following code works.
func initializeCategory<T: UIView> (category: Category, type1: T) {
let a = type(of :type1)
print(a)
}
or
switch type1 {
case is SKView:
print(1)
default:
print(2)
}
SOLVED
func initializeCategory (category: Category, type: UIView) {
view.addSubview(category)
category.delegate = self
if type == view {
category.topAnchor.constraint(equalTo: type.safeAreaLayoutGuide.topAnchor, constant: 16).isActive = true
} else {
category.topAnchor.constraint(equalTo: type.bottomAnchor, constant: 16).isActive = true
}
category.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16).isActive = true
category.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16).isActive = true
category.heightConstraint = category.heightAnchor.constraint(equalToConstant: 40)
category.heightConstraint?.isActive = true
}

Am I adding yet another, or changing, this constraint?

Say I do this ...
override func viewDidLoad() {
super.viewDidLoad()
view.heightAnchor.constraint(equalToConstant: 50).isActive = true
later, I do this ...
view.heightAnchor.constraint(equalToConstant: 51).isActive = true
am I a bad person?
Have I now redundantly added a second constraint (what happens to the first?)
Or does it know to change the first?
Or does something else happen? Am I making a leak?
What should I do, and in what way have I been bad, if any?
What's the correct thing to do here?
view.heightAnchor.constraint(equalToConstant: 50).isActive = true
later, I do this ...
view.heightAnchor.constraint(equalToConstant: 51).isActive = true
am I a bad person?
Yes, and if I'm not mistaken, the runtime will tell you so with a loud message in the console warning that you have unsatisfiable (conflicting) constraints. You have a constraint setting the height to 50 and another setting the height to 51 and both things cannot be true.
You didn't give enough code to be sure of what's going on in your case, but you can easily see that what I'm saying is correct, by making your view controller's code consist only of the following:
func delay(_ delay:Double, closure:#escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(v)
v.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
v.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
v.widthAnchor.constraint(equalToConstant: 100).isActive = true
v.heightAnchor.constraint(equalToConstant: 50).isActive = true
delay(3) {
v.heightAnchor.constraint(equalToConstant: 51).isActive = true
}
}
}
As you stipulated, we "later" add the 51 constraint — and as I said, the runtime squawks at that moment.
The correct procedure is to keep a reference to the original constraint
so that you can change its constant later. (Under more complex circumstances you could actually deactivate, i.e. remove, the first constraint before adding the second, but if all you plan to do is alter the constant, that's not necessary, as it is mutable.)

Programmatically adding multiple subviews with constraints throws exception

EnvironmentXcode-8Swift-3iOS-10
IntentThe germain intent is to get three subviews added to the main view, such that they appear sequentially adjacent starting from the top of the screen.There's more to the ultimate intent, but this is where I'm currently stuck.
Working CodeIf I'm just adding a single subview, it works with the following code (slightly abridged, line numbers added for reference):
01: class ViewController: UIViewController, UITextFieldDelegate {
02: var textMatte: UIView!
03: override func viewDidLoad() {
04: super.viewDidLoad()
05: setupTextfieldMatte(inView: view)
06: }
07: func setupTextfieldMatte(inView: UIView) {
08: textMatte = UIView()
09: textMatte.backgroundColor = UIColor.lightGray
10: textMatte.translatesAutoresizingMaskIntoConstraints = false
11: inView.addSubview(textMatte)
12: let tmGuide = textMatte.layoutMarginsGuide
13: let inGuide = inView.layoutMarginsGuide
14: tmGuide.topAnchor.constraint(equalTo: inGuide.topAnchor, constant: 40).isActive = true
15: tmGuide.leadingAnchor.constraint(equalTo: inGuide.leadingAnchor, constant: 20).isActive = true
16: tmGuide.trailingAnchor.constraint(equalTo: inGuide.trailingAnchor, constant: -20).isActive = true
17: tmGuide.heightAnchor.constraint(equalToConstant: 40).isActive = true
18: }
19: //... other code ...
20: }
Broken CodeI wanted to break-up the creation step from the constraint step, in order to do "batch" processing (and because there's more that needs to happen, as eventually these subviews will also have their own subviews...). Added relative line numbers for ease of further description and (hopefully) answers from you folks:
01: class ViewController: UIViewController, UITextFieldDelegate {
02: var mattes = [UIView()]
03: override func viewDidLoad() {
04: super.viewDidLoad()
05: for (index, title) in ["A", "B", "C"].enumerated() { // genericized for posting
06: let v = createView(idx: index)
07: mattes.append(v)
08: view.addSubview(v)
09: }
10: _ = mattes.popLast() //from testing/debugging found that there was an extraneous entry in the array
11: addViewAnnotations(views: mattes, inView: self.view)
12: }
13: func createView(idx: Int) -> UIView {
14: let v = UIView()
15: v.backgroundColor = UIColor.lightGray
16: v.translatesAutoresizingMaskIntoConstraints = false
17: v.tag = idx
18: return v
19: }
20: func addViewAnnotations(views: [UIView], inView: UIView) {
21: let inGuide = inView.layoutMarginsGuide
22: for (index, v) in views.enumerated() {
23: let myGuide = v.layoutMarginsGuide
24: if index == 0 {
25: myGuide.topAnchor.constraint(equalTo: inGuide.topAnchor, constant: 40).isActive = true
*** //^^^ libc++abi.dylib: terminating with uncaught exception of type NSException
26: }
27: else {
28: myGuide.topAnchor.constraint(equalTo: views[index-1].layoutMarginsGuide.bottomAnchor, constant: 10).isActive = true
29: }
30: myGuide.leadingAnchor.constraint(equalTo: inGuide.leadingAnchor, constant: 20).isActive = true
31: myGuide.trailingAnchor.constraint(equalTo: inGuide.trailingAnchor, constant: -20).isActive = true
32: myGuide.heightAnchor.constraint(equalToConstant: 40).isActive = true
33: }
34: }
35: //... other code ...
36: }
The error occurs on line 25 (error message in comment below that line), verified with print statements above and below the line.There's no additional error/debugging information that I can seeI had expected that it might break on line 28, but 25 (in the "broken code") is identical to line 14 (in the working code)Note: If I put a try in from of the line, Xcode tells me: "No calls to throwing functions occur within 'try' expression"
I have a feeling that this is one of those stupid oversights that crop up so often when modifying code, but I just cannot seem to spot the source of the problem - so I'm hoping one of you can.
UPDATE 2016-10-16Based on my modification as described in the first comment I added, I played around with the code a bit more and found that the problem occurs only when trying to make [what is now] the last constraint active:
001: override func viewDidLoad() {
002: super.viewDidLoad()
003: for (index, title) in ["Small Blind", "Big Blind", "Ante"].enumerated() {
004: let v = createView(idx: index)
005: mattes.append(v)
006: view.addSubview(v)
007: let myGuide = v.layoutMarginsGuide
008: let inGuide = view.layoutMarginsGuide
009: myGuide.leadingAnchor.constraint(equalTo: inGuide.leadingAnchor, constant: 20 ).isActive = true
010: myGuide.trailingAnchor.constraint(equalTo: inGuide.trailingAnchor, constant: -20).isActive = true
011: myGuide.heightAnchor.constraint(equalToConstant: 40).isActive = true
012: if index == 0 {
013: myGuide.topAnchor.constraint(equalTo: inGuide.topAnchor, constant: 40).isActive = true
014: }
015: else {
016: let x = myGuide.topAnchor.constraint(equalTo: mattes[index-1].bottomAnchor, constant: 10)
017: x.isActive = true
//^^^ libc++abi.dylib: terminating with uncaught exception of type NSException
018: }
019: }
020: }
All the other constraints have no issues. It doesn't seem to matter if I use:mattes[index-1].bottomAnchormattes[index-1].layoutMarginsGuide.bottomAnchorThe first one evaluates to <NSLayoutYAxisAnchor:0x174076540 "UIView:0x100b0d380.bottom">, the second to <NSLayoutYAxisAnchor:0x174076c00 "UILayoutGuide:0x174191e00'UIViewLayoutMarginsGuide'.bottom"> (if that matters?)If I comment out line 017, the code runs, but while the first rectangle is in the correct location, the remaining two are not - they're flush against the top of the screen instead of below the top indicators.So - perhaps there's a better way to set them up?
What is the description of the exception? Be sure to add views to their superview (in the same view hierarchy) before adding the constraints. You can't create constraints between views that aren't both in the same hierarchy.
In your update, you're using index-1 as an index into the mattes array, that may be the cause of the exception the first time around.
I don't know if this is contributing to issues, but I don't create constraints from one view's layoutMarginsGuide to a superview's layoutMarginsGuide. Think of that guide as for the view and it's subviews. So the constraints would be from the subview itself (not its margin) to the superview's layoutMarginsGuide.
I think it was a combination of things that was causing the problem, but first let me present the working code and a couple of screen shots
001: class ViewController: UIViewController, UITextFieldDelegate {
002: var textfields: [UITextField] = []
003: var labels: [UILabel] = []
004: var mattes: [UIView] = []
005: override func viewDidLoad() {
006: super.viewDidLoad()
007: view.backgroundColor = UIColor.blue
008: for title in ["A", "B", "C"] {
009: let matte = setupMatte(inView: view)
010: let textfield = setupTextfield(inView: view, title: title)
011: let label = setupLabel(inView: view, title: title)
012: mattes.append(matte)
013: textfields.append(textfield)
014: labels.append(label)
015: }
016: addConstraints(inView: view) // could probably leave off parameter, but for now...
017: }
018: func setupMatte(inView: UIView) -> UIView {
019: let matte = UIView()
//...various view attribute configurations...
020: matte.translatesAutoresizingMaskIntoConstraints = false
021: inView.addSubview(matte)
022: return matte
023: }
024: func setupTextfield(inView: UIView, title: String) -> UITextField {
025: let textfield = UITextField()
//...various textfield attribute configurations...
026: textfield.translatesAutoresizingMaskIntoConstraints = false
027: inView.addSubview(textfield)
028: return textfield
029: }
030: func setupLabel(inView: UIView, title: String) -> UILabel {
031: let label = UILabel()
//...various label attribute configurations...
032: label.translatesAutoresizingMaskIntoConstraints = false
033: inView.addSubview(label)
034: return label
035: }
036: func addConstraints(inView: UIView) {
037: for (index, matte) in mattes.enumerated() {
038: let textfield = textfields[index]
039: let label = labels[index]
040: matte.leadingAnchor.constraint(equalTo: inView.leadingAnchor).isActive = true
041: matte.trailingAnchor.constraint(equalTo: inView.trailingAnchor).isActive = true
042: matte.heightAnchor.constraint(equalToConstant: 50).isActive = true
043: label.leadingAnchor.constraint(equalTo: matte.leadingAnchor, constant: 20).isActive = true
044: label.widthAnchor.constraint(equalToConstant: 150).isActive = true
045: textfield.leadingAnchor.constraint(equalTo: label.trailingAnchor, constant: 5).isActive = true
046: textfield.trailingAnchor.constraint(equalTo: matte.trailingAnchor, constant: -20).isActive = true
047: if index == 0 {
048: matte.topAnchor.constraint(equalTo: inView.topAnchor, constant: 20).isActive = true
049: }
050: else {
051: matte.topAnchor.constraint(equalTo: mattes[index - 1].bottomAnchor, constant: 5).isActive = true
052: }
053: textfield.centerYAnchor.constraint(equalTo: matte.centerYAnchor).isActive = true
054: label.centerYAnchor.constraint(equalTo: textfield.centerYAnchor).isActive = true
055: }
056: }
//... other code ...
057: }
Interestingly, while the image from the simulator correctly handles landscape mode, when I run it on my iPhone 6s - it doesn't rotate when I hold the phone in landscape mode - but I'm not too worried about that at this time, since the app I'm working on is only intended for portrait mode.
Now, the pieces that I think made a significant difference from my original code:
(Note: I don't know why, but for some reason I originally named the function for handling constraints "Annotations", this was fixed in my current working code)
BROKEN : var mattes = [UIView()]
WORKING: var mattes: [UIView] = []
I think the above may have been a significant difference
BROKEN : viewDidLoad function looped:
Created sub-view
Appended sub-view to mattes array
Called view.addSubview(v)
After loop:
Popped off last element of mattes array
Added annotations
WORKING: viewDidLoad function looped:
Created sub-view (matte)
The creation process called inView.addSubview(matte) (where inView is the same as view or self.view)
Appended sub-view to mattes array
After loop:
Added annotations
I think the difference in how mattes was defined eliminated the need to pop off the last (or any) element in the array before going to add the constraints
BROKEN : in addViewAnnotations I made constraints using the layoutMarginGuide of both the sub-view and [parent] view
v.layoutMarginGuide.topAnchor.constraint(equalTo: view.layoutMarginGuide.topAnchor, constant: 40).isActive = true
WORKING: in addConstraints I made the constraints directly from the sub-view and [parent] view
matte.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true
(Thanks to Jerry for pointing this out, I didn't understand the distinction and I don't think I fully fixed my code when I did my "UPDATE")
The above was probably the most significant difference

Swift: creating UI when function is called

I've got one of these Views here:
let placeContainerView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.whiteColor()
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.cornerRadius = 7
view.layer.masksToBounds = true
return view
}()
And I'm looking to create one next to it every time a function "createNewView()" is called.
let showFullPlaceContainerView = UITapGestureRecognizer(target: self, action: #selector(showFullPlaceContainerViewFunction))
placeContainerView.addGestureRecognizer(showFullPlaceContainerView)
That I want each of the placeContainerView's to respond to.
So I want a view to be generated and I'll give it certain values. And then when I call the function createNewView() I'll get a new view next to it that is exactly the same except with whatever new values I put in.
If you've got any ideas please let me know!
Thank you
EDIT:
The code below demonstrates how I want to setup the placeContainerView each time but I need them to be displayed so that the placeContainerView.topAnchor() is different each time.. How exactly does that work if it is kept in its own class and doesn't know how many times it has been created?
Also, as placeContainerView contains placeLabel and placeImageView do these have to be generated inside the new PlaceContainerViewClass as well?
func setupPlaceContainerView() {
placeContainerView.leftAnchor.constraintEqualToAnchor(view.leftAnchor, constant: -180).active = true
placeContainerView.topAnchor.constraintEqualToAnchor(view.topAnchor, constant: 80).active = true
placeContainerView.widthAnchor.constraintEqualToConstant(227).active = true
placeContainerView.heightAnchor.constraintEqualToConstant(45).active = true
placeContainerView.addSubview(placeLabel)
placeContainerView.addSubview(placeImageLabelSeparator)
placeContainerView.addSubview(placeImageView)
placeLabel.leftAnchor.constraintEqualToAnchor(placeContainerView.leftAnchor).active = true
placeLabel.topAnchor.constraintEqualToAnchor(placeContainerView.topAnchor).active = true
placeLabel.widthAnchor.constraintEqualToConstant(180).active = true
placeLabel.heightAnchor.constraintEqualToAnchor(placeContainerView.heightAnchor).active = true
placeImageLabelSeparator.leftAnchor.constraintEqualToAnchor(placeLabel.rightAnchor).active = true
placeImageLabelSeparator.topAnchor.constraintEqualToAnchor(placeContainerView.topAnchor).active = true
placeImageLabelSeparator.widthAnchor.constraintEqualToConstant(2).active = true
placeImageLabelSeparator.heightAnchor.constraintEqualToAnchor(placeContainerView.heightAnchor).active = true
placeImageView.leftAnchor.constraintEqualToAnchor(placeImageLabelSeparator.rightAnchor).active = true
placeImageView.topAnchor.constraintEqualToAnchor(placeContainerView.topAnchor).active = true
placeImageView.widthAnchor.constraintEqualToConstant(45).active = true
placeImageView.heightAnchor.constraintEqualToAnchor(placeContainerView.heightAnchor).active = true
As noted by #Paulw11, this task is simply done by creating a new class.
class placeContainerView:UIView {
var x:Double!
var y:Bool!
var z:UILabel!
var controller:UIViewController!
//If you want to pass specific values number, you can use convenience init method OR you can use the default init method they give you.
//previousLabelFrame:CGrect = CGRect() // I defaulted all these values to 0, make them whatevree u need. You would use the default one for the first Label you would make. Then after that, you would pass in the previous one made, to get the frame of it so you can add to the one after that.
convenience init(x:Double,y:Bool, z:UILabel, previousLabelFrame:CGRect = CGRect(x: 0, y:0, width:0, height:0), VC:UIViewController) {
self.x = x
self.y = y
self.z = z
self.controller = VC
let distance = self.controller.width*0.1 //Whatever u decide here
//You could just do CGRect(x:previousLabelFrame.maxX+distance, depeding on what you need.
self.frame = CGRect(x: previousLabelFrame.minX+distance, y:previousLabelFrame.minY, width: previousLabelFrame.width, height:previousLabelFrame.height)
}
}
Usage inside ViewController:
var views:[placeContainerView] = []
let view:placeContainerView = placeContainerView(10, true, UILabel(),views[views.count-1], self)
self.views.append(view)
//OR if this is the FIRST placeContainerView of the whole app, it will use the default values for the frame.
let view:placeContainerView = placeContainerView(10, true, UILabel(), self)
self.views.append(view)
Some odd example of how to use.
Then everytime they click a button, just make a new placeContainerView

Resources