iOS App Architecture with NSOperations

笑着哭i 提交于 2019-12-04 08:17:02

问题


Two month ago I started to write a new iPhone Application and for this reason I created a generic RESTFul web service, which allows me to have a lot of these necessary features like user authentication, user profiles, a friendship system, media processing, a messaging system and so on. In my mind there are several use cases to reuse this webservice for future iPhone applications.

With this state of mind, I decided to write a static library for this application (and all future apps) that handles all the heavy lifting like media (image, video, sound) setup and processing, communicating with the web service, parsing and mapping of the results, handling CoreData and so on.

Given my application there are scenarios when a lot of parallel tasks are running (worst case) e.g. the user currently changes his/her profile picture, while the application sends the users location to the server (in the background) and a new push notification is received.

So decided to encapsule each logical operation (like SendUserLocation or GetCurrentFriendList) in a NSOperation and add them to a serviceQueue (NSOperationQueue).

Each Operation is able to spawn subtasks when the operation successfully got a result from the webservice and should process it now.

A typical ServiceManager method looks like

- (void)activateFriendsSync:(id)observer onSuccess:(SEL)selector {
    ELOSyncFriends *opSyncFriends  = [[ELOSyncFriends alloc] initWithSM:self];
    [self ELServiceLogger:opSyncFriends];
    [serviceQueue addOperation:opSyncFriends];
    if(observer) {
        [self registerObserver:observer selector:selector name:opSyncFriends.notificationName]; 
    }
}

Each operation, request (to the server) and subTask uses a GUID as a notificationName to notify the parent object when it's done processing. If everything in an operation is done, it sends a notification back to the user interface.

That said, the code for adding and removing subtasks looks like this

- (void)removeSubTask:(NSNotification*)notification {
    ELRequest *request = (ELRequest*)[notification object];
    [subTasks removeObjectIdenticalTo:request.notificationName];
    if([subTasks count] == 0) {
         // all SubTaks done, send notification to parent
        [serviceManager.notificationCenter postNotificationName:self.notificationName object:request];
    }
}

- (NSString*)addSubTask {
    NSString* newName = [self GetUUID];
    [subTasks addObject:[newName retain]];
    [serviceManager.notificationCenter addObserver:self selector:@selector(removeSubTask:) name:newName object:nil];
    return newName;
} 

- (NSString *)GetUUID {
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    return [(NSString *)string autorelease];
}

Now all I've got to do is to call the serviceManager in my gui to start a specific operation like

[self.core.serviceManager activateFriendsSync:nil onSuccess:nil];

If I want to register an observer, I just pass an observer object and a selector like this

[self.core.serviceManager activateFriendsSync:self onSuccess:@selector(myMethod:)];

Last but not least my question(s): The "architecture" runs very well and stable, but is it worth doing? Does it create too much overhead? Does it even make sense? How you, personally, implement concurrent operations?

Best Henrik

P.S. Feel free to edit my question, ask questions (as a comment), call me names for this thinking.

I really had a hard time explaining it, basically because I'm not a native english speaker. And don't get me wrong. I didn't write this posting to show off in any kind. All I want to do is learn (and maybe to write a more advanced iphone / objective c question)


回答1:


yes, if it's being farmed out to service requests and you have many calls to make, then such a library is not (imo) overkill, and i have written something similar. this structure made it very easy for me to manage a complex system, with very complex and varied tasks.

the primary design difference i made was not to use NSNotification with a service manager. instead, i favored using protocols/types for callbacks (which the operation holds a reference to). NSNotification is quite heavy. in this case, the operation does not retain the listener(s)/notified objects, but the listeners retain the operation. if the relation is 1-1, then allow cancellation.

another major consideration is to define threading early on. allow clients to define which thread they want to receive their response on. the reason for this is that there is often a constraint or logical entry for the callback if the notified/listener must update the UI (e.g., you're using UIKit or AppKit). therefore, the creator can say to the operation 'you must inform me from the main thread', or 'i can handle the response from any thread'. this will reduce your controller/listener/observer code and chance for errors greatly.




回答2:


For "sub operations": what about putting them on your queue, with the parent operation being a dependency (cf. -[ NSOperation addDependency: ]) of each of its child operations? The NSOperationQueue can sequence your whole pile of operations for you. I think this is simple and natural to work with.




回答3:


You have just described a very similar architecture that I'm using in a few of my apps :)

I have my service manager layer returning a set of objects instantly and then returning an updated set after a while i.e.

NSArray *stuff = [serviceManager getFriendsForUser:@"Bob"];

and then, after the server has responded, an NSNotification is received that contains an updated list (of friends for Bob in this case).

Apart from this tiny change, your architecture is the same!

It is quite a lot of work to get it all set up but I think it's worth it in the long run as fixing bugs / extending the code is much easier.



来源:https://stackoverflow.com/questions/3856598/ios-app-architecture-with-nsoperations

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!