我有一个单例,当我的应用程序启动时会加载一堆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 :(得分: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
答案 1 :(得分: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;
}
希望有所帮助。