Why use Virtual (C++)

ref – https://stackoverflow.com/questions/2391679/why-do-we-need-virtual-functions-in-c?rq=1

Simple Over-riding

Without “virtual” you get “early binding”. Which implementation of the method is used gets
decided at compile time based on the type of the pointer that you call through.

OUTPUT:

Constructing Shape
Constructing Circle

Constructing Shape

SHAPE: Draw function
SHAPE: Draw function

Using Virtual

OUTPUT:

Constructing Shape
Constructing Circle

Constructing Shape

SHAPE: Draw function
Circle: draw function

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

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.

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

loading and showing images for Tables and Collections in swift

https://github.com/DigitalLeaves/FlawlessTablesAndCollectionViews
https://digitalleaves.com/blog/2016/02/flawless-uicollectionviews-and-uitableviews/
https://medium.com/capital-one-developers/smooth-scrolling-in-uitableview-and-uicollectionview-a012045d77f

Image flashes demo (The problem)
no flashes demo (The solution)

First, some background

tableView:cellForRowAtIndexPath: and collectionView:cellForItemAtIndexPath: are called whenever a new cell has to be displayed

The cells have an NSIndexPath[section-row] to identify its position.
In order to get the NSIndexPath of the cell, use

There is an array that stores the data to be displayed for the cells.

data_table

Cells, unlike data in the array, are re-used for efficiency. Thus, they do not stay in place. When a cell with data is about to be displayed, cells are dequeued ( or allocated when there is no cells ). The table will assign the current IndexPath to it, then set data onto it.

data_cell_table

In detail, the cells are kept in a pool where they are dequeued and served as they are needed.
When you ask for a cell with dequeueCellWithReuseIdentifier: a new one is created if and only if there’s no previous created cell that can be served.

Objective C version

In objective C, as you can see, we first ask the pool to return us a cell to use.
If its nil, which means the pool does not have spare ones, we need to allocate and create our own.
Once created, we can start settings it properties, and then return it to the class to be displayed.

Swift version

In swift, it combines the re-use or creating a new one in one method call of dequeueReusableCell.

Example

So, let us go ahead and see how it all starts out. When the table or collection view first start out, it sees that the the visible rows needs to be displayed.
First, it looks at the first row at index (section 0, row 0), and that it needs to display that cell.

It goes into delegate method cellForRow and tries to dequeue a cell. Because we are just starting out, our cell pool will be empty. Thus, get a new freshly allocated cell for us to use. We assign its display properties (namely, text, color, etc). In our case we simply assign the text property to something. Say, a string “one”.

display_cell_1-4

It then goes to the second row at index (section 0, row 1) and does the same thing. It will see that the cell pool is empty, and thus creates a new cell. We assign its display properties, and give it a strong “two”.

This applies for the rest of the cells that needs to be drawn on the table. Say if 8 cells are showing, usually table will allocate a few more cells, say 10. Take note that even though cells 9 and 10 are allocated, its indexPath will be nil because it is not shown by the table yet Once they are shown, their indexPath will be assigned an IndexPath.

Scrolling up, reusing those cells

At this point, we have successfully created table view cells, set their properties, and have displayed the data in the table.

The cell pool is still empty because we are currently using all of the cells. In other words, they are on display.

Now, the user uses their finger and swipes up. The whole table scrolls up one page.

swipe_up_recollect_cells

At this point, the first row at index (section 0, row 0), disappears off the screen. The cell object representing that row gets queued into the cell pool.
then the second row at index (section 0, row 1), disappears off the screen. It also gets queued into the cell pool…
As each on display cell disappears off screen, they get “re-collected” into the cell pool.

But! As each row disappears, new rows from the bottom appears right!?

We need to make sure they are drawn. So at this point, say, (section 0, row 4) starts to appear and it needs display.

It runs through delegate method cellForRow for (section 0, row 4) and tries to dequeue a cell.

It gets a cell object that (section 0, row 1) was previously using.
(section 0, row 1) have disappeared off screen and is not using its cell anymore. It has returned its cell back to the cell pool.

Take note that when the cell (which was previously used by row 0) is dequeued for (section 0, row 4), the tableView will changes the cell’s indexPath to (0,4). Thus, this signifies that this cell now represents for tableView’s section 0, row 4 now.

Hence the cell variable we get back is a valid object with our designated IndexPath of (0, 4)

dequeue_cells

