Quick code dive in for our Simple Todo app using iCloud
(This post is part of hands on iOS programming series)
(For Objective C basics visit earlier part of Series)
I have now pushed code for simple todo application.
It does following things --
a) Populates a list of Todos
b) Allows Dynamic addition/Deletion/updation of Todos
c) Sync Todos between iCloud using Key/Value pairs.
Have a look at code over here.
I have tried to keep each commit to capture essential steps in the building up of Todo application. If one is familiar with Storyboards and stuff, he can follow the commits to replicate the code.
(This post is part of hands on iOS programming series)
(For Objective C basics visit earlier part of Series)
In this post we will not go in detail, just touch up on the necessary terminology/lingos to get upto speed with GUI programming in iOS.
iOS apps are based on event-driven programming. Event-driven programming means flow of application is driven by events in the system. There are either user (Eg: Touch up/down) or system events (Eg: Low battery)
iOS application follows a popular Model-View-Controller (MVC) design pattern.
Model: Is the class which takes care of holding data of the application. Data can be dynamic or static and can be persisted depending on the needs of the application. Structure of data can be simple array or some complex data structure. All this is responsibility of Model class. Usually model interacts with Controller. Eg: Simple Array
Controller: This is the class which handles interaction between views and data. It determines which views to swap in or out. Animation between transitions and pushing data to view from model. Eg: ViewController, Navigation Controller, etc...
View: This is the class which can be a simple view or complex hierarchy of views. It represents visual representation of application and all the user events are fed through this class. Eg: TextBox, label etc...
One more thing that is not mentioned is the Window object. It is like the canvas of the system on which various views are drawn.
Starting point in any iOS application is by calling UIApplicationMain.
This creates two objects UIApplication & AppDelegate
UIApplication manages application event loop and coordinates with other high-level app behaviors.
AppDelegate creates window for the application and also provides space for state transitions within the app.
Usually when writing an application, we would first create wireframes and layout diagrams for various screens/views and their transitions.
iOS simplifies this by introducing Storyboards. After iOS 5.x it is the way forward. Before that it was Xibs. Many developers prefer Xibs over Storyboards.
We will look at storyboard example in our tutorial.
Storyboards: A storyboard is a visual representation of the app’s user interface, showing screens of content and the transitions between them. You use storyboards to lay out the flow—or story—that drives your app.
Segues: Transitions between scenes are called segues.
We are now ready to jump into code. If you want more detailed step by step tutorial apple has one. It talks at length about all the concepts etc...
After learning Objective C basics, its time to move to real iOS programming. I will come out with a series soon on iOS Programming using Storyboards. We will briefly look at Concepts around it and then jump to some live example.
If you have any inputs feel free to post a comment related to it. I will see if it can be incorporated
In the previous post we saw we had to introduce a copyMe or deepCopyMe method so that we can make a copy of our own object. But problem with this method, is that every creator of class can name his copying method as he wishes to. In a big code, figuring this out would be difficult.
Objective C offers a simple solution, in the form of NSCopying / NSMutableCopying & NSObject.
Any method needing to implement a copy function, should call copy and/or mutableCopy of NSObject.
We look here at code examples and results of such actions.
For reference we use the code over here. We have a AddressBook and ContactCard classes. For sake of simplicity we have only one contact card in the address book.
Our reference ab1 object is an object of type AddressBook.
AssignWhen we assign one object to another, we essentially create a new reference pointer to same data.
For eg:
We look at lines 35 -42 in main.m
We can see both ab1 and ab2 point to essentially same data. Hence output of both ab1 & ab2 is same. So any change in either one results in change of data for both objects.
Shallow Copy
We introduce a "copyme" function to create a copy of AddressBook. But this is essentially a shallow copy. Even though we now have seperate copies of Addressbook, any change in contactcard for one (ab1) still reflects on another object (ab3).
This problem occurs because both ab1 and ab3 point to same ContactCard object.
Reference Code is between lines 46 - 63 in main.m
Deep Copy
We now create two seperate copies of AddressBook and ContactCard object. As a result change in one (ab1) object does not create problem in other object (ab4).
Reference Code is between lines 66 - 78 in main.m
Hope this clarifies difference between assign, shallow and deep copy.
In our examples we have created copyme and deepcopyme methods. But we can address this using Objective C protocol which governs copy for every object which conforms to the protocol.
We already looked at Protocols. When we mention Protocols, it is necessary to mention delegates as well.
Dictionary defines delegate as someone who has authority to represent some other person.
In our case delegate is a class/object who knows which is the class that conforms to protocol.
This is a popular Delegate Design Pattern, where a class is delegated task to carry on behalf of originating class. This way to external world it appears the job is done by delegated class, which in reality is done by someone else.
Lets look at our protocol example.
//Protocols.h
@interface MyProtocol
-(void) implicitRequiredMethod
@required
-(void) explicitRequiredMethod
@optional
-(void) explicitOptionalMethod
@end
//ProtocolConformer.h
@interface ProtocolConformer<MyProtocol>
-(void) implicitRequiredMethod
-(void) explicitRequiredMethod
@end
// BroadCaster.h
@interface BroadCaster
{
-id<MyProtocol> protocolHandle;
}
-id initWithProtocolHandle:id<MyProtocol> pH;
-(void) broadcastNow;
@end
Here the BroadCaster is the one who is acting as a Delegate Class. It holds the handle to ProtocolConformer where the actual magic is supposed to happen.
But to external world all actions for the events happens on Broadcaster class.
If this is still confusing here is one good discussion on stackoverflow
In previous post we have seen What is Protocol.One can extend existing already declared Protocol just like we extend existing classes albeit with different syntax.
Here is our original Protocol declaration
//Protocols.h
@interface MyProtocol
-(void) implicitRequiredMethod
@required
-(void) explicitRequiredMethod
@optional
-(void) explicitOptionalMethod
@end
So imagine we want to add new Protocol say "AdvancedProtocol" which adds one more method to existing protocol. Here is how you achieve that
Categories is a very unique and useful feature of Objective C.
Category provides an easy way to modularize definition of a class into groups or categories of related methods.
Categories can be useful in following cases --
Extending an existing class definition without access to its original source code or without subclassing.
Distributed Incremental development of Code. This is possible as one doesnot need to implement all the methods declared in the interface section.
Extending using Categories differs from subclassing in following ways --
One can override methods in original class, but unlike subclasses, it cannot access original method implementation. It is for this reason it is not recommended to override methods inside Category.
Although category has access to instance variables of original class, it cannot add its own instance variables.
Here is an example of Categories.
Use Case: We get URL in string format and we need to parse it. Also this url parsing might be required across various classes.
There could be two approaches in my opinion -
Write a separate Class which provides for parsing method.
We can use Category to extend NSString class and introduce Parsing method.
Which one to choose depends on context of use case. Here we see second case as a demonstration of Category implementation.
[ Heads up this is very long post, so get a cup of coffee before you start on this :) ]
Understanding Memory management for any platform is central part of work for a programmer. Wrong choices and your program can break and result in unhappy customer.
iOS / Objective C provides nice wrapper to reduce basic memory handling issues by programmer.
It does by using Automatic Reference Counting(ARC).
In ARC rule is simple, as long as there is a pointer referencing the memory, the memory is not released
All this happens at compile time. Compiler checks what are the attributes of Properties and based on that does decisions, when to send request for reclaiming the memory.
strong -- By default all Properties have strong attribute. It essentially says, property is owned and hence do not release till the end of scope.
For eg:
@interface Engine
@property NSString* manufacturer
@end
@interface Car
@property BOOL running;
@property(strong) Engine make; // you dont need to explicitly mention strong although we are doing it here for clarity.
Now compiler knows unless "nano" object's make gets dereferenced, it cannot release "eng" object.
weak -- This exists essentially to avoid retain cycles . We saw with strong attribute, every pointer reference causes increment in reference counting to the given memory.
This is not desirable in all cases especially with parent-child relationships. This is because it causes retain cycles, where parent is pointing to child and child is pointing back to parent resulting in either of them not being released. Essentially retain cycles result in memory leak and hence we need to avoid them.
By having weak reference we can avoid these retain cycles.
For eg:
If we needed reference to all Cars using a Particular Engine, we might have reference to Car object as well. In this case we would end up with retain cycle . So the declaration of Engine class would look like as following --
@class Car //forward declaration of Car class
@interface Engine
@property NSString* manufacturer;
@property(weak) List<Car*> cars;
@end
This way now there are retain cycles between Car(Parent) and Engine (child) class.
copy -- By specifying the attribute, we are saying we would need a copy of the memory instead of the same reference.
This is very useful in cases where referencing to same value can result in unexpected behavior.
Its very practical to have engines from same manufacturer. So when there are two cars with engine from same manufacturer our pointer references can look as follows.
Can you see a problem here, If something changes in engine, information captured about engine in both the cars would be lost. This can be a serious issue in a larger project.
Also in practice every engine of car would be independant of each other, so it would be wise to create seperate copies of engines for each car instance/object.
This is exactly what copy attribute does, creates independent copies.
Here is the Class definition --
@interface Car
@property BOOL running;
@property(copy) Engine* make; //create seperate copy of engine.
@end
Now it is the responsibility of each instance to destroy the created instances of engine which was not the case earlier.
You can override dealloc method of NSObject.
(Note: Copying objects is not a trivial task it involves lot of deeper understanding. We cover all that in subsequent posts)
Migration Trivia:
If you are late entrant to iOS / Objective C world like me, you wont even notice this.
But in case you come across these terms, it here for completeness
@property directive by default makes setters and getters atomic operations. This is very useful in multithreaded environment. But it comes at the cost of overhead to maintain synchronisation.
Not every application needs to deal in threads if for example you are making stop watch application you dont need threads. In such case one can conserve the overheads by using nonatomic attribute.
We observed in our previous posting on class in iOS that we need to declare and define getter and setters everytime.
iOS makes it simple to reduce this pain by offering two directives namely @Property and @Synthesize. But using these properties is not so straight forward. If we donot know what we are doing, we can end up in a pointer mess and might have program doing funny things.
We will look at intricacies in another post, which will be split in two parts --
Under The Hood Properties in Objective C (Links would be added later)
Custom naming of getters & setters.
Memory Management & Properties.
Copying in Objective C (Links would be added later)
For now lets look at basic declaration of @property and @synthesize pair.
// Car.h
@interface Car
{
Engine e;
}
@property Color c;
...
@end
//Car.m
@implementation Car
@synthesize Color c
.....
@end
Thats it. Now one can use the Color c variable in the implementation without worrying about setters and getters.
Class is a programmatic representation of real world object.
For Eg: If you had to design a program for Automated Car Parking system, you might need to represent real objects of Car, People, Parking Hall in some form. These all real Objects can be represented as Class in Object Oriented World.
So essentially Class will contain data to store state of the object and methods/functions which would be used to attain the states.
Lets say we want to represent Car object.
Car would have Engine, Colour of its own and other parts which we choose to ignore.
Car can start, stop at minimum
Thus data here would be Engine, Colour
& Operations would be Start, Stop
Declaring a Car Class would be as follows --
@interface Car
{
Engine engine;
Color color;
}
-(void) setColor:Color c;
-(void) getColor;
-(void) setEngine:Engine e;
-(void) start;
-(void) stop;
@end
If you have to write the implementation of the class, you can write in separate file with actual function definitions between @implementation... @end directives.
The (-) sign tells that the compiler that methods are instance methods. It also means that they can be operated only on instance of a class or Object of the class.
We can have (+) sign as well in front of method. It means the method is a class method and you can call it without creating an instance.
Class methods are not static methods though. They differ in following ways --
To call class methods, one needs instance of the metaclass that describes the class object being invoked.
Also unlike static methods, one can inherit class methods, making it easier to share one single implementation like +alloc of NSObject class.
If you notice we have also written set/get methods, we can eliminate that by declaring @property and @synthesize directives. We will revisit them, later in the basics series.