ALAssetsLibrary assetForURL: siempre devolviendo cero para fotos en "My Photo Stream" en iOS 8.1
ios8.1 (5)
Este código funcionó bien en iOS 7, pero en iOS 8.1, todos los activos ubicados en el álbum "My Photo Stream" son nulos dentro del bloque de resultados. (No se llama a failureBlock). Los álbumes normales y los álbumes compartidos funcionan bien.
Intenté la respuesta aceptada de: Error al intentar asignar __block ALAsset dentro de assetForURL: resultBlock:
Es decir, estoy sosteniendo una referencia a un objeto ALAssetsLibrary, escuchando el evento ALAssetsLibraryChangedNotification
(lo que no ocurre por cierto, pero bueno.) Me aseguré de que mi aplicación tenga permiso para acceder a las fotos, estoy en el wi-fi , Veo las miniaturas de las fotos muy bien en mi tableView. Es solo cuando intento cargarlos con assetForURL:
siempre son nulos.
// example URL: assets-library://asset/asset.JPG?id=1ECB69B9-DC7A-45A7-B135-F43317D3412C&ext=JPG
[self.library assetForURL:[NSURL URLWithString:url] resultBlock:^(ALAsset *asset) {
NSLog(@"Asset: %@", asset); // nil :(
} failureBlock:^(NSError *error) {
NSLog(@"Failure, wahhh!");
}];
¿Alguien más está viendo este problema?
Desde iOS 8.0 y versiones posteriores, debe utilizar el marco de Fotos en lugar del marco de la Biblioteca de recursos.
Después de no encontrar ninguna respuesta para esto en ningún lugar, creé la siguiente extensión de PHAsset que funciona muy bien a partir de iOS 8.2, aunque supongo que es teóricamente lento. Aunque uno de los comentarios anteriores dice que esto está arreglado en iOS8.2 beta, el error todavía estaba presente para mí ahora que se lanzó iOS8.2.
import Photos
import UIKit
extension PHAsset {
class func fetchAssetWithALAssetURL (alURL: NSURL) -> PHAsset? {
let phPhotoLibrary = PHPhotoLibrary.sharedPhotoLibrary()
let assetManager = PHImageManager()
var phAsset : PHAsset?
let optionsForFetch = PHFetchOptions()
optionsForFetch.includeHiddenAssets = true
var fetchResult = PHAsset.fetchAssetsWithALAssetURLs([alURL], options: optionsForFetch)
if fetchResult?.count > 0 {
return fetchResult[0] as? PHAsset
} else {
var str = alURL.absoluteString!
let startOfString = advance(find(str, "=")!, 1)
let endOfString = advance(startOfString, 36)
let range = Range<String.Index>(start:startOfString, end:endOfString)
let localIDFragment = str.substringWithRange(range)
let fetchResultForPhotostream = PHAssetCollection.fetchAssetCollectionsWithType(PHAssetCollectionType.Album, subtype: PHAssetCollectionSubtype.AlbumMyPhotoStream, options: nil)
if fetchResultForPhotostream?.count > 0 {
let photostream = fetchResultForPhotostream![0] as PHAssetCollection
let fetchResultForPhotostreamAssets = PHAsset.fetchAssetsInAssetCollection(photostream, options: optionsForFetch)
if fetchResultForPhotostreamAssets?.count >= 0 {
var stop : Bool = false
for var i = 0; i < fetchResultForPhotostreamAssets.count && !stop; i++ {
let phAssetBeingCompared = fetchResultForPhotostreamAssets[i] as PHAsset
if phAssetBeingCompared.localIdentifier.rangeOfString(localIDFragment, options: nil, range: nil, locale: nil) != nil {
phAsset = phAssetBeingCompared
stop = true
}
}
return phAsset
}
}
return nil
}
}
}
He observado que intentar recuperar un activo utilizando assetForURL dentro de un bloque de éxito writeImage toSavedPhotosAlbum para ese mismo activo dará como resultado un activo de nulo (la mayoría de las veces).
Sin embargo, recuperar el activo con assetForURL algún tiempo después de que se haya completado la ejecución del bloqueo de éxito de writeImage produce el activo correcto.
La espera de 1 segundo funcionó, mientras que la espera de solo 300 ms no. Pero esto, por supuesto, será diferente para cada dispositivo y situación.
Esto realmente no responde la pregunta de una manera satisfactoria, pero tal vez ayuda a alguien más a resolver el problema subyacente.
Probado con iPad mini en iOS 8.1, así es como debería hacerlo con el nuevo Marco de Fotos :
NSURL *url = /* your asset url from the old ALAsset library prior to iOS 8 */
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithALAssetURLs:@[url]
options:nil];
assert(assets.count == 1);
PHAsset *asset = assets.firstObject;
[[PHImageManager defaultManager] requestImageForAsset:asset
targetSize:CGSizeMake(800, 800) // TODO: your target size
contentMode:PHImageContentModeDefault
options:nil
resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info)
{
// Do whatever you want to the result
}];
Yo tuve el mismo problema. Cambiarme al marco de fotos no es una opción para mí en este momento, pero afortunadamente he encontrado una solución alternativa. Puede que te resulte un poco feo y sospecho que puede funcionar lento cuando Photo Stream contiene muchas fotos, pero es mejor que nada.
La idea es enumerar todos los elementos en el grupo de activos de Photo Stream y comparar la URL necesaria con la URL de cada elemento. Afortunadamente, todavía funciona.
Tengo un método como este (la biblioteca es una propiedad ALAssetsLibrary de la misma clase, puede que necesite inicializarla dentro de este código):
- (void)loadItem:(NSURL *)url withSuccessBlock:(void (^)(void))successBlock andFailureBlock:(void (^)(void))failureBlock {
[library assetForURL:url
resultBlock:^(ALAsset *asset)
{
if (asset){
//////////////////////////////////////////////////////
// SUCCESS POINT #1 - asset is what we are looking for
//////////////////////////////////////////////////////
successBlock();
}
else {
// On iOS 8.1 [library assetForUrl] Photo Streams always returns nil. Try to obtain it in an alternative way
[library enumerateGroupsWithTypes:ALAssetsGroupPhotoStream
usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
[group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if([result.defaultRepresentation.url isEqual:url])
{
///////////////////////////////////////////////////////
// SUCCESS POINT #2 - result is what we are looking for
///////////////////////////////////////////////////////
successBlock();
*stop = YES;
}
}];
}
failureBlock:^(NSError *error)
{
NSLog(@"Error: Cannot load asset from photo stream - %@", [error localizedDescription]);
failureBlock();
}];
}
}
failureBlock:^(NSError *error)
{
NSLog(@"Error: Cannot load asset - %@", [error localizedDescription]);
failureBlock();
}
];
}
Espero que esto ayude.