为什么当我在应用程序加载后将项目添加到核心数据时,它们不会显示,直到我点击单元格?(然后只有那一个显示)



显示问题的示例项目: http://d.pr/f/g8x5

我正在构建一个与iOS上的Twitter API交互的应用程序(使用本地操作系统访问,而不是通过web API)。我将项目发送到Core Data,然后应该显示在使用NSFetchedResultsControllerUITableViewController中。

下面是我的cellForRowAtIndexPath:方法中的代码:

Tweet *tweet = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.nameLabel.text = tweet.name;
cell.screenNameLabel.text = [NSString stringWithFormat:@"@%@", tweet.screenname];
NSString *tweetText = tweet.text;
tweetText = [tweetText stringByReplacingOccurrencesOfString:@"&" withString:@"&"];
NSMutableAttributedString *tweetAttributedText = [[NSMutableAttributedString alloc] initWithString:tweetText];
// Color @usernames in tweet text for label
NSError *error;
NSRegularExpression *screenNameRegEx = [NSRegularExpression regularExpressionWithPattern:@"\B@[a-zA-Z0-9_]+" options:0 error:&error];
NSArray *screenNameMatches = [screenNameRegEx matchesInString:tweetText options:0 range:NSMakeRange(0, tweetText.length)];
for (NSTextCheckingResult *match in screenNameMatches) {
    [tweetAttributedText addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:31/255.0 green:121/255.0 blue:189/255.0 alpha:1.0] range:match.range];
}
// Color #hashtags
NSRegularExpression *hashtagRegEx = [NSRegularExpression regularExpressionWithPattern:@"\B#[a-zA-Z0-9_]+" options:0 error:&error];
NSArray *hashtagMatches = [hashtagRegEx matchesInString:tweetText options:0 range:NSMakeRange(0, tweetText.length)];
for (NSTextCheckingResult *match in hashtagMatches) {
    [tweetAttributedText addAttribute:NSForegroundColorAttributeName value:[UIColor lightGrayColor] range:match.range];
}
// Color links
NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:&error];
NSArray *linkMatches = [linkDetector matchesInString:tweetText options:0 range:NSMakeRange(0, tweetText.length)];
for (NSTextCheckingResult *match in linkMatches) {
    // Make sure it's not a telephone number link
    if (![match.URL.scheme isEqualToString:@"tel"]) {
        [tweetAttributedText addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:21/255.0 green:116/255.0 blue:255/255.0 alpha:1.0] range:match.range];
    }
}
cell.tweetTextLabel.attributedText = tweetAttributedText;
return cell;

然后在我的viewDidAppear中调用Twitter API并拉下新文章:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.accountStore = [[ACAccountStore alloc] init];
    // If user has logged into Twitter system-wide
    if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) {
        ACAccountType *twitterAccountType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
        [self.accountStore requestAccessToAccountsWithType:twitterAccountType options:nil completion:^(BOOL granted, NSError *error) {
            if (granted) {
                NSArray *twitterAccounts = [self.accountStore accountsWithAccountType:twitterAccountType];
                NSURL *requestURL = [NSURL URLWithString:@"https://api.twitter.com"
                                     @"/1.1/statuses/home_timeline.json"];
                NSDictionary *requestParameters = @{@"include_rts": @"0",
                                                    @"count": @"20"};
                SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:requestURL parameters:requestParameters];
                request.account = twitterAccounts[0];
                [request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
                    if (responseData) {
                        if (urlResponse.statusCode >= 200 && urlResponse.statusCode < 300) {
                            NSError *jsonError;
                            NSArray *homeTimelineData = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:&jsonError];
                            for (NSDictionary *tweetDictionary in homeTimelineData) {
                                NSManagedObjectContext *context = self.managedObjectContext;
                                Tweet *tweet = [NSEntityDescription insertNewObjectForEntityForName:@"Tweet" inManagedObjectContext:context];
                                tweet.text = [tweetDictionary objectForKey:@"text"];
                                tweet.name = [[tweetDictionary objectForKey:@"user"] objectForKey:@"name"];
                                tweet.screenname = [[tweetDictionary objectForKey:@"user"] objectForKey:@"screen_name"];
                                // Save the date of when the tweet was posted
                                NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                                dateFormatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";
                                tweet.date = [dateFormatter dateFromString:[tweetDictionary objectForKey:@"created_at"]];
                                NSError *error;
                                if (![context save:&error]) {
                                    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                                }
                            }
                        }
                    }
                }];
            }
            else {
            }
        }];
    }
    // If not logged in system-wide, alert user to log in via Settings
    else {
        UIAlertView *notLoggedInAlert = [[UIAlertView alloc] initWithTitle:@"Not Logged in to Twitter" message:@"You must be logged into Twitter. Go to the Settings app and log in from there." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [notLoggedInAlert show];
    }
}

但是实际上没有项显示,直到我点击每个单独的单元格,然后只有一个会显示。我觉得这是一个问题,主线程没有更新,但我不知道发生了什么。

我到底做错了什么?

再看一遍,SLRequest回调是在后台线程上进行的,这会阻止CoreData和UIKit正常工作。

:
dispatch_async(dispatch_get_main_queue(), ^{
    if (urlResponse.statusCode >= 200 && urlResponse.statusCode < 300) {
    ...
    }
});

你需要实现NSFetchedArrayController委托方法并将自己设置为取回控制器的委托。这样,当获取的内容发生变化时,你就会收到通知。

最新更新