usar tiene como objective-c ios7 ios8 alassetslibrary photosframework

objective c - tiene - Marco de AssetsLibrary roto en iOS 8



iphone 10 tiene nfc (6)

Me encontré con un problema en iOS 8 con el marco de la Biblioteca de activos que parece ser un error en iOS 8. Si creo un álbum llamado ''MyMedia'' y luego lo elimino, cuando intento crear el álbum de nuevo, este fragmento del código a continuación devuelve ''nil'' que indica que existe el álbum ''MyMedia'' aunque no lo haga porque lo eliminé usando la aplicación ''Fotos''.

__block ALAssetsGroup *myGroup = nil; __block BOOL addAssetDone = false; NSString *albumName = @"MyMedia"; [assetsLib addAssetsGroupAlbumWithName:albumName resultBlock:^(ALAssetsGroup *group) { myGroup = group; addAssetDone = true; } failureBlock:^(NSError *error) { NSLog( @"failed to create album: %@", albumName); addAssetDone = true; }]; while (!addAssetDone) { [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05f]]; } return myGroup; // returns nil if group has previously been created and then deleted

Este mismo método funciona al crear un nuevo álbum ''MyMedia2''. ¿Alguien más ha experimentado este problema y conoce una solución alternativa? ¿Es la única solución para pasar al nuevo marco de "Fotos" o estoy haciendo algo incorrecto aquí? Tenga en cuenta que este código siempre funciona en iOS7.X

En realidad, los pasos para reproducir este problema son los siguientes:> 1. Desinstale su aplicación que toma fotos y las guarda en un álbum personalizado. 2. En iOS Photos, elimine el álbum personalizado que tiene fotos guardadas en él. 3. Instale su aplicación. 4. Si toma fotos o graba videos con la aplicación, no los crea ni los almacena. Si miras en los álbumes de fotos de iOS, el álbum personalizado no existe y no aparece ninguna de las imágenes / videos tomados con la aplicación.


Solo quería actualizar a todos los que debería haber actualizado antes, pero me llené de trabajo. Este problema es / era un problema con iOS 8 pero se ha corregido con iOS 8.0.2, así que todo lo que necesita hacer para solucionarlo es actualizar su iOS a iOS 8.0.2


Mi respuesta anterior fue incorrecta. Realmente no lo había probado. Finalmente descubrí lo que tenía que hacerse y fue difícil, pero lo hice funcionar. Esto es lo que tuve que hacer para que mi aplicación se ejecutara tanto en iOS 7.xX como en iOS 8.Xx y cree un álbum personalizado que la aplicación eliminó previamente ->

  1. Escribí dos fragmentos de código: uno que usa el marco de Fotos en iOS 8.xx y otro que usa el marco de AssetsLibrary en iOS 7.xx

  2. Si la aplicación se podía ejecutar en ambas versiones de iOS, vinculé la aplicación al marco de Photos, pero luego la cambié de obligatoria a opcional para que no se cargara en iOS 7.xx

  3. Como el código de la infraestructura de Photos no se podía invocar directamente en el tiempo de ejecución en iOS 7.xx, tuve que cambiarlo para que cargara las clases, las funciones (y los bloques) dinámicamente en el tiempo de ejecución

Aquí está el fragmento de código que funciona cuando se ejecuta en un iPhone. Esto debería funcionar en el simulador también ->

