【问题标题】:Callbacks in ObjC+CocoaObjC+Cocoa 中的回调
【发布时间】:2009-07-26 18:40:51
【问题描述】:

我对 Cocoa/ObjC 比较陌生。有人可以帮我更改我的代码以使用异步网络调用吗?目前它看起来像这样(虚构的例子):

// Networker.m
-(AttackResult*)attack:(Charactor*)target {
    // prepare attack information to be sent to server
    ServerData *data = ...;
    id resultData = [self sendToServer:data];
    // extract and return the result of the attack as an AttackResult
}

-(MoveResult*)moveTo:(NSPoint*)point {
    // prepare move information to be sent to server
    ServerData *data = ...;
    id resultData = [self sendToServer:data];
    // extract and return the result of the movement as a MoveResult
}


-(ServerData*)sendToServer:(ServerData*)data {
    // json encoding, etc
    [NSURLConnection sendSynchronousRequest:request ...]; // (A)
    // json decoding
    // extract and return result of the action or request
}

请注意,对于每个动作(攻击、移动等),Networker 类都有与 ServerData 相互转换的逻辑。期望我的代码中的其他类来处理这个 ServerData 是不可接受的。

我需要使 A 行异步调用。 似乎正确的方法是使用 [NSURLConnection connectionWithRequest:...delegate:...] 实现回调来做后处理。这是我能想到的唯一方法:

//Networker.m
-(void)attack:(Charactor*)target delegate:(id)delegate {
    // prepare attack information to be sent to server
    ServerData *data = ...;
    self._currRequestType = @"ATTACK";
    self._currRequestDelegate = delegate;
    [self sendToServer:data];
    // extract and return the result of the attack
}

-(void)moveTo:(NSPoint*)point delegate:(id)delegate {
    // prepare move information to be sent to server
    ServerData *data = ...;
    self._currRequestType = @"MOVE";
    self._currRequestDelegate = delegate;
    [self sendToServer:data];
    // extract and return the result of the movement
}


-(void)sendToServer:(ServerData*)data {
    // json encoding, etc
    [NSURLConnection connectionWithRequest:...delegate:self] // (A)
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    //json decoding, etc
    switch( self._currRequestType ) {
        case @"ATTACK": {...} // extract and return the result of the attack in a callback
        case @"MOVE": {...} // extract and return the result of the move in a callback
    }
}

但是,这很丑陋,而且不是线程安全的。 这样做的正确方法是什么?

谢谢,

【问题讨论】:

  • 你能告诉我你的代码的虚构示例对任何人有什么好处吗?我不得不说这和把你邻居的车送去修理厂差不多,因为你的车有问题。
  • 用一个简单的游戏类比来说明我的设计问题比解释我正在开发的应用程序的有些复杂的功能更容易。

标签: iphone objective-c cocoa events refactoring


【解决方案1】:

一种选择是每个命令/请求都有一个对象实例;作为额外的奖励,您可以使用子类,以便类型的处理是多态的,而不是基于大的 switch 语句。使用 initWithDelegate: 方法创建一个基本命令对象(然后在与需要参数的命令相对应的子类中具有专门的 inits)和用于基本发送/接收管道的方法。每个子类都可以实现一个 handleResponse: 或类似的,从您的基类 connectionDidFinishLoading: 中调用。

如果您想对该服务的客户端隐藏它,您的攻击:、moveTo: 等方法可以隐藏这些对象的实例化,因此客户端将与相同的 API 进行交互。

【讨论】:

  • 如果你试一试,你可能会发现它并没有你想象的那么多额外的代码——你需要做的就是将现有的代码分散到几个类中。但是,是的,有时好的设计需要更多的代码。可理解性和可维护性应该是比原始行数更重要的考虑因素。
  • 实现起来很痛苦,但至少现在我可以做一些事情,比如跟踪当前请求并停止/重试它。
猜你喜欢
  • 2010-11-20
  • 1970-01-01
  • 2013-02-17
  • 2012-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
相关资源
最近更新 更多