ios - 为什么当我在应用程序加载后将项目添加到 Core Data 时,它们直到我点击单元格才会显示? (然后只有那个显示。)

标签 ios objective-c cocoa-touch uiviewcontroller slrequest

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

我正在构建一个与 iOS 上的 Twitter API 交互的应用程序(使用 native 操作系统访问,而不是通过 Web API)。我将项目发送到核心数据,然后它应该显示在我使用 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 正常运行。将整个 block 包裹在:

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

关于ios - 为什么当我在应用程序加载后将项目添加到 Core Data 时,它们直到我点击单元格才会显示? (然后只有那个显示。),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22363162/

相关文章:

iphone - UIControlEventTouchDragInside 问题

objective-c - 对大量缺失的、非常基本的 Objective-C 类进行故障排除

ios - 如何在 iOS 上以编程方式截断两行表格单元格中的尾部

iPhone 4 相机不透明度

iphone - 如何使用 GCD 在后台定期运行代码块?

ios - 在 Xcode 7 中使用 AutoLayout 将 5 个 subview 均匀地分布在其父 View 的宽度上

ios - 警告 : attempt to present ViewController whose view is not in the window hierarchy

ios - viewForHeaderInSection 绘制背景,但前提是 View 位于屏幕顶部

ios - 为什么 swift 中的 var++ 是错误的,而改成 var+1 是正确的

ios - CloudKit 和 GameCenter 在游戏中?