// PHPhotoLibrary_class will only be non-nil on iOS 8.x.x Class PHPhotoLibrary_class = NSClassFromString(@"PHPhotoLibrary"); if (PHPhotoLibrary_class) { /** * iOS 8..x. . code that has to be called dynamically at runtime and will not link on iOS 7.x.x ... [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title]; } completionHandler:^(BOOL success, NSError *error) { if (!success) { NSLog(@"Error creating album: %@", error); } }]; */ // dynamic runtime code for code chunk listed above id sharedPhotoLibrary = [PHPhotoLibrary_class performSelector:NSSelectorFromString(@"sharedPhotoLibrary")]; SEL performChanges = NSSelectorFromString(@"performChanges:completionHandler:"); NSMethodSignature *methodSig = [sharedPhotoLibrary methodSignatureForSelector:performChanges]; NSInvocation* inv = [NSInvocation invocationWithMethodSignature:methodSig]; [inv setTarget:sharedPhotoLibrary]; [inv setSelector:performChanges]; void(^firstBlock)() = ^void() { Class PHAssetCollectionChangeRequest_class = NSClassFromString(@"PHAssetCollectionChangeRequest"); SEL creationRequestForAssetCollectionWithTitle = NSSelectorFromString(@"creationRequestForAssetCollectionWithTitle:"); [PHAssetCollectionChangeRequest_class performSelector:creationRequestForAssetCollectionWithTitle withObject:albumName]; }; void (^secondBlock)(BOOL success, NSError *error) = ^void(BOOL success, NSError *error) { if (success) { [assetsLib enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *stop) { if (group) { NSString *name = [group valueForProperty:ALAssetsGroupPropertyName]; if ([albumName isEqualToString:name]) { groupFound = true; handler(group, nil); } } } failureBlock:^(NSError *error) { handler(nil, error); }]; } if (error) { NSLog(@"Error creating album: %@", error); handler(nil, error); } }; // Set the success and failure blocks. [inv setArgument:&firstBlock atIndex:2]; [inv setArgument:&secondBlock atIndex:3]; [inv invoke]; } else { // code that always creates an album on iOS 7.x.x but fails // in certain situations such as if album has been deleted // previously on iOS 8...x. . [assetsLib addAssetsGroupAlbumWithName:albumName resultBlock:^(ALAssetsGroup *group) { handler(group, nil); } failureBlock:^(NSError *error) { NSLog( @"Failed to create album: %@", albumName); handler(nil, error); }]; }


Usando la respuesta de Adam, y la Categoría de Marin Todorov en ALAssetsLibrary, ALAssetsLibrary + Custom PhotoAlbum para crear álbumes de fotos, y colocar fotos en ellos, este código a continuación reemplaza el workhorse principal en esa categoría, funciona en dispositivos iOS7 y dispositivos iOS 8.1 para aquellos que necesitan tener ambos.

sin embargo, da dos advertencias sobre performSelector en la clase desconocida, se aprecian mejoras:

(No copiará una foto de un álbum compartido que no haya creado y fallará con el mensaje, cualquier mejora allí también sería buena)

1) agregar los marcos de "Fotos", establecer a "opcional"

2) incluye la línea de importación # import <Photos / PHPhotoLibrary.h>

//---------------------------------------------------------------------------------------- - (void)addAssetURL:(NSURL *)assetURL toAlbum:(NSString *)albumName completion:(ALAssetsLibraryWriteImageCompletionBlock)completion failure:(ALAssetsLibraryAccessFailureBlock)failure { NSLog(); __block BOOL albumWasFound = NO; //----------------------------------------- ALAssetsLibraryGroupsEnumerationResultsBlock enumerationBlock; enumerationBlock = ^(ALAssetsGroup *group, BOOL *stop) { NSLog(@" ALAssetsLibraryGroupsEnumerationResultsBlock"); // Compare the names of the albums if ([albumName compare:[group valueForProperty:ALAssetsGroupPropertyName]] == NSOrderedSame) { NSLog(@"--------------Target album is found"); // Target album is found albumWasFound = YES; // Get a hold of the photo''s asset instance // If the user denies access to the application, or if no application is allowed to // access the data, the failure block is called. ALAssetsLibraryAssetForURLResultBlock assetForURLResultBlock = [self _assetForURLResultBlockWithGroup:group assetURL:assetURL completion:completion failure:failure]; [self assetForURL:assetURL resultBlock:assetForURLResultBlock failureBlock:failure]; // Album was found, bail out of the method *stop = YES; } if (group == nil && albumWasFound == NO) { NSLog(@"--------------Target album does not exist"); // Photo albums are over, target album does not exist, thus create it // Since you use the assets library inside the block, // ARC will complain on compile time that there’s a retain cycle. // When you have this – you just make a weak copy of your object. ALAssetsLibrary * __weak weakSelf = self; // If iOS version is lower than 5.0, throw a warning message if (! [self respondsToSelector:@selector(addAssetsGroupAlbumWithName:resultBlock:failureBlock:)]) { NSLog(@"--------------Target album does not exist and does not respond to addAssetsGroupAlbumWithName"); } else { NSLog(@"--------------Target album does not exist addAssetsGroupAlbumWithName"); // ----------- PHPhotoLibrary_class will only be non-nil on iOS 8.x.x ----------- Class PHPhotoLibrary_class = NSClassFromString(@"PHPhotoLibrary"); NSLog(@"PHPhotoLibrary_class %@ ", PHPhotoLibrary_class); if (PHPhotoLibrary_class) { NSLog(@"iOS8"); // --------- dynamic runtime code ----------- id sharedPhotoLibrary = [PHPhotoLibrary_class performSelector:NSSelectorFromString(@"sharedPhotoLibrary")]; NSLog(@"sharedPhotoLibrary %@ ", sharedPhotoLibrary); SEL performChanges = NSSelectorFromString(@"performChanges:completionHandler:"); NSMethodSignature *methodSig = [sharedPhotoLibrary methodSignatureForSelector:performChanges]; NSInvocation* inv = [NSInvocation invocationWithMethodSignature:methodSig]; [inv setTarget:sharedPhotoLibrary]; [inv setSelector:performChanges]; void(^firstBlock)() = ^void() { NSLog(@"firstBlock"); Class PHAssetCollectionChangeRequest_class = NSClassFromString(@"PHAssetCollectionChangeRequest"); SEL creationRequestForAssetCollectionWithTitle = NSSelectorFromString(@"creationRequestForAssetCollectionWithTitle:"); NSLog(@"PHAssetCollectionChangeRequest_class %@ ", PHAssetCollectionChangeRequest_class); [PHAssetCollectionChangeRequest_class performSelector:creationRequestForAssetCollectionWithTitle withObject:albumName]; }; void (^secondBlock)(BOOL success, NSError *error) = ^void(BOOL success, NSError *error) { NSLog(@"secondBlock"); if (success) { NSLog(@"success"); [self enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *fullStop) { if (group) { NSLog(@"group %@ ", group); NSString *name = [group valueForProperty:ALAssetsGroupPropertyName]; if ([albumName isEqualToString:name]) { NSLog(@"[albumName isEqualToString:name] %@ ", name); ALAssetsLibraryAssetForURLResultBlock assetForURLResultBlock = [self _assetForURLResultBlockWithGroup:group assetURL:assetURL completion:completion failure:failure]; [self assetForURL:assetURL resultBlock:assetForURLResultBlock failureBlock:failure]; *fullStop = YES; } } } failureBlock:failure]; } if (error) { NSLog(@"Error creating album: %@", error); } }; // Set the success and failure blocks. [inv setArgument:&firstBlock atIndex:2]; [inv setArgument:&secondBlock atIndex:3]; [inv invoke]; } else { NSLog(@"iOS7"); [self addAssetsGroupAlbumWithName:albumName resultBlock:^(ALAssetsGroup *createdGroup) { // Get the photo''s instance, add the photo to the newly created album ALAssetsLibraryAssetForURLResultBlock assetForURLResultBlock = [weakSelf _assetForURLResultBlockWithGroup:createdGroup assetURL:assetURL completion:completion failure:failure]; [weakSelf assetForURL:assetURL resultBlock:assetForURLResultBlock failureBlock:failure]; } failureBlock:failure]; } } // Should be the last iteration anyway, but just in case *stop = YES; } }; // Search all photo albums in the library [self enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:enumerationBlock failureBlock:failure]; }


Como ninguna de las sugerencias anteriores me ayudó, así es como resolví los problemas con el guardado de activos (fotos) en un nombre de álbum personalizado. Este código: "fetchCollectionResult.count == 0" maneja específicamente la situación cuando ha eliminado su álbum personalizado una vez y tratando de guardarlo nuevamente, ya que supongo que fetchCollectionResult podría dejar de ser ''nil''. Puede cambiar esto fácilmente para admitir también el guardado de videos / películas.

