ObjC设计 - 从异步“模型”代码中请求用户输入

时间:2014-05-14 02:43:44

标签: ios objective-c

我希望这不是一个愚蠢的问题,但我需要向用户询问输入,并且需要在与UI异步执行的代码的上下文中。我在幕后与服务器通信,而用户可能正在UI上做其他事情。在通信期间的某个时刻,需要来自用户的输入(诸如密码之类的东西)。

我的问题不在于如何获取信息,我可以使用AlertView或主队列上的某些内容轻松获取信息。对我来说不合适的是将UI代码放入我的模型代码中。我有一个负责网络通信的类,并且从该上下文中实例化UI元素看起来就像是糟糕的设计。

我考虑过使用NSNotificationCenter来广播用户输入或使用委托的需要。问题是,没有特定的ViewController可以作为委托,因为当需要这些信息时,用户可以在任何屏幕上,我不想在每个ViewController中复制通知处理代码。这离开了应用代表。

因此,在iOS开发的世界中,人们通常只是将UI代码留在模型中,或者将代码放在app委托中,还是有其他一些我缺少的设计替代方案?

3 个答案:

答案 0 :(得分:2)

委托并不总是必须是对象的实例。它可能只是一个班级!代表中的协议方法必须以" +"让班级回应他们。我确实遇到过你的情况,因为我喜欢保持模型代码(非ui相关)干净。根据您的具体情况,可能还有其他解决方法。

但是,如果有许多对象必须侦听您的事件,那么通知就是解决方案。相反,如果你只需要提供一个输入视图,那么只需要一个委托(你不会有多个viewControllers同时显示输入视图你是不是)。

以下是将类作为委托提供的示例:

[[DatabaseUpdateModel alloc] initWithDelegate: (id)[DatabaseUpdateModelDelegate class]];

并且在DatabaseUpdateModelDelegate.m的实现中,您将拥有例如:

+(void) databaseUpdateModel:(DatabaseUpdateModel*)dbModel didFinishDownloadWithDatabasePath:(NSURL*)path
{
    //present UI element to rename database (or whatever the input is for);
}

+(void) databaseUpdateModel:(DatabaseUpdateModel*)dbModel didFaceNetworkError:(NSError*)error
{
    //present UI element to notify the user of the error;
}

DatabaseUpdateModel当然不是最好的名字;我只是这样命名就提出了我的观点..

使用这种方法,如果多个对象需要侦听事件,DatabaseUpdateModelDelegate类也可以发出通知。这样你就可以避免你的模型不必要地发送通知(无论是否正在收听)。代表完成所有工作:)

答案 1 :(得分:1)

您可以通过让GUI为模型提供块来将GUI代码与模型代码分离出来,只要执行GUI操作,该模块就会被调用。因此,GUI与模型分离,只是在适当的时候由模型调用。

如果你有一个视图控制器控制器,你可以使用委托或NSNotificationCenter,即一个元视图控制器,它没有与之关联的视图,但管理所有其他视图控制器(如果需要),并可以在顶部显示提示GUI在需要的时候,有什么看法。

答案 2 :(得分:1)

在我看来,您应该使用以下标准:

  1. 代码是否正确?
  2. 代码可以理解吗?
  3. 代码是否易于更新?
  4. 代码是否易于调试?
  5. 代码是否模块化,以便您可以轻松地将其移动到新项目中?
  6. (不容忽视)代码是否易于实现?
  7. 在这种情况下,使用NSNotification是一个合理的选择,可能会传递用户界面代码的委托,以便在用户输入用户名时使用。密码。请记住,即使用户输入用户名/密码,视图仍应保留在屏幕上,直到网络代码验证完毕。

    或者,您可以使用所需的方法公开AppDelegate。这就是我们的工作。例如:

    @protocol PasswordViewProtocol
    -(void) showPasswordDialog:(NetworkObject*)delegate;  // delegate gets called when user hits "Login" with username+password
    -(void) hidePasswordDialog;     // used if a networking error occurs
    -(void) passwordWasIncorrect;   // show a red message in the view indicating an error occurred
    -(void) passwordWasCorrect;     // remove the view, perhaps save the username+password
    @end
    
    @interface AppDelegate : UIResponder<UIApplicationDelegate, PasswordViewProtocol>
    @end
    
    @interface UIApplication(typedDelegate)
    + (AppDelegate*)typedDelegate;
    @end
    

    然后你可以用以下代码调用代码:

    [UIApplication.typedDelegate showPasswordDialog:myNetworkObject];
    

    还有很多其他方法可以做同样的事情,但这符合标准。