Note that there are some explanatory texts on larger screens.

plurals
  1. POPreferable design pattern for model with background networking
    primarykey
    data
    text
    <p>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.</p> <p>That leads to the question: <em>how should I design the @interface of my class</em>?</p> <p>The main requirements are:</p> <ul> <li>It should deliver data from Model to Viewcontroller :) ;</li> <li>It shouldn't block the main (UI) thread;</li> <li>It should be easy to understand and follow by other developers.</li> </ul> <p>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.</p> <p>Let's say we have Posts class (Posts.h/.m) that should provide ViewController with latest posts in NSArray* format.</p> <p><strong>Option I -- concurrency is in class users</strong></p> <p>The class itself is not concurrent, but the users are:</p> <pre><code>//Posts.h: @interface Posts : NSObject - (NSArray*)getPostsForUser:(NSString*)user; @end //ViewController.m @implementation ViewController - (void)someFunctionThatUpdatesUI { //&lt;...&gt; 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]; }]; }]; //&lt;...&gt; } </code></pre> <p>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?</p> <p><strong>Option II -- concurrency with completion handlers pattern</strong></p> <p>Second option that I currently use in my app is a completion handler pattern. As the completion handler is called only <em>after</em> some long networking is performed, it doesn't block the main thread:</p> <pre><code>//Posts.h: @interface Posts : NSObject - (NSError*)getPostsForUser:(NSString*)user withCompletionHandler:(void(^)(NSArray*))handler; @end @implementation Posts - (NSError*)getPostsForUser:(NSString*)user withCompletionHandler:(void(^)(NSArray*))handler { //&lt;...&gt; 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); }); }); //&lt;...&gt; } //ViewController.m - (void)someFunctionThatUpdatesUI { //&lt;...&gt; [Posts shared] getPostsForUser:@"mike" withCompletionHandler:^(NSArray* posts){ //updateUI with posts }]; } </code></pre> <p>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.</p> <p><strong>Option III -- delegate pattern</strong></p> <p>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.</p> <pre><code>//Posts.h: @protocol PostUpdate&lt;NSObject&gt; - (void)updateUIWithPosts:(NSArray*)posts FromUser:(NSString*)user; @end @interface Posts - (NSError*)updatePostsFromUser:(NSString*)user; @property(nonatomic, weak) id&lt;PostUpdate&gt; delegate; @end //ViewController.m: @implementation ViewController&lt;PostUpdate&gt; - (void)viewWillAppear { //&lt;...&gt; [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 </code></pre> <p>So here are the questions:</p> <ul> <li>What else patterns fit the requirements to deliver data from Model to Controllers in non-blocking way?</li> <li>What option would you recommend based on your experience, practise or theoretical knowledge?</li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload