Tuesday, March 20, 2018

UITableView using custom .xib files for table and cells.

Occasionally I find myself needing a UITableView that has been setup from a custom .xib (interface builder) file, rather than from within a Storyboard.  The process for setting up a UITableView within an xib is different to that for setting one within a Storyboard, mainly because you cannot use prototype cells and design your cells within the UITableView itself - the custom cell requires its own .xib file too.  Ive documented the process for setting up a UITableView in this way below.

First up, I assume you have a UIViewController that is within an .xib file.  If not, theres a guide to setting up a UIViewController within an xib here.  You can also use the below method for a UITableView within a storyboard - you just need to delete the UITableViewCell from within the UITableView first.


  • Drag in a new UITableView object into your UIViewController
  • Drag datasource and delegate outlets onto Files Owner
  • Drag an outlet connection for the UITableView into your UIViewController
  • Create a new .xib file to hold the custom cell
  • Delete any view in that file and add a new UITableViewCell object.
  • Add a new swift file to contain your custom cell UITableViewCell subclass, and define the basic class
  • Back in the custom cell .xib file, set the Custom Class of the UITableViewCell object to the sub-class you just defined.
  • Then in the same xib file, but this time on the Attributes Inspector rather than the Identity Inspector, set the Re-use Identifier to something memorable - I usually just use that class name again.
  • Now back in the main UIViewController swift that contains the UITableView,  add a line of code to register the custom nib you've just set up.  Somewhere on initialization is good, such as viewDidLoad.  Re-use identifier should match the 'RestorationId' property set in the cells custom xib file.  


  • Now add the basic stub functions for UITableViewDataSource.  You can see how the custom cell is dequeued in the code below. The identifier mentioned there is the one we set in the custom cell as 'RestorationId'.

  • Thats all the basic setup done.  From here you can add any UI elements you wish into the custom cell xib file, and drag the properties over to the swift file for your custom UITableViewCell class.  Then within the 'cellForRowAtIndexPath' you can set and populate those properties.

Tuesday, March 13, 2018

Social Network with Firebase 2 - Making a Post

Ive already outlined my database structure for my Firebase based social network.  Ive done the auth for new users, and Ive added each new user to an array at the root of my JSON database called Users.  Now for the first stage of allowing the user to create data : making posts.

As the database structure shows, my posts will also live in a 'posts' array at the root of the database structure.  Within that array, each post will have a unique key, which by the way consists mainly of a timestamp, which allows them to be easily sorted by date.  Within each key will live the post data, which consists most importantly of : id of the user that made the post, the date + time it was made, the text body of the post, longitude / latitude at which the post was made, and other things.  The gist of this blog post here is to simply describe how Firebase makes it easy for my app to add to the database.

Ive created a UIViewController for entering the post and an accompanying .xib file to contain the layout of it.  I didnt do the layout for this within a storyboard.  For reasons why and to see how to set up a UIViewController with an .xib, see here.

So assume that you have an interface of some kind that allows the user to enter text for the post body, which in my case includes a post title and post body text.  My social network is location based, so I'm using iOS location services to get the current GPS position of the users device so I can save lat and long data to this post too.  Incidentally, for simplicity - my JSON upload consists almost entirely of text elements.

So back to the point - what I basically want to do is to add this post to my posts array in the database.  First thing I need is a unique id for the post, which will be its key in the JSON array in the database.  To do this, i use a method called 'childByAutoId'.



So the ref property I made simply refers to the root of the database. My posts live in an array with key "posts" which is why its on the second line there, and following that I get my unique key for a new element in that array. Now I simply need to upload some JSON to that ref, containing the properties I want to store.

To do this, first Ive got my own local class which will represent the post data. In my case its called GZPost. It has properties like this :


I initialize it with a custom initializer that takes the unique key I have just made, which will be the posts 'id' locally (and its key in the JSON structure in Firebase).


Within that class I have a function called 'updateDictionary'.  All this does is convert my properties into a Dictionary of type [String : Any], which will be uploaded to the Database.  The func looks like this :


