2013-08-20 64 views
0

我的應用啓動時有一個加載了一堆ALAssets的單例。這導致主線程在將每個圖像加載到內存中時凍結超過10秒。顯然是一個很大的否定。運行包含塊的後臺線程

我試圖把它放在後臺線程上,但它只是部分執行。

+ (CCPhotos*) sharedPhotos 
{ 
    static CCPhotos* shared = nil; 

    if (!shared) 
    { 
     shared = [[CCPhotos alloc] init]; 

     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

     dispatch_async(queue, ^{ 
      [shared loadPhotosArray]; 
     }); 

    } 

    return shared; 
} 


- (void) loadPhotosArray 
{ 
    NSLog(@"Loading photos"); 
    _photos = [[NSMutableArray alloc] init]; 

    NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey: @"savedImages"]; 
    if (data) 
    { 
     NSArray* storedUrls = [[NSArray alloc] initWithArray: [NSKeyedUnarchiver unarchiveObjectWithData: data]]; 

     // reverse array 
     NSArray* urls = [[storedUrls reverseObjectEnumerator] allObjects]; 

     for (NSURL* assetUrl in urls) 
     { 
      NSLog(@"Looking up %@", assetUrl); 

      // Block to handle image handling success 
    // This initializes, but doesn't get called 
////-->>  
      ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) 
      { 
       ALAssetRepresentation *rep = [myasset defaultRepresentation]; 
       CGImageRef iref = [rep fullScreenImage]; 
       if (iref) { 
        UIImage* tempImage = [UIImage imageWithCGImage:iref]; 
        UIImage* image = [[UIImage alloc] initWithCGImage: tempImage.CGImage scale: 1.0 orientation: UIImageOrientationUp]; 

        // Set image in imageView 
        [_photos addObject: image]; 
        NSLog(@"Added photo with url: %@", [rep url]); 
        [[NSNotificationCenter defaultCenter] postNotificationName: @"PhotosChanged" object: self]; 
       } 
      }; 

      // Handles failure of getting image 
      ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror) 
      { 
       NSLog(@"Can't get image - %@",[myerror localizedDescription]); 
      }; 

      // Load image then call appropriate block 
      ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init]; 
      [assetslibrary assetForURL: assetUrl 
          resultBlock: resultblock 
          failureBlock: failureblock]; 
     } 
    } 
    else 
    { 
     NSLog(@"Photo storage is empty"); 
    } 
} 

我已經將問題縮小到了ALAssetsLibraryAssetForURLResultBlock resultblock,它沒有被調用。多個線程在開始時產生,每個線程都到達這一行,初始化結果塊,但不調用它。我認爲這與塊上的線程安全有關。有什麼想法嗎?

回答

0

嘗試這樣做,當你發佈通知:

dispatch_async(dispatch_get_main_queue(), ^{ 
    [[NSNotificationCenter defaultCenter] postNotificationName: @"PhotosChanged" object: self]; 
}); 

我相信它不是爲你工作的原因是因爲這是不是被稱爲主線程上。必須在主線程上執行所有UI更改/更新(我認爲這會導致此更新/更新)。這將迫使通知發生在必要的線程上,並應該正常工作!

這是一件很常見的事情。其實,我創建了一個代碼片段,因爲我發現自己打字這一點經常:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    <#on back thread#> 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     <#on main thread#> 
    }); 
}); 

我再設置完成捷徑dispatch_async

+0

也許我錯誤地解釋了我的問題,但問題是整個'ALAssetsLibraryAssetForURLResultBlock resultblock',它不被稱爲 – Chris

+0

啊,它調用失敗塊嗎?或者根本沒有阻止? – Firo

+0

都不叫。當我做'[shared loadPrayArray]''時,它們會被正確調用,而不會在新線程中產生它。此外,感謝那個片段:)它肯定會派上用場,我正在努力學習所有關於線程的知識。 – Chris

0

從什麼,我的理解,你是旋轉起來的多個實例你的單身。在這種情況下,你可能會想要在那裏放一個@synchronized塊。例如:

+ (CCPhotos*) sharedPhotos 
{ 
    static CCPhotos* shared = nil; 

    @synchronized ([CCPhotos class]) 
    { 
    if (!shared) 
    { 
     shared = [[CCPhotos alloc] init]; 

     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

     dispatch_async(queue, ^{ 
      [shared loadPhotosArray]; 
     }); 

    } 
    } 

    return shared; 
} 

希望有幫助。