All posts by admin

UIStackView programmatically

demo

This project demonstrates how to:

– Create a UIStackView
– add uiviews to it
– add constraints to the uiviews
– make each uiview appear and disappear

stackview_row_result

http://angelolloqui.com/blog/36-Oddities-of-UIStackView
https://developer.apple.com/documentation/uikit/uiview/1622572-translatesautoresizingmaskintoco

Creating a constraint

Say you want to create a constraint. That constraints sits on constraint creation conveniences such as heightAnchor, widthAnchor, topAnchor, leftAnchor, etc. Any property that you can create a constraint on, that property will have an anchor you can access, and thus, create constraints from.

In our case, we want to to set a constraint to our height. Thus there is a heightAnchor. Access that property to create a constraint.

translatesAutoresizingMaskIntoConstraints

From the doc: If you want to use Auto Layout to dynamically calculate the size and position of your view, you must set this property to false, and then provide a non ambiguous, nonconflicting set of constraints for the view.

By default, the property is set to true for any view you programmatically create.

If you add views in Interface Builder, the system automatically sets this property to false.

Resolving Constraint conflicts using priority

Thus, later on we’ll be hiding our viewA. However there is a constraint on viewA that says its height has to be 120, as stated earlier. In this case, we’ll get a constraint conflict in the log console, because setting aView’s isHidden to true, makes its height to 0. This is a constraint conflict with 120.

Thus, in order to fix this, we need to lower the priority of our 120 height constraint so that when viewA’s height changes to 0 (due to it being hidden), it will see that the 120 height constraint’s priority is lower. This is because any new height constraints has a default priority of 1000. Since 120 has a lower priority, then the constraints engine will allow 0 (which defaults to highest priority of 1000) to be valid.

Full Source

Table within a table

table within a table

UITableViewDataSource’s cellForRowAtIndexPath

For a certain row, use your custom cell that has the tableview.

UITableViewDelegate’s heightForRowAtIndexPath

Make sure your table view delegate method heightForRowAtIndexPath is appropriate so people can see your custom cell.

The cell that contains the inner table

Create your tableview with its associated data array, then add it to the cell’s view hierarchy.

Table row animation

Assuming you have basic table with data set up, this is how you do row animations on it.

To remove a row from the end

To add a row to the end

To reload all sections in a table

Move a row

Design pattern in ViewController, delegate, dataSource

ViewController.h

ViewController.m

The concept of delegate is that we can delegate messages to another object, as long as that object conforms to the delegate.
Once an object conforms to a delegate, it just simply needs to implement the delegate methods and that’s it.

Hence in our example, everything starts at tableView. tableView has 2 delegates:

  • UITableViewDelegate
  • UITableViewDataSource

design-patter-viewcontroller-delegate-datasource

Our ViewController class matches up with the ViewController box in the image. Then notice its 2 delegates coming out of it.

One is called “delegate”.
The other is called “dataSource”.

In code, looks like this:

Those delegates must point to objects that conforms to them.
Therefore, we then have object TestDelegate that conforms to UITableViewDelegate, which means it implements UITableViewDelegate’s method(s).
Hence the “delegate” delegate can point to it.

Same thing for UITableViewDataSource’s method(s). Hence the “dataSource” delegate can point to it.

TestDataSource.h

TestDataSource conforms to the UITableViewDataSource,
so that TestViewController’s tableView’s dataSource delegate can point to it.

In the DataSource object, we have a data structure that represent the data we are going to represent on the table.

Initializing the cell object for data source’s cellForRowAtIndexPath

Naturally, when we implement cellForRowAtIndexPath in the data source, we ask the tableView to dequeue a reusable cell for us. Then simply
configure the cell with an “item” object. The reason for this is that we don’t want to initialize an cell object by using multiple parameters and pass lots of data into it.

Rather, we create a configureWithItem that takes in an object type called say testItem. This is how we pass large amount of data into the cell.

Hence in your custom cell class, do something like this:

TestCell

In your data source object, you have the item objects in a structure array. Using the row index, pluck the items from the array and initialize your cell objects with it.

TestDelegate

Say, in your delegate, you need to access the data that is being displayed on your table.

For example, you need to return 0 for the height on index 2’s row depending on index 2’s data.
So how do you get that data?

The concept is to access the tableView’s dataSource. Only the viewController has the reference to the tableView.
Thus that is why we have a reference to the viewController as a property, and initialized it via dependency injection like so:

Now that you have reference to testNowController, you can then get the data source like this:

Then all you need to do is access the items array in the dataSource, and you can get the data from the row:

Make sure your return is id, because the array contains different kind of “item” objects. i.e.

  • TestAItem
  • TestBItem
  • TestCItem

Now you can access the item object for that index. Check for a property in the item. Then return the height accordingly.