Even though the cell’s IndexPath now is (0,4), its data has not been “cleaned” or “zeroed”, so it has the same configuration it had. In other words, that cell’s property text still has the previous string in it. And thus, as we dequeue that cell object for row 4, we over-write the text property with whatever row 4’s string is.

Then we properly return the cell object.

Note that the disappearing and appearing of the cells are determined by the TableView or Collection class. It may enqueue a bunch of disappearing cells first into the cell pool, then allow appearing cells to dequeue them. Or they may simply do it one by one.

The Problem

problem_1

1) When the first cell is loaded, it uses dequeueReusableCellWithIdentifier and gets a fresh cell object with address 0x…ffaabb.

2) It then uses the singleton ImageManager and starts doing a async download operation for image 1.

3) The user then swipes up. This makes the cell go out of display, and thus, the cell objects gets put into the cell pool, with its indexPath assigned to nil.

4) As the first row disappears, the 4th row appears, it uses dequeueReusableCellWithIdentifier cell and gets the cell object 0x…ffaabb from the cell pool. This cell was JUST used by row 1.

5) At this point, image 1 download progresses to 50%.

6) Due to 4) with its cell visible, it starts another async image download operation in singleton ImageManager. Image 4’s download progresses to 10%.

problem_2

7) With row 4 fully visible, it now has the cell object, and is downlading Image 4.

8) Image 1 finishes downloading.

9) Our closure in the cellForRow method points to the cell 0x…ffaabb. It then assigns cell 0x…ffaabb’s imageView.image to image1.

10) Now, for a split second, the image on row 4 is of image1.

11) Then a second later, image 4 finishes downloading, and thus in the same manager as 9), the closure code from cellForRow assigns 0x…ffaabb’s imageView.image to image 4.

12) Even though row 4 now correctly depicts image4 as intended, steps 9) to 11) creates a flash of of image 1 switching to image 4. The user can see it, depending on how slow the download speed is, and thus, is the problem we’re trying to solve.

Async Operations and when they complete

So, instead of doing instantaneous data assignments, we need to do async operations that may take a few seconds. Then after a certain amount of seconds is over, it comes back and updates our UI.

1) cellForRow hits dequeue cell and gets cell 0x…9aa00

2) Each row of the table matches up to the index of the URL array that gives us a string URL to download an image. cellForRow’s indexPath provides the index and we use that index to get the url from the data array.

we will be using this imageURL and use the Downloader singleton to download that image

3) The Downloader singleton uses the url and literally downloads the image. When its done, it hits up a closure to update the table UI

4) This here is the most important part. Once the download is done. It hits a closure. The closure references
the cell (that was dequeued for this table row), and the table IndexPath.

async_operation_tableview

It references the cell because we want to see which indexPath it is representing

It references the table IndexPath to know which row index was assigned to this operation.

Code is below:

Now in normal circumstances, the cell dequeued for say table row 11 has IndexPath [0, 11]. Table view IndexPath is [0, 11].

The Downloader finishes downloading the image, puts it in cache, and then calls our closure for completion.
It sees that IndexPath of the cell that’s we’re referencing is valid and is [0, 11]. This means as far as the cell is concerned, it is on display for row 11.
(If the IndexPath is nil, it means even though the cell is alive, it is not used by any table rows and not on display yet)

Furthermore, the indexPath of the table is [0, 11]. This means we’re currently processing for that row. Hence, due to:

1) cell’s IndexPath is representing and on display for row 11
2) cellForRow delegate method is called for table row 11

we can safely assign the downloaded image onto this cell.

Start download, cell scrolls off screen, download finishes

Let’s say we’re on row 11 and it starts to download an image.

It gets an URL from data[11]
Uses that URL and starts downloading image 11.

Then all of a sudden, the user scrolls row 11 out of view.

cell_scroll_off_screen

At this point 2 things happen:

1) cell for row 11’s indexPath gets set to nil because it is not on display anymore
2) row 15 appears, and dequeues a cell for usage.

1)

the download for image 11 completes! It runs to the closure. Notice 2 things. The closure references 2 important things:

– the cell that just before represented row 11. Its IndexPath is now nil because it is not only display anymore.
– the index of the cellForRow that is calling this closure (11)

We do a comparison and see that nil != 11, thus we don’t assign image 11 to cell’s imageView.

2)

On the other hand, row 15 appeared and dequeues a cell. It starts downloading the image, the image finishes and hits the closure. The closure references 2 things:

– the cell with IndexPath [0, 15] because it is visible
– the index of the cellForRow that is calling this closure (15)

