Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/106.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 块中的块不知道该做什么_Ios_Objective C - Fatal编程技术网

Ios 块中的块不知道该做什么

Ios 块中的块不知道该做什么,ios,objective-c,Ios,Objective C,我把事情搞得一团糟,试图找出一个熟练的方法来处理这个问题,但我被卡住了。我现在的问题是,在我希望代码被执行之前,我已经执行了代码,这与我的块有关 下面代码的问题是,在添加我的convertedimage之前,正在调用并执行postToForm方法。我如何修复此问题,使其等待发生?还是我完全走错了路??(我也需要了解内存使用情况,在发布帖子后需要释放内存。) 以下是我的代码,其中包含问题: // create serial queue dispatch_queue_t queue = dispat

我把事情搞得一团糟,试图找出一个熟练的方法来处理这个问题,但我被卡住了。我现在的问题是,在我希望代码被执行之前,我已经执行了代码,这与我的块有关

下面代码的问题是,在添加我的
convertedimage
之前,正在调用并执行
postToForm
方法。我如何修复此问题,使其等待发生?还是我完全走错了路??(我也需要了解内存使用情况,在发布帖子后需要释放内存。)

以下是我的代码,其中包含问题:

// create serial queue
dispatch_queue_t queue = dispatch_queue_create("myQueue", 0);

// create dispatch group
dispatch_group_t group = dispatch_group_create();

for(id photos in photoUrls) {
    NSString *urlString = photos;

    // enqueue operation in queue
    dispatch_async(queue, ^{
        // enter the group
        dispatch_group_enter(group);

        // do something async, I do use another dispatch_queue for example
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
            // wrap in autoreleasepool to release memory upon completion
            @autoreleasepool {
                // here for example the nested operation sleeps for two seconds
                NSURL *url = [NSURL URLWithString:urlString];
                ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

                [library assetForURL:url resultBlock:^(ALAsset *asset) {

                    //TODO: Deal with JPG or PNG
                    NSData *imageData = UIImageJPEGRepresentation([self thumbnailForAsset:asset maxPixelSize:1000], 0);
                    NSString *base64 = [imageData base64EncodedString];
                    NSLog(@"base64::%@",base64);
                    [convertedImages addObject:base64];

                } failureBlock:^(NSError *error) {
                    NSLog(@"that didn't work %@", error);
                }];


                dispatch_group_leave(group);
            }
        });

        // wait until the nested async operation leaves the group (e.g finishes its job)
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

        NSLog(@"Finished single operation.");
    });
}

// will be called once all operations complete
dispatch_async(queue, ^{
    NSLog(@"Finished all jobs. ");
    NSLog(@"how many::%lu",(unsigned long)convertedImages.count);
    [jsonWithPhotos setObject:convertedImages forKey:@"photo64"];
    [self postToForm];
});

如果您有依赖项,则需要使用NSOperationQueues。使用操作队列,您可以设置操作之间的依赖关系,以便一个(或多个)操作在特定操作完成之前不会执行

因此,例如,使用块(就像您拥有的块)可以实现如下所示

NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock:^{ /* your work */ }];
NSBlockOperation* dependentOperation = [NSBlockOperation blockOperationWithBlock:^{ /* dependent work */ }];

[dependentOperation addDependency:operation];

NSOperationQueue* q = [[NSOperationQueue alloc] init];
[q addOperations:@[ operation, dependentOperation] waitUntilFinished:NO];
NSOperationQueues还为您带来了一些好处,比如能够处理取消,如果您担心在其他地方出现故障时取消postToForm,这会很有用

如果您担心内存问题,可以将最大并发操作数设置为NSOperationQueue的一部分

q.maxConcurrentOperationCount = 5; 

如果您想使用dispatch_async来完成所有这些,那么您就必须使用稍微不同的功能。从我能告诉你的情况来看,你只是想在后台做这一切。有几种不同的方法可以做到这一点,但我看到您的代码在后台线程的单个块中运行,然后在完成后调用。这也是最有效的内存(不是膨胀),因为它一次只运行一个转换,而不是试图一次完成所有转换并填满可用内存(可能会崩溃)


自动释放池中包装所有这些内容,只是为了增加内存管理的乐趣。

在加载所有图像之前调用完成块的原因是您正在调用
调度组\u离开(组)在错误的位置。您应该在库的结果块(和错误块)中调用它。其余部分是正确的(事实上,正如苹果建议的那样,实现队列的完成块:因为GCD的私有队列是串行的,所以完成块只不过是队列本身的最后一个块)

编辑:按要求: 事实上,AlassetLibrary需要一些时间来提取请求url处的数据(事实上,有一个完成块,提示操作是异步的)。因此,在请求当前url的图像后,您立即释放了由
dispatch\u group\u enter
创建的信号量,这可能是在库执行完成块之前发生的

现在,请注意,您如何实现队列的完成块仅对串行队列有效,在iOS 5+中,您可以通过将
调度队列\u并发
指定为队列类型来创建并发队列(与全局队列一样),这种方法不再有效。如果您没有串行队列,而是有一个并发队列,在本例中,我会检查当前url是否是AlassetLibrary结果块中的最后一个,并在那里调用完成块

为了完整性,您可以使用
dispatch\u semaphore\u t
来处理这种情况,这在逻辑上比使用组等待(这里您的组由1个操作组成)更正确,但是,我重复一下,这只是在逻辑上更好,结果是相同的


我写的所有东西都写在

中,为什么要麻烦将循环中的每个任务作为单独的异步作业来运行呢?将整个循环作为单个任务运行,并在该完成处理程序中调用主线程上的函数来postToForm

差不多

   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 
                                         (unsigned long)NULL), ^(void) {
      [self convertImages];

   });

   // Call this on background thread
   - (void)convertImages {

      for(id photos in photoUrls) {
         // Do stuff  
      }

      // Now call function on main thread
      [[NSOperationQueue mainQueue] addOperationWithBlock:^ {
              [self updateUI];
      }];
    }

    // Must call this on main thread because we update the UI
    - (void)updateUI {
           NSLog(@"Finished all jobs. ");
           NSLog(@"how many::%lu",(unsigned long)convertedImages.count);
           [jsonWithPhotos setObject:convertedImages forKey:@"photo64"];
           [self postToForm];
    }

这是否意味着我需要使用不同的方法来执行块,或者我可以用我所拥有的实现NSOperationQueues?如果我正确理解您的代码,我相信您可以创建所有图像处理操作,然后创建最终的post操作。可以将post操作的依赖项设置为依赖于所有图像处理操作。图像处理操作将包括自动释放池中的所有内容。这回答了你的问题吗?哦,老兄,我花了这么多时间才得到这么简单的答案!想解释一下为什么它能正常工作吗?
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 
                                         (unsigned long)NULL), ^(void) {
      [self convertImages];

   });

   // Call this on background thread
   - (void)convertImages {

      for(id photos in photoUrls) {
         // Do stuff  
      }

      // Now call function on main thread
      [[NSOperationQueue mainQueue] addOperationWithBlock:^ {
              [self updateUI];
      }];
    }

    // Must call this on main thread because we update the UI
    - (void)updateUI {
           NSLog(@"Finished all jobs. ");
           NSLog(@"how many::%lu",(unsigned long)convertedImages.count);
           [jsonWithPhotos setObject:convertedImages forKey:@"photo64"];
           [self postToForm];
    }