【问题标题】:iOS MVC - How to pass data from model to controller?iOS MVC - 如何将数据从模型传递到控制器?
【发布时间】:2012-07-08 11:42:17
【问题描述】:

我对此进行了相当多的研究,但我对我的问题有一个心理障碍。我正在为 iOS 应用开发 Objective-C

这是我的设置:

  1. 视图控制器从视图(用户输入)获取文本,并将该文本传递给模型的 MethodA。

  2. 模型中的 MethodA 作用于输入文本并获得输出(例如,在 google 中搜索该文本)。它使用 dispatch_async 方法进行搜索,该方法将选择器调用到模型中的 MethodB。

  3. MethodB 解析输出并将所有结果放入 NSMutableArray

  4. 我的问题:如何将 NSMutableArray 传递回视图控制器,以便在视图上显示它?

抱歉,如果我的问题的答案非常简单/显而易见。我是 Objective-C 的新手

【问题讨论】:

  • 你在使用 Core Data 吗?我不确定我个人是否完全理解你的问题。解析输出的 MethodB 是什么?
  • 抱歉,我的问题不清楚。方法 A 使用 dispatch_async 调用 Web 服务。 dispatch_async 的选择器在完成获取原始数据(NSData)后调用方法 B。方法 B 解析来自 NSData 的 JSON 回复并将这些结果放入 NSMutableArray。我没有使用核心数据。 Core Data 是实现这一点的更好方法吗?
  • MethodA 和 MethodB 只是视图控制器内部的方法?
  • 不,它们在 Model 类中

标签: objective-c ios model-view-controller


【解决方案1】:

任何时候我想要进行异步处理并且这些东西需要回到 UI 的某个地方,我会做以下两件事之一:

1. Use NSNotification to tell anyone who cares that the work is complete
2. Use a delegate property on the worker and a @protocol

1 NSNotification

模型对象应该在它的 .h 文件中记录当某些事情发生时它会触发通知;例如当模型的一部分被更新时。当 ViewController 初始化模型对象时,让它自己设置为记录通知的观察者,并实现一个更新 UI 的回调。

2 委托和@protocol

使用正确命名的方法(例如fooObjectDidUpdate:(Foo *)object;)创建@protocol(例如@protocol FooModelUpdateDelegate),然后模型类具有id<FooModelUpdateDelegate> updateDelegate 的委托属性,并且ViewController 将自身设置为该委托,我确定剩下的你可以自己解决。

【讨论】:

  • 只是补充一点,如今,区块是 IMO 的一种更好的方式。
【解决方案2】:

我想传递一个响应选择器方法的委托对象并使用处理后的数据调用此方法将是实现程序应得的松散耦合结构的好方法。您是否熟悉这个概念,或者我应该为您挖掘一些代码示例?


更新:代码示例

所以,我可能会使用调用类,比如MyViewController,来实现回调方法,myCallbackMethod,如下所示:

-(void) myCallbakcMethod: NSMutableArray* array {
    //DoWhatever with the returned data
}

关键是在计算完成时将结果传递回此方法。 因此,在您调用 MethodAMyViewController 中,您传递对委托的引用以处理结果,即 self

//From this:
[MyModel methodA:param1]
//To:
[MyModel methodA:param1:self]

MyModels methodAmethodB 需要添加一个参数 (id)delegate 并在调用之间传递。

在数据myArray 准备好的methodB 中,执行以下调用:

    if([delegate respondsToSelector:@selector(myCallbackMethod:)]])
        [observer performSelector:@selector(myCallbackMethod:) withObject:myArray];

【讨论】:

  • 我认为这正是我想要实现的(在看到你的回复之前我不确定这是否可行)。代码示例肯定会对我有所帮助。谢谢!
  • 这太棒了!这正是我想要的。
【解决方案3】:

在您的视图控制器中:

    // your controller code
    ...
    [myModel getSearchResult:searchKeyword receiver:self action:@selector(responseReceived:)];
}

- (void)responseReceived:(MyModel *)model
{   
    NSArray *searchResult = model.searchResult; 
    [model release], model = nil;
    // some view actions, for instance update your table view
    ...
}

在您的模型中:

...
- (id)getSearchResult:(NSString *)searchKeyword receiver:(id)aReceiver action:(SEL)receiverAction {
    self.receiver = aReceiver;
    self.action = receiverAction;
    // some async actions
}

在异步响应接收器中:

    ...
    [self.receiver performSelector:self.action withObject:self];
}

【讨论】:

  • 那你在哪里处理http错误呢?我可以有一个更完整的例子吗?谢谢:)
  • 使用 AFNetworking 可以节省很多时间。它使用块而不是选择器。 github.com/AFNetworking/AFNetworking/tree/master/Example/…
  • 谢谢!这就是我正在使用的。然后我将 AFNetworking 调用移动到模型数据中,然后再次包装它。在这些块中,最初我触发了通知......现在我通过向包装器方法添加块来更改为对成功和失败块的调用。感谢您为我指明正确的方向!
【解决方案4】:

除非我误解了您的描述,否则听起来您的“模型”课程做得比它应该做的更多。在这种情况下,它至少完成了控制器的一些工作。我的建议是将 methodA 和 methodB 折叠到视图控制器(或另一个控制器类)中。方法 B 仍然可以设置“模型”实例的 NSMutableArray 属性,如果这是必要的(或者如果不是,则跳过该步骤)。

【讨论】:

    【解决方案5】:
    -(void)methodA {
        NSMutableArray *someArray = ...
        [self methodB:someArray];
    }
    
    -(void)methodB:(NSMutableArray*)array {
        NSLog(@"%@", array);
        // do something with the array, like update the view
    }
    

    但如果两者都是视图控制器内部的方法,为什么不直接更新方法内部的视图而不是将其传递给另一个方法呢?

    【讨论】:

    • 这就是我最初的代码。我在我的 ViewController 中完成了所有这些工作。但我一直读到 Model 应该负责处理数据,尤其是处理逻辑,所以这就是我想在 Model 中实现类似功能的原因。感谢您的回复。
    • 不一定。在视图控制器中处理一些数据是可以的。但是,如果您正在查看很多内容,请使用委托方法从模型与您的视图控制器进行通信。你也可以看看使用积木,这些太棒了。
    • 同意块很棒。我在 dispatch_async 中使用它们,它们使用起来非常简单。我应该尝试将数据从模型传回另一个控制器。
    猜你喜欢
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-26
    • 1970-01-01
    相关资源
    最近更新 更多