Static methods vs class methods

https://stackoverflow.com/questions/29636633/static-vs-class-functions-variables-in-swift-classes

static and class both associate a method with a class, rather than an instance of a class.

The difference is that subclasses can override class methods; they cannot override static methods.

cannot_override_static_method

Cannot override final functions

cannot_override_final

Finally, you can finalize your override like so:

Should IBOutlet be weak or strong?

https://stackoverflow.com/questions/7678469/should-iboutlets-be-strong-or-weak-under-arc/7729141#7729141

…the outlets to subviews of the view controller’s view can be weak, because these subviews are already strongly owned by the top-level object of the nib file.

However, when an Outlet is defined as a weak pointer and the pointer is set, ARC calls the runtime function:

This adds the pointer (object) to a table using the object value as a key. This table is referred to as the weak table. ARC uses this table to store all the weak pointers of your application. Now, when the object value is deallocated, ARC will iterate over the weak table and set the weak reference to nil.

Alternatively, ARC can call:

Then, the object is unregistered and objc_destroyWeak calls again:

This book-keeping associated with a weak reference can take 2–3 times longer over the release of a strong reference. So, a weak reference introduces an overhead for the runtime that you can avoid by simply defining outlets as strong.

weak references

https://softwareengineering.stackexchange.com/questions/229287/what-use-is-a-non-zeroing-weak-reference

weak reference – a reference that DOES NOT affect the reference count. Simply put, a weak reference is a reference (pointer, in Objective-C land) to an object which does not participate in keeping that object alive.

Weak references are useful for things like avoiding retain cycles, but their utility is limited due to their inherent danger. With a plain weak reference in Objective-C, when the target object is destroyed, you’re left with a dangling pointer. (your weak reference points to trash content) If your code tries to use that pointer, it will crash or worse.

Use unsafe__unretained to create non-zeroing weak pointers in order to clarify this:

or

An unsafe reference is similar to a weak reference in that it doesn’t keep its related object alive, but it won’t be set to nil if the destination object is deallocated. This means that you’ll be left with a dangling pointer to the memory originally occupied by the now deallocated object, hence the term “unsafe.” Sending a message to a dangling pointer will result in a crash.

Zeroing weak references (weak references are only available in Mac OS X ≥ 10.7 and iOS ≥ 5) eliminate this danger. They work just like a regular unsafe unretained reference, except that when the target object is destroyed, they automatically become nil. At any time you access an object through a zeroing weak reference, you’re guaranteed to either access a valid, live object, or get nil. As long as your code can handle nil, then you’re perfectly safe.

You can just declare any instance variable like so:

And it’s automatically a zeroing weak reference.

strong reference – a reference that DOES affect the reference count

where to remove observer in swift

https://stackoverflow.com/questions/28689989/where-to-remove-observer-for-nsnotification-in-swift/40339926#40339926
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Deinitialization.html

Swift automatically deallocates your instances when they are no longer needed, to free up resources. Deinitializers are called automatically, just before instance deallocation takes place. You are not allowed to call a deinitializer yourself.

deinitializion in class hierarchy

Superclass deinitializers are inherited by their subclasses, and the superclass deinitializer (parent) is called automatically at the end of a subclass deinitializer (child) implementation. Hence, the lowest level (youngest kids) subclass calls their deinit. Then their parents. Then the parent’s parents…and so on.

Also, superclass deinitializers are always called, even if a subclass does not provide its own deinitializer.

As of iOS 9

As of iOS 9 (and OS X 10.11), you don’t need to remove observers yourself, if you’re not using block based observers though.

The system will do it for you, since it uses zeroing-weak references for observers, where it can.

In detail:
https://useyourloaf.com/blog/unregistering-nsnotificationcenter-observers-in-ios-9/

Using iOS 9 or later the Foundation framework release notes contain some good news:

In OS X 10.11 and iOS 9.0 NSNotificationCenter and NSDistributedNotificationCenter will no longer send notifications to registered observers that may be deallocated.
The notification center now keeps a zeroing reference to the observer:

If the observer is able to be stored as a zeroing-weak reference the underlying storage will store the observer as a zeroing weak reference, alternatively if the object cannot be stored weakly (i.e. it has a custom retain/release mechanism that would prevent the runtime from being able to store the object weakly) it will store the object as a non-weak zeroing reference.
So the next time the notification center wants to send a notification to the observer it can detect that it no longer exists and remove the observer for us:

This means that observers are not required to un-register in their deallocation method. The next notification that would be routed to that observer will detect the zeroed reference and automatically un-register the observer.

Note that this does not apply if you are using a block based observer:

Block based observers via the -[NSNotificationCenter addObserverForName:object:queue:usingBlock] method still need to be un-registered when no longer in use since the system still holds a strong reference to these observers.