Preferable design pattern for model with background networking - ios

I'm developing a model class that provides data parsed from the web. Of course, I'd like my application to be responsive and thus networking should be done on separate thread/queue.
That leads to the question: how should I design the #interface of my class?
The main requirements are:
It should deliver data from Model to Viewcontroller :) ;
It shouldn't block the main (UI) thread;
It should be easy to understand and follow by other developers.
From what I've learned from WWDC2012 video, "Building Concurrent User Interfaces on iOS" Apple recommends to move the concurrent code to the class itself that uses model.
Let's say we have Posts class (Posts.h/.m) that should provide ViewController with latest posts in NSArray* format.
Option I -- concurrency is in class users
The class itself is not concurrent, but the users are:
//Posts.h:
#interface Posts : NSObject
- (NSArray*)getPostsForUser:(NSString*)user;
#end
//ViewController.m
#implementation ViewController
- (void)someFunctionThatUpdatesUI
{
//<...>
NSOperationQueue *q = [[NSOperationQueue alloc] init];
[q addOperationWithBlock:^{
NSArray *currentPosts = [Posts shared] getPostsForUser:#"mike";
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
//UI should be updated only on main thread
[self updateUIWithPosts:currentPosts];
}];
}];
//<...>
}
The main disadvantage of this approach is the necessity to repeat almost the same code in every ViewController. What if there are dozens of them?
Option II -- concurrency with completion handlers pattern
Second option that I currently use in my app is a completion handler pattern. As the completion handler is called only after some long networking is performed, it doesn't block the main thread:
//Posts.h:
#interface Posts : NSObject
- (NSError*)getPostsForUser:(NSString*)user
withCompletionHandler:(void(^)(NSArray*))handler;
#end
#implementation Posts
- (NSError*)getPostsForUser:(NSString*)user
withCompletionHandler:(void(^)(NSArray*))handler
{
//<...>
dispatch_async(dipatch_get_global_queue(0, 0), ^{
//Do some may-be-long networking stuff here,
//parse, etc and put it into NSArray *result
dispatch_async(dipatch_get_main_queue(), ^{
handler(result);
});
});
//<...>
}
//ViewController.m
- (void)someFunctionThatUpdatesUI
{
//<...>
[Posts shared] getPostsForUser:#"mike"
withCompletionHandler:^(NSArray* posts){
//updateUI with posts
}];
}
From my point of view, this way is good but the #interface is rather complicated, the method names are long and (from my point of view) obfuscated.
Option III -- delegate pattern
Another option that I see is the delegate pattern. What bothers me is that only one ViewController may be the delegate, thus it leads to necessity to set every VC as delegate in - viewWillAppear, which is easy to forget.
//Posts.h:
#protocol PostUpdate<NSObject>
- (void)updateUIWithPosts:(NSArray*)posts FromUser:(NSString*)user;
#end
#interface Posts
- (NSError*)updatePostsFromUser:(NSString*)user;
#property(nonatomic, weak) id<PostUpdate> delegate;
#end
//ViewController.m:
#implementation ViewController<PostUpdate>
- (void)viewWillAppear
{
//<...>
[Posts shared].delegate = self;
}
- (IBAction)getLatestsPostButtonPressed:(id)sender
{
[[Posts shared] updatePostsFromUser:#"mike"];
}
// protocol PostUpdate
- (void)updateUIWithPosts:(NSArray*)posts FromUser:(NSString*)user
{
//updating UI with posts
}
#end
So here are the questions:
What else patterns fit the requirements to deliver data from Model to Controllers in non-blocking way?
What option would you recommend based on your experience, practise or theoretical knowledge?

Short answer
I recommend going with option-II as it's the most suitable solution in your case.
Long answer
First of all, none of the three solutions is wrong, but we are only trying to figure out the best one among them for your case.
• The problem with option-I is that it's always synchronous and will block the calling thread while you need it to be asynchronous, and therefore, you'll find yourself always calling it from a background thread which means there will be a lot of repeated code that will make maintenance harder (This option can be a good solution if you need the method to be asynchronous sometimes and synchronous most of the time).
• The option-II solves the problem by providing a way to notify the caller thread when the data is ready, and the added parameter isn't really a disadvantage compared to the easiness of use and flexibility it gives. And if you think you will not really need the added parameter in some cases, you can simply make another synchronous version of the method without that parameter:
- (NSArray *)fetchPostsForUser:(NSString*)user; /// Synchronous
- (void)fetchPostsForUser:(NSString*)user /// Asynchronous
completion:(CompletionHandler)completion;
CompletionHandler is defined as following:
typedef void (^CompletionHandler)(NSArray *result, NSError *error);
• The third option isn't really a good solution for your problem. Delegates should be used to deliver events about the class itself, not to deliver responses to previously called methods. Also, notice than you can only have one delegate and this means you can't call such method from two different controllers at the same time.

Option 1 is bad for the reason you mention.
Option 3 is bad because you may have network data returned in a different order than requested if you have 2 network requests going at the same time. This may make it more difficult than necessary to update your UI properly, depending on your data. (For example, items could appear out of order.)
Option 2 seems ideal. It has the benefits of Option 3, plus you get the scope-capturing benefit of Objective-C blocks. You may want to look at the networking library AFNetworking, which approximately follows this pattern. One additional consideration is that you should keep your data networking & serialization in a separate class from data persistence / processing. For example, one class should download data, turn it into an array of Post objects, and send it to the callback block. That callback block could be a view controller, or it could be a separate class that caches the data to disk (using NSCoder or Core Data, for example.) This approach will keep your code as flexible as possible.

Related

Sharing NSURLsession delegate implementation among view controllers

In my iOS app, many ViewControllers will need to send/receive data from a server based on user input and actions. I am going to use NSURLSession for all my networking activities. But I don't want to make every ViewController conform to the NSURLSession delegate
protocol and repeat all the methods.
I see two solutions
Create a class that conforms to the NSURLSession delegate
protocol. Other classes create an instance of this class and use its methods to send/receive data from the server. The reuse of the class handling all the networking will be done using singleton design pattern by overloading its init method so that only instance of it is created.
Disadvantage of this approach seems to be that having singletons make its tough to create unit tests that completely gets functionality of each class isolated form others. I.e.Suppose an error only happens because viewcontroler1 asked "shared class" to send a particular message followed viewcontroller 2 asked it send some other message. Then it is not possible to catch this using unit tests.
Subclass of the UIViewController that implements the methods and subclass my ViewControllers of of this.
One issue here is that if I have different kinds of views in app, then I need to create subclass for each type of ViewController with NSURL session delegate methods. And I have to carefully assign the delegate object from method to method. When I look at it, I think this approach also has the same unit-testing problem as approach 1.
I would appreciate any comments on
1. Approaches others have used in similar situation
2. Pros/cons of above approaches (including the 2 I have listed above). I realize this may be a bit subjective, but IMHO getting good advice on design patterns is as important as (or even more important than) answers to what is wrong with my code or which API to use to solve problem X
The way I've done this in the past is:
1) Created a class that contained a NSURLSession object
#interface CustomSession : NSURLSessionDelegate
#property (nonatomic, strong) NSURLSession *mySession;
2) In the CustomSession init method initialize mySession, set delegate to self.
3) Implemented desired NSURLSession delegate methods in CustomSession.
4) Use block methods (optional, but I prefer them)
5) Decide whether you want to use CustomSession as a singleton or instantiate it every time you need it. You can actually do both just define init methods accordingly.
+ (CustomSession *)session
{
//Singleton
}
+ (instancetype) newClient{
//normal init method}
6) As for unit testing, you could have a weak pointer in CustomSession to the parent VC (as you pointed out this would work if you're not using a Singleton).
Quick suggestion: Use AFNetworking, will simplify your life. For example I use AFHTTPSessionManager and the corresponding block methods provided:
[self GET:detailsURL parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject)

NSMutableArray Thread Concurrency with GCD

I have an NSMutableArray in a "sharedStore"-pattern singleton.
Publicly, it's accessible only through methods that cast it as an NSArray. Within the class, it's
#property (nonatomic, copy) NSMutableArray *myItems;
This array never gets manipulated outsdie the singleton but ViewControllers send the singleton messages to manipulate this controller. Some of these messages empty the array, some re-populate it, etc.
Having ended up in a situation where the array was empty in one method call and not yet empty in the next, I've started implementing some concurrency behaviour.
Here's what I'm doing so far:
In the .m file of the singleton, I have a
#property (nonatomic, strong) dispatch_queue_t arrayAccessQueue;
In my singleton's initializer it gets created as a serial queue. And then, every method that has anything to do with mutating this array does so from within a dispatch_sync call, for example:
dispatch_sync(self.arrayAccessQueue, ^{
[_myItems removeAllObjects];
});
This has made things better and has made my app behave more smoothly. However, I have no way of quantifying that beyond it having fixed that one odd behaviour described above. I also kind of feel like I'm in the dark as to any problems that may be lurking beneath the surface.
This pattern makes sense to me, but should I be using something else, like #synchronize or NSLock or NSOperationQueue? Will this come back to bite me?
Using dispatch_sync is fine as long as you wrap all array reads and writes and you ensure it is a serial queue.
But you could improve things by allowing concurrent reads. To do this, use dispatch_sync around all array reads and use dispatch_barrier_sync around all array writes. And setup the queue to be concurrent.
Do this ensures only a single write can happen at a time, reads will be block until the write is done, and a write will wait until all current reads are done.
Using a GCD queue concurrent and providing sort of accessor to your array you can synchronize reading and writing by using dispatch_sync while reading and dispatch_barrier_async while writing.
- (id)methodToRead {
id __block obj = nil;
dispatch_sync(syncQueue, ^{
obj = <#read_Something#>;
});
return obj;
}
- (void) methodsForWriting:(id)obj {
dispatch_barrier_async(syncQueue, ^{
// write passing obj to something
});
}
This will guarantee that during writing everything is locked from reading.
Using GCD is the right choice. The only "gotcha" is that you need to do ALL operations on that queue: add, remove, insert, etc.
I will also mention you need to ensure that you do not use a concurrent queue. You should be using a serial queue, which is the default anyways.

iOS common objects

I'm writing an iOS app where there is a common object that all views within the app need to access.
I have been creating, and initialising the object within the viewDidLoad event (of the first view controller), and then passing a reference to this object to all other views that need it. This does not seem like the correct way to do things, feels like I'm somehow breaking the MVC pattern since I'm relying that this particular view is always the first to load in order to setup objects that the whole application needs.
I have now modified my app to do the basic object creation and initialisation in the appDelegate "didFinishLaunching...". This is now working and I can access this common object from all of my other views without having to pass around a reference from one view to the other.
Before I go and continue too far, I was hoping to get peoples input on whether this is the correct way to do things, or whether I should be doing anything else? Sorry if this seems like a trivial question, I'm just learning and want to learn how to do things properly.
Thanks in advance :-)
Without repeating what has already been answered, I'd suggest you make your own Singleton object to hold your 'globals', so you don't clutter your AppDelegate with it.
#interface MyGlobalDataController : NSObject
#property (nonatomic, strong) MyData *myData;
+(MyGlobalDataController *)sharedInstance;
#end
#implementation MyGlobalDataController
static MyGlobalDataController *MyGlobalDataControllerSharedInstance = nil;
- (id)init {
self = [super init];
if (self) {
// do whatever needs doing
}
return self;
}
+(MyGlobalDataController *)sharedInstance {
#synchronized(self) {
if (MyGlobalDataControllerSharedInstance == nil) {
MyGlobalDataControllerSharedInstance = [[MyGlobalDataController alloc] init];
}
}
return MyGlobalDataControllerSharedInstance;
}
#end
The first time you access your sharedInstance, the init will be called, so you don't have to worry about timing there.
Putting your global object initialisation in didFinishLaunching is a better idea than having it in didLoad.
Some people will disagree with me here and say you shouldn't have globals full stop, but personally I think having some sort of global state is acceptable. I love a good object-orientated app but there is a balance to be struck between solid OOP and the flexibility provided by having a few globals.
I think ultimately do whatever is right for you, the major disadvantage of having a global state is that it becomes difficult to maintain and has the potential to introduce a lot of bugs / unexpected behaviour especially in a large app, whereas if you stick to the MVC pattern then each view in your app simply does what it is meant to without unnecessarily affecting other parts of the app.
Nowadays, I tend to stick to MVC / OOP principles for the most part, but have an [AppDelegate]sharedAppDelegate] singleton I can use to access variables at certain points. I have very, very few variables in here but they do come in handy i.e. now my app has a shared 'loading HUD' which is managed by this class, and my sharedAppDelegate also contains a lot of static methods for initiating HTTP, parsing JSON etc which saves a lot of time.
One alternative to having global information in your appDelegate is using NSUserDefaults to store key-value information
Hope that helps anyway, like I said some people will disagree with me but ultimately it boils down to personal preferences, and where the balance for you in terms of rigidity to the MVC model versus flexibility is

