【问题标题】:Returning an NSArray to an ivar from a completion Handler从完成处理程序将 NSArray 返回到 ivar
【发布时间】:2015-01-07 07:17:50
【问题描述】:

自 2 天以来,我有点卡住了。我正在尝试使用新的 Twitter-Fabric-Kit 显示带有 twitter-user 时间线的 UITableView(我遵循了本指南:https://dev.twitter.com/twitter-kit/ios/show-tweets)。 我尝试这样做:通过 JSON 从某个用户那里获取 Tweet-ID,并将其放入实例变量中。这部分正在工作。问题 - 到目前为止我发现了这一点 - 是数组被传递给完成处理程序中的实例变量,但它似乎是异步运行的。我已经尝试用 GCD 解决这个问题,但我没有运气。也许有人可以指出正确的方向,甚至我的解决方案是废话并且有更好的方法;-)

#import "TweetTableViewController.h"

static NSString * const TweetTableReuseIdentifier = @"TwitterCell";

@interface TweetTableViewController ()

@property (nonatomic, strong) NSArray *tweetArray;
@property (nonatomic, strong) TWTRTweetTableViewCell *prototypeCell;

@end

@implementation TweetTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self createTweetArray];
//  .... tableView setup is here ...    

//    If I uncomment the next line the whole thing works!
//    NSArray *test = @[@"517330786857795584", @"516652595021352960"];

    __weak typeof(self) weakSelf = self;
    [[[Twitter sharedInstance]APIClient]loadTweetsWithIDs:self.tweetArray completion:^(NSArray *tweets, NSError *error) {
        if (tweets) {
            typeof(self) strongSelf = weakSelf;
            strongSelf.tweetArray = tweets;
            [strongSelf.tableView reloadData];
        } else {
            NSLog(@"Failed to load tweet: %@", [error localizedDescription]);
        }
    }];
}

- (void)createTweetArray {
        NSMutableArray *tempArray = [NSMutableArray array];
        [[Twitter sharedInstance]logInGuestWithCompletion:^(TWTRGuestSession *guestSession, NSError *error) {
            if (guestSession) {
                NSString *timeline = @"https://api.twitter.com/1.1/statuses/user_timeline.json";
                NSDictionary *parameters = @{@"user_id" : @"345330869"};
                NSError *clientError;
                NSURLRequest *request = [[[Twitter sharedInstance]APIClient]URLRequestWithMethod:@"GET"
                                                                                             URL:timeline
                                                                                      parameters:parameters
                                                                                           error:&clientError];
                if (request) {
                    [[[Twitter sharedInstance]APIClient]sendTwitterRequest:request completion:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                        if (data) {
                            NSError *jsonError;
                            NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
                            for (NSDictionary *dic in json) {
                                [tempArray addObject:[dic objectForKey:@"id_str"]];
                            }
                            [self handleJSONData:tempArray];
                        } else {
                            NSLog(@"Error: %@", connectionError);
                        }
                    }];
                } else {
                    NSLog(@"Error: %@", clientError);
                }
            }
        }];
}

- (void)handleJSONData:(NSMutableArray *)array {
    self.tweetArray = [NSArray arrayWithArray:array];
    NSLog(@" %@", self.tweetArray);
}

当我使用这段代码运行我的应用程序时,我在控制台中看到了以下日志:

2014-11-10 22:08:41.447 [65550:3869433] numberOfSectionsInTableView
2014-11-10 22:08:41.448 [65550:3869433] numberOfSectionsInTableView
2014-11-10 22:08:41.448 [65550:3869433] numberOfRowsInSection: 0
2014-11-10 22:08:41.448 [65550:3869433] numberOfSectionsInTableView
2014-11-10 22:08:41.448 [65550:3869433] numberOfRowsInSection: 0
2014-11-10 22:08:41.449 [65550:3869433] numberOfSectionsInTableView
2014-11-10 22:08:41.450 [65550:3869433] numberOfRowsInSection: 0
2014-11-10 22:08:43.426 [65550:3869433] (
    517330786857795584,
    516652595021352960,
    514841221907243008,
    513704220600848384,
    513598624706875392,
    513598609603178496,
    513598594017132544,
    513598581471969280,
    513598566502502400,
    513229247117545472,
    511424250138611713,
    509025219584212992,
    505655616338407424,
    500357644226285568,
    474861008314322944,
    469938745438109697,
    468465457750888449,
    464706315924041728,
    464704566492418048,
    457148030731694080
)

self.tweetArray 数组应该用于 numberOfRowsInSection 以及数据源,但该块似乎完成得很晚。如前所述,我尝试了 dispatch_async 和 dispatch_sync 但似乎没有任何效果。我最后的想法是 handleJSONData: 方法中的 [self.tableView reloadData] ,但这使我的应用程序崩溃。使用静态数组,tableView 正在工作...

感谢您的意见,我真的被困在这里......

【问题讨论】:

  • 您可以在handleJSONData: 中添加[self.tableView reloadData] 时的崩溃日志吗?对我来说,这似乎是一个合乎逻辑的想法。实际上,您的问题只是您的UITableView 在您获取数据之前加载得太早(因此,没有什么可显示的),您必须在获取后重新加载它。
  • ...“甚至我的解决方案都是废话...”不要对自己太苛刻。给猫剥皮的方法有一百万种,没有一种方法是正确的。嘿,只要效果足够好
  • 正如 Ckuota 所说,在加载表之前,您需要等待完成块完成。在数组加载时显示进度条。 stackoverflow.com/questions/22914753/…
  • @Ckouta :我现在不在我的 Mac 上,无法提供崩溃日志,但它在不同的时间点和numberOfRowsInSection: 20 崩溃。所以,我猜它会因为数组而崩溃?!但是NSArray *test = @[@"517330786857795584", @"516652595021352960"](这个有效)和上面填充数组的方式有区别吗?两者都是字符串,我已经检查过了。
  • @heikomania 嗨,您还需要帮助吗?如果您需要,我会发布答案。

标签: ios objective-c json twitter objective-c-blocks


【解决方案1】:

在您的 handleJSONData: 方法中设置断点并验证它是否在主队列上运行。

如果它不在主队列上运行,则无法更新 UI,例如在 self.tableView 上调用 reloadData

要在主队列上运行更新,您可以使用 GCD:

dispatch_async(dispatch_get_main_queue(),
^{
   [self.tableView reloadData]
});

或 NSOperationQueue:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    [self.tableView reloadData]
}];

【讨论】:

    【解决方案2】:

    完成处理程序将始终在调用它的代码完成后完成。这就是异步代码的工作方式。是的,您应该重建在完成处理程序中提供表格视图数据源的数据结构,然后调用 reloadData。如果这崩溃了,那是因为错误,而不是因为这样做是错误的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-24
      • 2019-01-24
      • 1970-01-01
      • 1970-01-01
      • 2021-07-31
      • 2016-06-02
      • 1970-01-01
      相关资源
      最近更新 更多