We do a comparison and see that 15 == 15. Thus, we assign the JUST downloaded image for cell with IndexPath [0, 15].

Not visible offscreen cell gets taken by a row that is now visible

two_rows_use_one_cell

There is another situation where when we scroll off screen, the cell for index 11 (0x…ff1000) nows has indexPath of nil.

The downloader for image 11 is going on.

Row 15 appears on screen. It gets dequeued the cell (0x…ff1000) that was previously used by row 11. This is because row 11 disappeared and not using the cell anymore. Then, cellForRow at index 15 starts downloading image 15.

Hence cell 0x…ff1000 now has IndexPath of 15 because it is representing visible row 15.

downloader for image 11 finishes, and runs its closure. It references 0x…ff1000, but wait, the IndexPath for that is now [0, 15]!!
The index of the cellForRow that is calling this closure is 11. Thus, 15 != 11, and we do not assign image 11 to this cell.

image 15 finishes downloading, and runs its closure. It references 0x…ff1000 and the IndexPath for it is [0, 15].
The index of the cellForRow that is calling this closure is 15. Thus 15 == 15 is valid, and it goes ahead and assigns image 15 to
the cell’s imageView.image.

After everything has been downloaded

After everything is downloaded, all images should be instantaneously retrieved from the dictionary cache (url: Image). Once it gets the image, it would use the main queue to update our table.

In your cellForRowAt, the cellIndex and tableIndex check should succeed much more now because there is no more delay. The image retrieval is instantaneous and then calls the closure right away.

Separate Delegate and DataSource of UITableView from your ViewController

Step 1 demo – simple table
step 2 demo – pull out the data source
step 3 demo – pull out table view delegates

Step 1

Step 2 – pulling out the Data Source

In order to declare a data source, we first create an object that houses the data to represent the rows of data in your table view. Declare the protocol of UITableViewDataSource. This is so that your class conforms to it. And other delegates can then safely point to your object.

In the implementation, declare your data container, such as an array of strings.
Initialize your array in the initializer.

Then, in order satisfy the protocol that we conformed to (UITableViewDataSource), make sure you implement its needed methods.
Specifically, we implement

Declare your Data class in ViewController, point dataSource to it

ViewController.m

We now declare our data class (which safely conforms to UITableViewDataSource )as a property.

Initialize the data object. Then we point the table view’s data source to it.

Now if you run it, all UITableViewDelegate delegate messages are sent to your MyData object.

Step 3 – Pulling out the UITableViewDelegate

Now we’re going to create a View object that takes care of all the UITableViewDelegate delegates.

We implement delegate methods:

We log which row is selected.

We also check what kind of cell it is. Then we do something unique according to the cell type.

Declare your MyView property. It should conform to protocol UITableViewDelegate.

ViewController.m

Then we instantiate it. Make sure your table view’s delegate points to the MyView object. Now all delegates sent from table view for its delegate functionality will be sent to your MyView object to be processed.

Notice that your ViewController is now nice and clean, with a clear separation of concern between data source delegates and tableview delegates.

create table cells using xib

https://medium.com/@musawiralishah/creating-custom-uitableviewcell-using-nib-xib-files-in-xcode-9bee5824e722#.lbixf1y87

New File > Empty Interface Builder
Then you’ll see the .xib file appear

create_xib

Click on the “right pane button” to make the Identity Inspector appear, because that’s where all the Interface Builder attributes are.
If the right pane button is not there, go to menu View > Utilities > Identity Inspector.

In the UI components section on the bottom, scroll through all of the UI components that you can drag and drop into the IB. When you get to “Table View Cell”, drag it into the empty space

drag_table_view_cell

Then drag a label across, and into the cell.
drag_in_label

Create a UITableViewCell source file. In order to connect source file to interface builder, first make sure our cell is selected. Then enter the existing class’s name into the “Custom Class” textfield of the Identity Inspector.

Click on the small arrow button to make sure the xib can detect and navigate to the correct source file. Once that’s done, double click your xib so it opens. Then open up the hierarchy of UI components and you can ctrl+drag the components into the registered source file.

xib_class_name

Next, we will create outlets for the text labels in our cell so we can set their values.

You will see the IB outlet in your code like so:

to the left of the code, in the region where you put your breakpoints, you’ll see a small circle. If you hover over that circle, you’ll see that the corresponding UI component in IB will light up.

xib_corresponding_ui

As you can see, both says noteLabel.