NSMutableDictionary - EXC BAD ACCESS - simultaneous read/write

I was hoping for some help with my app.
I have a set up where multiple threads access a shared NSMutableDictionary owned by a singleton class. The threads access the dictionary in response to downloading JSON and processing it. The singleton class is basically preventing duplication of some downloaded objects which have an unique id number.
ie.
//NSURLConnection calls:
[[Singleton sharedInstance] processJSON:data];
#interface Singleton
+ (Singleton) sharedInstance;
#property (nonatomic, strong) NSMutableDictionary *store;
#end
#implementation
-(void) processJSON:(NSData*)data {
...
someCustomClass *potentialEntry = [someCustomClass parse:data];
...
if(![self entryExists:potentialEntry.stringId])
[self addNewEntry:potentialEntry];
...
}
-(void) entryExists:(NSString*)objectId {
if(self.store[objectId])
return true;
else return false;
}
-(void) addEntry:(someCustomClass *object) {
self.store[object.stringId] = object;
}
There can be as many as 5-10 threads at a time calling processJSON at once.
Not immediately but after a few minutes of running (quicker on the iPhone than on the simulator) I get the dreaded EXC BAD ACCESS.
I don't confess to know how NSMutableDictionary works but I would guess that there's some kind of hash table in the background which needs to be updated when assigning objects and read when accessing objects. Therefore, if threads were to instantaneously read/write to a dictionary, this error could occur - may be because an object has moved in memory?
Im hoping that someone with more knowledge on the subject could enlighten me!
As for solutions I was thinking of the singleton class having an NSOperationQueue with a maximum concurrent operation number of 1 and then using operationWithBlock: whenever I want to access the NSDictionary. The only problem is that it makes calling processJSON an asynchronous function and I can't return the created object straight away; I'd have to use a block and that would be a bit messier. Is there any way of using #synchronize? Would that work well?
I'd draw your attention to the Synchronization section of the iOS rendition of the Threading Programming Guide that Hot Licks pointed you to. One of those locking mechanisms, or the use of a dedicated serial queue, can help you achieve thread safety.
Your intuition regarding the serial operation queue is promising, though frequently people will use a serial dispatch queue for this (e.g., so you can call dispatch_sync from any queue to your dictionary's serial queue), achieving both a controlled mechanism for interacting with it as well as synchronous operations. Or, even better, you can use a custom concurrent queue (not a global queue), and perform reads via dispatch_sync and perform writes via dispatch_barrier_async, achieving an efficient reader/writer scheme (as discussed in WWDC 2011 - Mastering GCD or WWDC 2012 - Asynchronous Design Patterns).
The Eliminating Lock-Based Code section of the Concurrency Programming Guide outlines some of the rationale for using a serial queue for synchronization versus the traditional locking techniques.
The Grand Central Dispatch (GCD) Reference and the dispatch queue discussion in the Concurrency Programming Guide should provide quite a bit of information.
the simplest solution is to just put all off the code that accesses the dict in an #synchronized block.
serial operation queues are great, but sounds like overkill to me for this, as you aren't guarding a whole ecosystem of data, just one structure..

Delegates in IOS - Some clarification required

I'm only really beginning IOS development but have a few years dev of ASP.net through C#. To be honest I've never had a real need to understand delegates / events etc. before, I know that I'm using them when programming web.forms but a lot of the functionality is taken care of by the framework, behind the scenes.
So now that I'm developing in IOS I'm forced to try to understand how they function (I'm presuming here that the theory of delegates / events is the same across languages, maybe I'm wrong). Anyway, the following line of code in IOS:
if ([self.delegate respondsToSelector:#selector(startImporting:)])
{
[self.delegate startImporting:self];
}
Am I right in thinking that, in pseudo code, it means something along the lines of:
If the method/class calling this method has a method in it called 'startImporting' then call the method 'startImporting' within the calling class.
Hope that's clear. If that's the case then would it essentially be the same as having a static method in C# that you could call with something like:
myImportClass.startImporting();
Presumably not, or that's how it would be done. So, am I missing the whole point of delegates, their benefits etc? I've read what they are over and over and while it makes sense, it never clicks, I never (in web forms anyway) have really seen the benefit of using them.
This becomes increasingly important as I'm moving to using lambda expressions in .net and they're closely linked to delegates in C# so while I can just start using them, I'd prefer to know why and what benefit delegates actually are.
The delegation pattern in Cocoa is used to inform (report progress, etc.) or query (ask for credentials, etc.) another object without knowing much about it.
Typically, you use a protocol to define what methods you will call on the delegate and the delegate then needs to conform to that protocol. You can also add methods that the delegate doesn't need to implement (optional). When you do so, you'll have to call -respondsToSelector:, because you don't know whether the delegate wants the particular method to be called or not.
An example:
You have a class that produces something, let's call it Machine and a worker of the class Worker. The machine needs to be adjusted for the task:
Machine *machine = [[Machine alloc] init];
[machine prepareWithParameters:myParameters];
Now that we have the machine we want to produce a massive amount of Stuff:
[machine produceStuff];
Okay, we're done. But how do we know when an unit of Stuff has been produced? We could have our worker constantly standing beside our machine and wait:
while (![machine isFinished]) {
if ([machine didProduceStuff]) {
Stuff *stuff = [machine producedStuff];
[self doSomethingWithStuff:stuff];
}
else {
// Get a very large coffee...
}
}
Wouldn't it be great if the machine did inform us automatically, when it's done with producing an unit of Stuff?
#protocol MachineDelegate <NSObject>
#optional
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff;
#end
Let's add the worker as a delegate of machine:
Worker *worker;
Machine *machine = [[Machine alloc] init];
[machine prepareWithParameters:myParameters];
[machine setDelegate:worker]; // worker does conform to <MachineDelegate>
[machine produceStuff];
When Machine is done producing something, it will then call:
if ([[self delegate] respondsToSelector:#selector(machine:didProduceStuff:)])
[[self delegate] machine:self didProduceStuff:stuff];
The worker will then receive this method and can do something:
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff {
[self doSomethingWithStuff:stuff];
if ([machine isFinished])
[self shutDownMachine:machine];
}
Isn't that much more efficient and easier for the worker? Now he can do something more productive than standing besides the machine while the machine is still producing. You could now add even more methods to MachineDelegate:
#protocol MachineDelegate <NSObject>
#required
- (void) machineNeedsMaintenance:(Machine *)machine;
- (void) machine:(Machine *)machine fatalErrorOccured:(Error *)error;
- (BOOL) machine:(Machine *)machine shouldContinueAfterProductionError:(Error *)error;
#optional
- (void) machineDidEnterEcoMode:(Machine *)machine;
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff;
#end
Delegates can also be used to change the behavior of an object without subclassing it:
#protocol MachineDelegate <NSObject>
#required
- (Color *) colorForStuffBeingProducedInMachine:(Machine *)machine;
- (BOOL) machineShouldGiftWrapStuffWhenDone:(Machine *)machine;
#end
I hope I could help you understand the benefit of abstracting your code using delegates a little bit.
Understanding the MVC model and the use of Protocols and notifications is critical to grasping the use and purpose of delegates. Think of them as types of responders for different events related to a specific action.
Hera are some useful links in stackOverflow:
Delegate and notifications
Protocols and delegates
Hope it helps
delegates are useful in getting callbacks from other class
so why to use delegate:
that is we call a method on a class... that's normal... if we want the instantiated class to let us call back... that's where delegates comes in handy...
simple example:
You download songs from a site using a method on one class
once the class completes downloading you want the class to let you know.
//protocol declaration
#protocol DownloadProtocol <NSObject>
-(void)OnFinish;
#end
//SOng download class
#interface songs
#property(Strong,nonatomic) id<DownloadProtcol> delegate;
-(void)Download;
#end
#implementation songs
-(void)Download
{
///the code to download goes here
[self callTheCallingClass];
}
-(void)CallTheCallingClass
{
[self.delegate OnFinish];
}
#end
//
#interface mainclass<DownloadProtocol>
#end
#implementation mainclass
-(void)viewDidload
{
Songs *s=[[SOngs alloc]init];
s.delegate=self;
[s download];
}
-(void)OnFinish
{
NSlog(#"Called");
}
#end
see the delegation is achieved through protocol in objective c. I think you can understand the syntax of it.
In the songs class we create a property for that protocol. we keep it the type as ID... because the type is not known at compile time.
in the songs class once we complete the download we call the protocol method...
In the main class first we adopt the protocol syntax
class
the above is syntax of that
the we instantiate the songs class
then assign the main class object(self) to delegate of songs class
then we have to apply the protocol class in .m by adding method name from protocol
so from now on whenever songs class call the protocol method through delegate instance variable....out protocol method adoption on main class gets run
try this code hope it helps...
if you want more info on this topic google it as delegate design pattern
the main benefit is
it promotes loosely coupled programming...

Resources