I am creating an iOS application that allows the user to take a picture and save it in a user album, which fills the UICollectionView in the application with photos from the album. I found many examples on the Internet on how to do this, but I could not get past the stubborn problem with the very last picture that did not appear on the album. I ended up using notifications and a sequential send queue, but I think it can be improved.
This is how I save the photos and then re-populate the UICollectionView:
I built a method to call when I need to list a photo album (viewDidLoad and once when I received ALAssetsLibraryChangedNotification).
-(void)setupCollectionView {
_assets = [@[] mutableCopy];
__block NSMutableArray *tmpAssets = [@[] mutableCopy];
ALAssetsLibrary *assetsLibrary = [ProfileViewController defaultAssetsLibrary];
[assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if ([[group valueForProperty:ALAssetsGroupPropertyName] isEqualToString:albumName]) {
if (group == nil){
return;
}
NSLog(@"Refresh pictures - %d",[group numberOfAssets]);
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
if (group!=nil) {
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if(result){
[tmpAssets addObject:result];
}else{
*stop = YES;
}
}];
}
self.assets = tmpAssets;
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
[self.collectionView.collectionViewLayout invalidateLayout];
});
}
} failureBlock:^(NSError *error) {
NSLog(@"Error loading images %@", error);
}];
}
, , , , , , , . ( "" ), , .
, ALAssets, ALAssetsLibraryChangedNotification, . , :
- (void) handleAssetChangedNotifiation:(NSNotification *)notification {
NSDictionary *userInfo = notification.userInfo;
NSSet *updateAssets = userInfo[ALAssetLibraryUpdatedAssetsKey];
if (updateAssets.count>0) {
dispatch_sync(photoLoadQueue, ^{
[self setupCollectionView];
});
}
}
. , - ALAssetLibraryUpdatedAssetsKey, , , , . , , :
Received notification: NSConcreteNotification 0x15ed4af0 {name = ALAssetsLibraryChangedNotification; object = <ALAssetsLibrary: 0x15db9e80>; userInfo = {
ALAssetLibraryUpdatedAssetGroupsKey = "{(\n assets-library://group/?id=43E80EF8-EA91-4C71-AFD2-EBDCB53A1D53\n)}";
ALAssetLibraryUpdatedAssetsKey = "{(\n assets-library://asset/asset.JPG?id=63E43AF3-3729-43E9-806C-BE463116FDA2&ext=JPG,\n assets-library://asset/asset.JPG?id=FA2ED24E-DF0F-49A3-85B8-9C181E4077A4&ext=JPG,\n assets-library://asset/asset.JPG?id=A0B66E2E-6EA1-462C-AD93-DB3087BA65D8&ext=JPG\n)}";}}
Received notification: NSConcreteNotification 0x15d538c0 {name = ALAssetsLibraryChangedNotification; object = <ALAssetsLibrary: 0x15db9e80>; userInfo = {
ALAssetLibraryUpdatedAssetsKey = "{(\n assets-library://asset/asset.JPG?id=FBDD2086-EC76-473F-A23E-4F4200C0A6DF&ext=JPG\n)}";}}
Received notification: NSConcreteNotification 0x15dc9230 {name = ALAssetsLibraryChangedNotification; object = <ALAssetsLibrary: 0x15db9e80>; userInfo = {}}
Received notification: NSConcreteNotification 0x15df5b40 {name = ALAssetsLibraryChangedNotification; object = <ALAssetsLibrary: 0x15db9e80>; userInfo = {}}
Received notification: NSConcreteNotification 0x15d6a050 {name = ALAssetsLibraryChangedNotification; object = <ALAssetsLibrary: 0x15db9e80>; userInfo = {}}
Received notification: NSConcreteNotification 0x15d379e0 {name = ALAssetsLibraryChangedNotification; object = <ALAssetsLibrary: 0x15db9e80>; userInfo = {
ALAssetLibraryUpdatedAssetGroupsKey = "{(\n assets-library://group/?id=1E76AFA7-89B4-4277-A175-D7C8E62E49D0&filter=1,\n assets-library://group/?id=1E76AFA7-89B4-4277-A175-D7C8E62E49D0\n)}";
ALAssetLibraryUpdatedAssetsKey = "{(\n assets-library://asset/asset.JPG?id=FBDD2086-EC76-473F-A23E-4F4200C0A6DF&ext=JPG\n)}";
Received notification: NSConcreteNotification 0x15df7bf0 {name = ALAssetsLibraryChangedNotification; object = <ALAssetsLibrary: 0x15db9e80>; userInfo = {
ALAssetLibraryUpdatedAssetGroupsKey = "{(\n assets-library://group/?id=8E390051-E107-42BC-AE55-24BA35966642\n)}";}}
Received notification: NSConcreteNotification 0x15d40360 {name = ALAssetsLibraryChangedNotification; object = <ALAssetsLibrary: 0x15db9e80>; userInfo = {
ALAssetLibraryUpdatedAssetsKey = "{(\n assets-library://asset/asset.JPG?id=5A45779A-C3C1-4545-9BD6-88F094FFA5B9&ext=JPG\n)}";}}
? , , , , . - ? , , .
, , (, , , , , , ):
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *originalImage, *editedImage, *imageToSave;
editedImage = (UIImage *) [info objectForKey:UIImagePickerControllerEditedImage];
originalImage = (UIImage *) [info objectForKey:UIImagePickerControllerOriginalImage];
if (editedImage) {
imageToSave = editedImage;
}else {
imageToSave = originalImage;
}
__block ALAssetsGroup* groupToAddTo;
ALAssetsLibrary *assetsLibrary = [ProfileViewController defaultAssetsLibrary];
[[NSNotificationCenter defaultCenter] removeObserver:self name:ALAssetsLibraryChangedNotification object:nil];
[assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if ([[group valueForProperty:ALAssetsGroupPropertyName] isEqualToString:albumName]) {
NSLog(@"found album %@", albumName);
groupToAddTo = group;
CGImageRef img = [imageToSave CGImage];
[assetsLibrary writeImageToSavedPhotosAlbum:img orientation: alOrientation completionBlock:^(NSURL* assetURL, NSError* error) {
if (error.code == 0) {
[assetsLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {
if ([groupToAddTo valueForProperty:ALAssetsGroupPropertyURL] == nil){
NSLog(@"group properties are nil!");
}else {
if([groupToAddTo addAsset:asset]){
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAssetChangedNotifiation:) name:ALAssetsLibraryChangedNotification object:nil];
}else {
NSLog(@"Image Not Added!");
}
}
}
failureBlock:^(NSError* error) {
NSLog(@"failed to retrieve image asset:\nError: %@ ", [error localizedDescription]);
}];
}else {
NSLog(@"saved image failed.\nerror code %i\n%@", error.code, [error localizedDescription]);
}
}];
}}
failureBlock:^(NSError* error) {
NSLog(@"failed to enumerate albums:\nError: %@", [error localizedDescription]);}];
[picker dismissViewControllerAnimated:YES completion:NULL];
}