10

两个月前,我开始编写一个新的 iPhone 应用程序,为此我创建了一个通用的 RESTFul Web 服务,它允许我拥有许多这些必要的功能,例如用户身份验证、用户配置文件、友谊系统、媒体处理、消息传递系统等等。在我看来,有几个用例可以将这个 Web 服务重用于未来的 iPhone 应用程序。

带着这种心态,我决定为这个应用程序(以及所有未来的应用程序)编写一个静态库,以处理所有繁重的工作,如媒体(图像、视频、声音)设置和处理、与 Web 服务通信、解析和映射结果,处理CoreData等。

鉴于我的应用程序有很多并行任务正在运行(最坏情况)的场景,例如用户当前更改了他/她的个人资料图片,而应用程序将用户位置发送到服务器(在后台)并且新的推送通知是已收到。

因此决定将每个逻辑操作(如 SendUserLocation 或 GetCurrentFriendList)封装在一个 NSOperation 中,并将它们添加到一个服务队列(NSOperationQueue)中。

当操作成功地从 web 服务获得结果并且现在应该处理它时,每个操作都能够产生子任务。

替代文字

一个典型的 ServiceManager 方法看起来像

- (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]; 
    }
}

每个操作、请求(对服务器)和 subTask 都使用 GUID 作为 notificationName,以在完成处理时通知父对象。如果操作中的所有内容都已完成,它会将通知发送回用户界面。

也就是说,添加和删除子任务的代码如下所示

- (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];
}

现在我所要做的就是在我的 gui 中调用 serviceManager 来启动一个特定的操作,比如

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

如果我想注册一个观察者,我只需传递一个观察者对象和一个像这样的选择器

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

最后但并非最不重要的问题:“架构”运行得非常好且稳定,但值得做吗?它会产生过多的开销吗?它甚至有意义吗?您个人如何实现并发操作?

最好的亨利克

PS 随意编辑我的问题,提出问题(作为评论),给我起这个想法的名字。

我真的很难解释它,主要是因为我不是以英语为母语的人。不要误会我的意思。我写这篇文章不是为了炫耀。我想做的就是学习(也许写一个更高级的iphone/objective c问题)

4

3 回答 3

4

是的,如果它被外包给服务请求并且你有很多电话要打,那么这样的图书馆并不是(imo)矫枉过正,我也写过类似的东西。这种结构使我很容易管理一个复杂的系统,其中包含非常复杂和多样的任务。

我所做的主要设计差异是将 NSNotification 与服务管理器一起使用。相反,我更喜欢使用协议/类型进行回调(操作持有引用)。NSNotification 很重。在这种情况下,操作不会保留侦听器/通知对象,但侦听器会保留操作。如果关系是 1-1,则允许取消。

另一个主要考虑因素是尽早定义线程。允许客户端定义他们希望在哪个线程上接收响应。这样做的原因是,如果通知/侦听器必须更新 UI(例如,您正在使用 UIKit 或 AppKit),则回调通常存在约束或逻辑条目。因此,创建者可以对操作说“你必须从主线程通知我”,或者“我可以处理来自任何线程的响应”。这将大大减少您的控制器/侦听器/观察器代码和出错的机会。

于 2011-02-15T20:21:57.817 回答
2

对于“子操作”:如何将它们放在您的队列中,而父操作是其每个子操作的依赖项(cf.-[ NSOperation addDependency: ])?NSOperationQueue 可以为您排序整个操作。我认为这很简单,很自然。

于 2012-09-07T01:51:41.917 回答
1

您刚刚描述了我在一些应用程序中使用的非常相似的架构:)

我让我的服务管理器层立即返回一组对象,然后在一段时间后返回一个更新的集合,即

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

然后,在服务器响应后,收到一个 NSNotification,其中包含更新的列表(在这种情况下是 Bob 的朋友)。

除了这个微小的变化,你的架构是一样的!

完成所有设置需要大量工作,但我认为从长远来看这是值得的,因为修复错误/扩展代码要容易得多。

于 2010-10-04T16:27:13.153 回答