繁体   English   中英

iOS - Thread不会回到主线程

[英]iOS - Thread does not going back to the main thread

我的线程有问题。 在线程忙碌之后,我在2个屏幕之间发生了几次。 线程不执行每一行..,断点只是在必须返回主线程时消失。 有人能帮帮我吗 ?

我在卸载视图时释放线程。

谢谢,

- (void)fetchFeedDataIntoDocument
{
    NSString * labelString = [NSString stringWithFormat:@"Feed Fetcher %@", self.pageTitle];
    const char *label = [labelString UTF8String];

    self.fetchF = dispatch_queue_create(label, NULL);
    dispatch_async(self.fetchF, ^{

        NSArray *feeds = [FeedFetcher getDataForJson:self.pageTitle downloadBy:@"up"];

        NSDictionary *lastfeed;

        AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];

        NSManagedObjectContext *context = [appDelegate getManagedObjectContext];

        if ([feeds count] > 0)
        {
            lastfeed = [feeds objectAtIndex:0];

            [FeedFetcher setLastUpdateIdToCatgorie:self.pageTitle WithId:[lastfeed objectForKey:@"id"] AndPulishDate:[lastfeed objectForKey:@"publish_up"]];
        }

        for (NSDictionary *feedInfo in feeds) {
            [Feed FeedWithInfo:feedInfo InManageObject:context];
        }

        NSError *error = nil;

        [context save:&error];

        if (error){
            NSLog(@"Error save : %@", error);}

        dispatch_async(dispatch_get_main_queue(), ^{
            [self setupFetchedResultsController];
            [self.tableView reloadData];
            [self downloadImagesForFeeds:feeds];
        });

    });

您从与创建它的位置不同的线程访问managedObjectContext。 这是核心数据线程规则#1。

您正在从应用代表处获取MOC。 如果它是正常的Xcode生成的MOC,那么它是使用线程限制并发创建的。 你甚至不能用它调用performBlock。 您只能从主线程访问该MOC。 期。 充其量只是玩火,充其量。

如果要在单独的线程中完成所有工作,还需要单独的MOC。 像这样(只是键入 - 未编译)...

NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
moc.parentContext = appDelegate.managedObjectContext;
[moc performBlock:^{
    // Go get your remote data and whatever you want to do

    // Calling save on this MOC will push the data up into the "main" MOC
    // (though it is now in the main MOC it has not been saved to the store).
    [moc save:&error];
}];

哪个会翻译成这样的......

- (void)fetchFeedDataIntoDocument
{
    NSString * labelString = [NSString stringWithFormat:@"Feed Fetcher %@", self.pageTitle];
    const char *label = [labelString UTF8String];

    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *mainContext = [appDelegate getManagedObjectContext];
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    context.parentContext = mainContext;
    [context performBlock:^{    
        NSArray *feeds = [FeedFetcher getDataForJson:self.pageTitle downloadBy:@"up"];

        NSDictionary *lastfeed;


        if ([feeds count] > 0)
        {
            lastfeed = [feeds objectAtIndex:0];

            [FeedFetcher setLastUpdateIdToCatgorie:self.pageTitle WithId:[lastfeed objectForKey:@"id"] AndPulishDate:[lastfeed objectForKey:@"publish_up"]];
        }

        for (NSDictionary *feedInfo in feeds) {
            [Feed FeedWithInfo:feedInfo InManageObject:context];
        }

        NSError *error = nil;

        [context save:&error];

        if (error){
            NSLog(@"Error save : %@", error);}
DO you really want to continue on error?
        dispatch_async(dispatch_get_main_queue(), ^{
            // Data has been pushed into main context from the background
            // but it still needs to be saved to store...
            // Do not forget to perform error handling...
            NSError *error = nil;
            [mainContext save:&error];
            [self setupFetchedResultsController];
            [self.tableView reloadData];
            [self downloadImagesForFeeds:feeds];
        });

    });

编辑

Xcode生成的用于创建MOC的代码使用init,它使用NSConfinementConcurrencyType。 您可以使用MainConcurrency替换它,没有任何问题,但可以获得多种好处。

在您的app委托文件中,替换...

    __managedObjectContext = [[NSManagedObjectContext alloc] init];

有了这个...

    __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

现在,您的主要MOC可以是“父级”,您也可以在其上调用performBlock。

更改以下代码..

   dispatch_queue_t queue1 = dispatch_queue_create("com.MyApp.AppTask",NULL);
   dispatch_queue_t main = dispatch_get_main_queue();
   dispatch_async(queue1, 
               ^{
                   dispatch_async(main, 
                                  ^{
                                      [self setupFetchedResultsController];
                                      [self.tableView reloadData];
                                      [self downloadImagesForFeeds:feeds];

                                  });

               });  

希望这个能对您有所帮助

这样做...

-(void)functionToCallFetch {

     [self performSelectorInBackground:@selector(fetchFeedDataIntoDocument) withObject:nil];

} 

- (void)fetchFeedDataIntoDocument
{

     NSArray *feeds = [FeedFetcher getDataForJson:self.pageTitle downloadBy:@"up"];

        NSDictionary *lastfeed;

        AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];

        NSManagedObjectContext *context = [appDelegate getManagedObjectContext];

        if ([feeds count] > 0)
        {
            lastfeed = [feeds objectAtIndex:0];

            [FeedFetcher setLastUpdateIdToCatgorie:self.pageTitle WithId:[lastfeed objectForKey:@"id"] AndPulishDate:[lastfeed objectForKey:@"publish_up"]];
        }

        for (NSDictionary *feedInfo in feeds) {
            [Feed FeedWithInfo:feedInfo InManageObject:context];
        }

        NSError *error = nil;

        [context save:&error];

        if (error){
            NSLog(@"Error save : %@", error);}

        //dispatch_async(dispatch_get_main_queue(), ^{
        //    [self setupFetchedResultsController];
        //    [self.tableView reloadData];
        //    [self downloadImagesForFeeds:feeds];
        //});
        [self performSelectorOnMainThread:@selector(setupFetchedResultsController) withObject:nil waitUntilDone:NO];
        [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
        [self performSelectorOnMainThread:@selector(downloadImagesForFeeds:) withObject:feeds waitUntilDone:NO];


}

也许这会更好?

您是否尝试构建如下方法:

- (void)methodToBePerformedOnMainThread{
        [self setupFetchedResultsController];
        [self.tableView reloadData];
        [self downloadImagesForFeeds:feeds];
}

并称之为

[self performSelectorOnMainThread:@selector(methodToBePerformedOnMainThread) withObject:nil waitUntilDone:NO];

fetchFeedDataIntoDocument

编辑:

您是否尝试用NSOperationQueue代替dispatch_queue来包装它?

喜欢 :

NSOperationQueue *operationQueue = [NSOperationQueue new];

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(fetchFeedDataIntoDocument) object:nil];

if(operation != nil){
    [operationQueue addOperation:operation];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM