NSMutableArray 在 for 循环后不保存添加的项目

Posted

技术标签:

【中文标题】NSMutableArray 在 for 循环后不保存添加的项目【英文标题】:NSMutableArray does not hold added items after for loop 【发布时间】:2012-12-27 22:18:45 【问题描述】:

我尝试进行 Facebook Graph 调用并将一些项目添加到数组中。这些项目被添加到一个 for 循环中,并且数组看起来很好。但是在 for 循环之后,这些项目就消失了。

我使用带有 Facebook SDK 3.1 的 xcode 4.5。

我错过了什么?

TableViewController.m

#import "TableViewController.h"

@interface TableViewController ()
@end

@implementation TableViewController 
    NSMutableArray *recipes;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 
        // Custom initialization
    
    return self;


- (void)viewDidLoad

    [super viewDidLoad];
    recipes = [NSMutableArray arrayWithObjects:@"Egg Benedict", nil];
    [recipes addObject:@"foobar"];
    NSLog(@"recipes before FBRquestConnection: %@", recipes);

    [FBRequestConnection
     startWithGraphpath:@"search?type=place&center=37.785834,-122.406417"
     completionHandler:^(FBRequestConnection *connection,
                         id result,
                         NSError *error) 
         if (!error) 
             for (id item in [result objectForKey:@"data"]) 
                [recipes addObject:[item objectForKey:@"name"]];
             
         NSLog(@"recipes after for-loop: %@", recipes);
         NSLog(@"amount of recipes after for-loop: %u", [recipes count]);
         
     ];
    NSLog(@"amount of recipes after FBRequestConnection: %u", [recipes count]);

调试控制台输出

2012-12-27 23:09:44.056 barbar[3481:19a03] recipes before FBRquestConnection: (
    "Egg Benedict",
    foobar
)
2012-12-27 23:09:44.056 barbar[3481:19a03] amount of recipes after FBRequestConnection: 2
2012-12-27 23:09:44.516 barbar[3481:19a03] recipes after for-loop: (
    "Egg Benedict",
    foobar,
    "Union Square, San Francisco",
    "Benefit Cosmetics",
    "San Francisco | The Official Guide",
    "BareMinerals by Bare Escentuals",
    "Viator.com",
    "Bleacher Report",
    "Downtown San Francisco",
    "AMC Metreon 16",
    "Cheesecake Factory",
    SquareTrade,
    "Westfield San Francisco Centre",
    "Bloomingdale's San Francisco",
    "Macy's San Francisco Union Square",
    Xoom,
    "Parc 55 Hotel",
    "Pottery Barn",
    "AT&T Park",
    Bebo,
    Snapfish,
    "Hilton San Francisco Union Square",
    uTorrent,
    "The Westin St. Francis",
    TRUSTe,
    "Apple Retail Store - San Francisco"
)
2012-12-27 23:09:44.516 barbar[3481:19a03] amount of recipes after for-loop: 26

干杯——杰里克

【问题讨论】:

这里有什么问题,这对我来说很好。您正在执行异步操作,所以日志发生的顺序可能令人困惑? 代码运行良好。日志显示了 for 循环之后的所有对象。你为什么不认为这是有效的?请记住,连接块外部(之后)的日志语句在 for 循环实际执行之前被调用。这是因为连接块是在后台线程上完成的。 【参考方案1】:

您的项目被添加到图形调用的完成块中。

当您执行 Api 调用时,它会转到服务器,并且在 Web 请求与您的结果一起返回之前不会触发完成块。

因此,当您的最后一行命中时,仍在请求 api 调用并且尚未返回。

【讨论】:

好的。这解释了调试输出的接线顺序。我的问题是,在 Iphone-Simulator 中只有项目显示在表视图中。所以不知何故我必须等到请求完成,然后应该加载表格视图......但是我该怎么做呢? [tableView reloadData] 是最简单的方法。但是还有其他命令可以让您插入新项目并将它们淡入,而不是从头开始重新加载表格视图。我会调查那些。但现在 reloadData 命令会让你开始运行。【参考方案2】:

如果你想让它在块对象中可变,我认为你需要在声明中添加__block(我曾经遇到过一些问题)。现在范围仅在块内被抑制。

还可以查看此链接以获取有关块内变量范围的更多信息。

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/Blocks/Articles/bxVariables.html

【讨论】:

【参考方案3】:

您的完成块正在随机线程上触发。块背后的想法是设置它并忘记它。我的意思是,您不能保证知道该完成块何时会触发。可能是 2 秒后,也可能是 2 分钟。

为了说明这一点,设置两个断点:一个在 viewDidLoad 方法的顶部,另一个在完成块内,然后开始单步执行代码。您会看到块外的断点被命中。当您逐步进入完成块时,您不会在块内移动。相反,您直接越过它并进入您的最后一个 NSLog 语句,这就是为什么您认为您只获得原始 2 个对象的原因。继续执行您的程序,块内的断点将被触发。

这应该有助于表明完成块在之后的某个不确定时间被触发,并且您的数组实际上很好。

【讨论】:

以上是关于NSMutableArray 在 for 循环后不保存添加的项目的主要内容,如果未能解决你的问题,请参考以下文章

从 NSMutableArray 中删除 for 循环中的对象

Java 多层for循环循环第三次程序就卡在里面某个循环里面后不执行了

为啥我在嵌套的 for 循环中分配 OpenCV Mat 对象后不包含预期值?

pytest 如何在第一项断言失败后不退出 for 循环

在 NSMutableArray 中管理 UIControls

以最节省内存的方式循环自定义对象的 NSMutableArray