【问题标题】:correct using NSURLConnection正确使用 NSURLConnection
【发布时间】:2023-03-09 09:07:01
【问题描述】:

我正在开发应用程序,它使用 NSURLConnection 发送和接收 JSON 数据,但我在 viewcontroller 中有这个连接及其 delagate 方法,我猜这对于 MVC 是不正确的。我想要整个连接的单独类,但是当连接完成加载时,我无法在视图控制器中检测到问题,所以我无法接收到数据。这样做的正确方法是什么?

但是,viewcontrollers 中的这个洞(非 MVC)NSURLConnection 对我的应用程序来说工作得很好,除了一种情况 - 当我需要使用 tableview 时,它是 viewcontroller 的一部分 - 它也是这个 tableview 的数据源和委托。似乎 tableview 正在尝试在连接完成加载之前创建单元格,我认为这有点奇怪,因为在方法 tableView:numberOfRowsInSection: 我已经有我需要的数据,我认为在我配置之前调用了这个方法tableView:CellForRowAtIndexPath: 中的单元格:...但我可能错了。有人可以解释一下这里发生了什么以及如何解决这个问题吗? (也是正确使用 MVC 和 NSURLConnection 的第一部分)

【问题讨论】:

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


    【解决方案1】:

    至于问题的第一部分,如果您满足以下条件,您可以获得更多的 MVC 设计:

    1. 在模型类中实现您的 JSON/NSURLConnection 内容,它还实现委托协议并对响应进行所有必要的处理;

    2. 当响应被处理时,视图控制器被发送一个消息;您可以为此定义一个自定义委托(即,您发送到在 ad-hoc 协议中定义的控制器的特定消息),或者简单地使用通知,这允许更多的解耦并且可能更容易实现(但更多运行时昂贵);

    3. 视图控制器的职责是在收到该消息后更新 UI 以反映新数据。

    关于您问题的第二部分,表格视图通常会在必须重绘自身时立即创建单元格,即在数据存在之前(因为这需要时间)。

    您需要做的是让表格自己绘制为空(可能显示 UI 的“加载”位)并在通知视图控制器已接收并处理数据时在表格上调用reloadData

    如果您遵循上述指导原则,根据 MVC 使您的设计更加解耦,这将是很自然的。

    编辑:关于你的最后一个问题:

    我不知道您如何以及在何处创建 myArray 对象,但是,作为一般规则,我希望它是您的数据源对象的 ivar(如果我没有理解错误的话);所以,当你第一次创建它时,你应该确保它被保留;稍后,当您完成数据源时,您在dealloc 中发布它。您可以通过以下几种可能的方式之一保留myArray,例如:

     myArray = [[NSArray alloc] init...];
    

    在这种情况下,alloc 已经为您提供了一个保留对象;或:

     myArray = [[NSArray arrayWith...] retain];
    

    在这种情况下,您需要保留便利构造函数返回的对象(它返回一个自动释放的对象);

     self.myArray = [NSArray arrayWith...];
    

    在这种情况下,如果 myArray 属性声明为 retain,则不需要保留。

    在上述所有情况下,您所做的是确保对象的保留计数至少为 1,以便在某些时候它不会被框架释放。不这样做意味着在某个时间点您的对象将自动解除分配,这很可能发生在您的数据存在之前,即在执行tableView:cellForRowAtIndexPath 之前。

    希望这会有所帮助...

    【讨论】:

    • 我发现返回行数和节数的方法在 tableView:cellForRowAtIndexPath 之前被调用 - 就像我在我的问题中写的......虽然我的数组没有填充一些对象, tableView:NumberOfRowsInSection 返回 0 ( [myArray count] ) ,所以方法 tableView:cellForRowAtIndexPath 甚至没有被调用......这个方法在数组被对象填充后第一次调用......
    • ........奇怪的是,当我在 viewcontroller 类中的任何地方使用 [[myArray objectAtIndex:0] objectForKey:@"myKey"] 时,一切都很好,但是当我在 tableView:cellForRowAtIndexPath 方法中使用它,应用程序崩溃与 EXC_BAD_ACCESS
    • 我保留了数组,现在它可以工作了......但我不明白为什么没有它它就不能工作......你能解释一下吗?谢谢
    【解决方案2】:

    为您的 JSON 客户端类实现委托协议,例如:

    @protocol JSONClientDelegate <NSObject>
    ...
    - (void) connectionFinishedLoading;
    ...
    @end
    
    @interface JSONClient
    {
        id<JSONCLientDelegate> delegate;
    }
    @property (nonatomic, assign) id<JSONClientDelegate> delegate;
    -(void) getJSON;
    @end
    
    @implementation JSONClient
    
    - (void) getJSON
    {
        ...
        [NSURLConenction connectonWithRequest:request delegate:self];
        ...
    }
    
    - connectionDidFinishLoading:(NSURLConnection*) connection
    {
        [delegate connectionFinishedLoading];
    }
    
    @end
    

    然后,让您的视图控制器实现委托协议:

    @interface MyViewController : UIViewController <JSONClientDelegate>
    ...
    - (void) doFoo;
    ...
    @end
    
    @implementation MyViewController
    
    - (void) doFoo
    {
        ...
        JSONClient* client = [JSONClient new];
        client.delegate = self;
    
        [client getJSON];
        ...
    }
    
    - (void) connectionFinishedLoading
    {
        // Connection finished - do things here.
    }
    
    @end
    

    请注意,这是一个非常简略的示例 - 我已经削减了一些角落以节省一些空间。我相信您可以阅读字里行间并填补空白 - 如果不是(即我的示例不清楚),请告诉我,我会进一步详细说明。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-29
      • 1970-01-01
      • 1970-01-01
      • 2014-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多