¡Este código es solo para iOS 8! ¡Debe asegurarse de no llamar si el dispositivo se ejecuta en versiones anteriores!

#define PHOTO_ALBUM_NAME @"MyPhotoAlbum" NSString* existingAlbumIdentifier = nil; -(void)saveAssetToAlbum:(UIImage*)myPhoto { PHPhotoLibrary* photoLib = [PHPhotoLibrary sharedPhotoLibrary]; __block NSString* albumIdentifier = existingAlbumIdentifier; __block PHAssetCollectionChangeRequest* collectionRequest; [photoLib performChanges:^ { PHFetchResult* fetchCollectionResult; if ( albumIdentifier ) fetchCollectionResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[albumIdentifier] options:nil]; // Create a new album if ( !fetchCollectionResult || fetchCollectionResult.count==0 ) { NSLog(@"Creating a new album."); collectionRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:PHOTO_ALBUM_NAME]; albumIdentifier = collectionRequest.placeholderForCreatedAssetCollection.localIdentifier; } // Use existing album else { NSLog(@"Fetching existing album, of #%d albums found.", fetchCollectionResult.count); PHAssetCollection* exisitingCollection = fetchCollectionResult.firstObject; collectionRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:exisitingCollection]; } NSLog(@"Album local identifier = %@", albumIdentifier); PHAssetChangeRequest* createAssetRequest; createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:myPhoto]; [collectionRequest addAssets:@[createAssetRequest.placeholderForCreatedAsset]]; } completionHandler:^(BOOL success, NSError *error) { if (success) { existingAlbumIdentifier = albumIdentifier; NSLog(@"added image to album:%@", PHOTO_ALBUM_NAME); } else NSLog(@"Error adding image to album: %@", error); }]; }


Puedes probar Mi método debajo para Crear álbum para iOS 7 e iOS 8

#define PHOTO_ALBUM_NAME @"AlbumName Videos" #pragma mark - Create Album -(void)createAlbum{ // PHPhotoLibrary_class will only be non-nil on iOS 8.x.x Class PHPhotoLibrary_class = NSClassFromString(@"PHPhotoLibrary"); if (PHPhotoLibrary_class) { // iOS 8..x. . code that has to be called dynamically at runtime and will not link on iOS 7.x.x ... [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:PHOTO_ALBUM_NAME]; } completionHandler:^(BOOL success, NSError *error) { if (!success) { NSLog(@"Error creating album: %@", error); }else{ NSLog(@"Created"); } }]; }else{ [self.library addAssetsGroupAlbumWithName:PHOTO_ALBUM_NAME resultBlock:^(ALAssetsGroup *group) { NSLog(@"adding album:''Compressed Videos'', success: %s", group.editable ? "YES" : "NO"); if (group.editable == NO) { } } failureBlock:^(NSError *error) { NSLog(@"error adding album"); }]; }}


Utilicé el siguiente código para comprobar si existe un álbum específico, y si no existe, créelo y añádale un par de imágenes. Después de crear un Asset desde un UIImage, uso su marcador de posición para agregarlo al álbum sin salir del bloque.

//Will enter only in iOS 8+ Class PHPhotoLibrary_class = NSClassFromString(@"PHPhotoLibrary"); if (PHPhotoLibrary_class) { [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^ { //Checks for App Photo Album and creates it if it doesn''t exist PHFetchOptions *fetchOptions = [PHFetchOptions new]; fetchOptions.predicate = [NSPredicate predicateWithFormat:@"title == %@", kAppAlbumName]; PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:fetchOptions]; if (fetchResult.count == 0) { //Create Album PHAssetCollectionChangeRequest *albumRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:kAppAlbumName]; //Add default photos to it NSMutableArray *photoAssets = [[NSMutableArray alloc] init]; for (UIImage *image in albumDefaultImages) { PHAssetChangeRequest *imageRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image]; [photoAssets addObject:imageRequest.placeholderForCreatedAsset]; } [albumRequest addAssets:photoAssets]; } } completionHandler:^(BOOL success, NSError *error) { NSLog(@"Log here..."); }]; }