So as you can see, it is simply taking its own properties and turning them into a Dictionary of the type that I can upload to Firebase. One of the beauties of Firebase is that - that dictionary can contain any properties I like, and I never need to go into Firebase itself and change anything at the backend. Whatever I send is stored automatically, which frees up so much time for the developer. At any point I can just add an array or a property wherever I choose in the structure of the Dictionary that I send.

Point to note here also - you can see it has an 'Author' property. This contains the id of the user who made the post, and in the case where its me making the post, thats obviously my id. I have a local class called GZUser which contains my id so I can get that from there, or I can also query Firebase for the current users' Id, like this :


The final method I have on this GZPost class is called 'referencePathString'. All this does is return the path to this item in Firebase. It takes the local 'postId' property and adds it to 'posts' which is the key for the posts array in the database. It looks like this :


So thats all the parts of the puzzle - now I just put them all together to upload my new post to Firebase. Using those methods specified above, the upload code looks like this :


To test this out, you can go to your Firebase Console, click on Database on the left, and just watch the new post data appear in your posts Array online.

Next I'll be outlining how to observe an array reference such as the posts one there and displaying the data in a UITableView.

Wednesday, March 7, 2018

Social Network with Firebase 1 - Signing In, Creating User

Im currently tasked with building a social network using Firebase as a back-end.  Im pleasantly surprised by how usable and generally liberating Firebase is, allowing a solitary developer like me to create both front and back-ends without too much hassle.  I dont want to create a full tutorial here on creating a social network with Firebase.  But I can create an overview of the process with some code snippets here for anyone else looking to undertake something like this.

First of all Ive sketched out (literally) my database structure for the Firebase back-end.  Ive copied what they did with their FriendlyPix app, which is an excellent example, but lacking some more thorough documentation.  Ive already written an explanation of that database structure in an article here.  Thats very close to the structure Ive got with a few additions for properties they dont have.

Ive also outlined how they do Auth in that article.  For my app Ive set up Firebase via Cocoapods, and Ive done the basic set up on the Firebase Console.

For authorization, I have a RegisterViewController with UITextField's for username, password (plus re-type), and also first name and surname fields.  When my user clicks to register, this happens :

Four fairly simple steps there.  First call to create the user using FirebaseAuth.  If that works, we get a User (Firebase type) object back, which contains amongst other things, our 'uid', which is the unique identifier for that user.

Second, we do a change request to add the displayName property of that user into Firebase Auth.  Third, we go to our Firebase database and we populate a whole new entity into the People database.  The key for this entity, is the unique uid that we got back from registering the user.  The values are a URL to the photo (more in future on this), the full name (made from whatever the user entered in the first name / surname fields), and a search index with a reversed version of the name for quicker searching.

Lastly, that user is signed in, which will give the app access to the data it needs to see.  This signing in is being observed in other locations in the app, like this :

So the signing in that happened at the end of the registration code, once complete, causes this listener to fire, as it notice the sign-in success.  The Firebase User object is passed in here so again we can use the 'uid' property.  At this point I set up an observer to go and retrieve that data that I just wrote to the database in the People array.


So in the method above, I firstly remove any previous observers that I may have created, in an array of type [DatabaseQuery].  This ensures Im not making Firebase do more work than it needs to, and slowing the app down in the process.  Then I create an observer to have a look at the database and let me know first what is in the database at the specified location (which is - in the people array, in a key which is my users uid), and to then update me should whatever in there change.

The result of that call returns 'snapshot', which is another Firebase type.  Within that object is a property called 'value', which can contain an NSDictionary, NSArray, NSNumber or NSString.  To handle the contents there, I have an initialiser for my local user object, which is called GZUser.

So quite simply, I have just taken back the data that I wrote during the registration process, that Firebase stored in its JSON format.  I have taken that back as a dictionary and I have initialised my local GZUser object with that dictionary (that was packaged in a Firebase snapshot).




Finally that data is used to populate the displayName field in my UI.  But that observer will carry on watching the space for changes, until I remove that observer.  Next up I have a look at uploading data to the Firebase Database, in this post here.

Social Network with Firebase 3 - Infinitely scrolling UITableView of Firebase Items

Ive already talked about the basics of a Firebase social network project , and adding posts in two other articles. Here I want to explain ...