Monthly Archives: July 2017

Pointing delegate to where the delegate implementation is

Most of the time, the delegate implementation is at the current source file where the delegate and its owning object is created.

But sometimes its not.

For example, say we have a UIView called caliGuestView. We want to set up a popover control in that class.

There is a custom made popover control like so:

Due to subclassed UIView, we know to drag a UIView component into the xib, then put Popover in its custom class tab. Thus we now have the custom made control in our xib. Once that’s done, we ctrl drag it into our source file and its ready to go.

CaliGuestView.swift

CaliGuestView.swift

Initially we think, ok, we get the delegate to point here in the CaliGuestView class. Then we implement the delegate methods in this class.
BUT! what if we have delegate functionality implemented elsewhere (like MyCustomCell.m). How do we get the delegate to point where the implementation is?

1) DO NOT ASSIGN the delegate here (in CailGuestView). Simply initialize it as is.

CaliGuestView.swift

2) make sure MyCustomCell’s delegate implementation is set

MyCustomCell.m

3) let MyCustomCell’s instance of this class point to self

MyCustomCell owns the CaliGuestView, and thus can simply access its delegate. Then point that delegate to self.

MyCustomCell.m

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.