在类/异步请求/ iOS之间传递数据

Ste*_*oom 5 oop iphone objective-c ipad ios

我正在将我的应用程序从Syncronous转换为Asyncronous HTTP请求,并遇到了一个问题,看起来它需要对应用程序处理其数据的方式进行相当大的改动.让我试着解释一下

以前它是这样的:

- Class1,Class2并且Class3都是UIViewController -Helper类 - 内容显示类的子类

他们做的事情差别很大,但共同的特点是他们与助手班级的互动.它们以多种不同的方式从用户收集请求的详细信息,然后最终向帮助程序类发送请求.
当它同步完成时,助手类将返回数据.然后,每个类将解释数据(XML文件)并通过segue将它们传递给Content显示类

所以大致如下:

1类:

//Get user input
SomeData *data = [helperclass makerequest];
id vcData = [data process];
[self performSegueWithIdentifier:@"segueIdentifier"];
---
- (void)prepareForSegue:(UIStoryboardSegue *)segue
{
    DestinationViewController *destination = (DestinationViewController *)segue.destinationViewController;
    destination.data = vcData;
}
Run Code Online (Sandbox Code Playgroud)

内容显示类:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.data presentdata];
}
Run Code Online (Sandbox Code Playgroud)

现在看起来像这样

我通过首先使它与Class1一起使用来处理这个问题,以便将修复程序部署到class2和class3.所以class1和helper现在就像这样交互

1类:

//Get user input
SomeData *data = [helperclass makerequestWithSender:self];
id vcData = [data process];
[self performSegueWithIdentifier:@"segueIdentifier"];
---
- (void)prepareForSegue:(UIStoryboardSegue *)segue
{
    DestinationViewController *destination = (DestinationViewController *)segue.destinationViewController;
    destination.data = vcData;
} 
Run Code Online (Sandbox Code Playgroud)

现在我面临的最大问题是如何从helperclass获取数据Class1.我设法让它工作

(void)makeRequestWithSender:(Class1*)sender
{
  [NSURLConnection sendAsynchronousRequest:...
     {
        [sender sendData:data];
     }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我把它推到另外2个GUI类别时,这将构成我遇到困难的请求.我的第一个想法是设置,sender:(id)但在线路上[sender sendData:data]告诉我id没有方法sendData:或类似的失败.

希望我在这里不是太模糊,你们可以提供帮助.如果需要,我将能够发布代码片段但是现在任何人都可以帮助更好地建议如何构造此请求的代码?

sch*_*bob 6

您基本上想要使用'观察者模式'或(可能)略微更改的设置,因此您可以使用委托.

观察者模式

您可以通过NSNotificationCenterNSNotifications获得机制.您的3个不同的UIViewController子类每个都订阅一个特定的NSNotification,您可以通过NSNotificationCenter发布通知来通知它们.

以下代码是如何在viewcontroller子类中处理问题的示例:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // subscribe to a specific notification
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomethingWithTheData:) name:@"MyDataChangedNotification" object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];  
    // do not forget to unsubscribe the observer, or you may experience crashes towards a deallocated observer
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
...
- (void)doSomethingWithTheData:(NSNotification *)notification {
    // you grab your data our of the notifications userinfo
    MyDataObject *myChangedData = [[notification userInfo] objectForKey:@"myChangedDataKey"];
    ...
}
Run Code Online (Sandbox Code Playgroud)

在您的助手类中,在数据更改后,您必须通知观察者,例如

-(void)myDataDidChangeHere {
    MyDataObject *myChangedData = ...;
    // you can add you data to the notification (to later access it in your viewcontrollers)
    [[NSNotificationCenter defaultCenter] postNotificationName:@"MyDataChangedNotification" object:nil userInfo:@{@"myChangedDataKey" : myChangedData}];
}
Run Code Online (Sandbox Code Playgroud)

通过@protocol

假设所有UIViewController子类都驻留在父视图控制器中,您可以在助手类中实现协议,并使父视图控制器成为委托.然后,父视图控制器可以通过传递消息来通知子视图控制器.

您的帮助程序类声明可能如下所示(假设ARC):

@protocol HelperDelegate;

@interface Helper : NSObject

@property (nonatomic, weak) id<HelperDelegate> delegate;

...
@end

@protocol HelperDelegate <NSObject>

-(void)helper:(Helper *)helper dataDidChange:(MyDataObject*)data;

@end
Run Code Online (Sandbox Code Playgroud)

在帮助程序实现中,您将通过以下方式通知代理:

...
if ([self.delegate respondsToSelector:@selector(helper:dataDidChange:)]) {
    [self.delegate helper:self dataDidChange:myChangedDataObject];
}
...
Run Code Online (Sandbox Code Playgroud)

您的父视图控制器需要是辅助类的委托并实现其协议; 在宣言中粗略草图

@interface ParentViewController : UIViewController <HelperDelegate>
Run Code Online (Sandbox Code Playgroud)

并在短版本中实施

// you alloc init your helper and assign the delegate to self, also of course implement the delegate method

-(void)helper:(Helper *)helper dataDidChange:(MyDataObject*)data {
    [self.myCustomChildViewController doSomethingWithTheNewData:data];
}
Run Code Online (Sandbox Code Playgroud)

除了..

你可能会问自己喜欢哪种方法.两者都是可行的,主要的区别在于,通过观察者模式,您可以"立即"获得更多对象,而协议只能有一个代理,并且必须在必要时转发消息.关于利弊的讨论很多.一旦你下定决心,我建议你阅读它们(抱歉没有足够的声誉发布超过两个链接,所以请搜索stackoverflow).如果不清楚,请询问.