2014-10-21 9 views
25

Questo codice ha funzionato correttamente in iOS 7 ma in iOS 8.1 tutte le risorse che si trovano nell'album "My Photo Stream" sono nul all'interno del blocco dei risultati. (Il fallimentoBlock non viene chiamato.) Gli album normali e gli album condivisi funzionano bene.ALAssetsBiblioteca assetForURL: restituisce sempre nil per le foto in "My Photo Stream" in iOS 8.1

ho cercato la risposta accettata da: Error trying to assigning __block ALAsset from inside assetForURL:resultBlock:

Cioè, ho in mano un riferimento a un oggetto ALAssetsLibrary, ascoltando per l'evento ALAssetsLibraryChangedNotification (cosa che non avviene btw, ma vabbè.) Ho fatto certo che la mia app ha il permesso di accedere alle foto, io sono su wi-fi, vedo le miniature delle foto bene nel mio tableView. È solo quando cerco di caricarli con assetForURL: che sono sempre nulli.

// 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!"); 
}]; 

Qualcun altro sta visualizzando questo problema?

risposta

30

Ho avuto lo stesso problema. Passare al framework Photos non è un'opzione per me in questo momento, ma per fortuna ho trovato una soluzione alternativa. Potresti trovarlo un brutto e sospetto che possa funzionare lentamente quando Photo Stream contiene molte foto, ma è meglio di niente.

L'idea è di enumerare tutti gli elementi nel gruppo di risorse del flusso fotografico e confrontare l'URL necessario con l'URL di ciascun elemento. Fortunatamente, funziona ancora.

Ho un metodo come questo (biblioteca è di proprietà ALAssetsLibrary della stessa classe, potrebbe essere necessario inizializzare all'interno di questo codice):

- (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(); 
     } 
    ]; 
} 

Spero che questo aiuti.

+3

Anche se non è l'ideale, questo fa davvero il trucco, grazie mille! Non essere eccessivamente nitpicky ma sembra che 'item.url' dovrebbe essere solo 'url' corretto? E probabilmente dovremmo chiamare un blocco di successo che passi in ALAsset. Grazie ancora! – taber

+0

Ho lo stesso problema per Moment e My Photo Stream, sebbene la soluzione sopra non funzioni ... enumerare i gruppi non fa nulla ... anche se cambio ALAssetsGroupPhotoStream in ALAssetsGroupAll – AkademiksQc

+0

strano, ha funzionato qui - sei sicuro hai approvato il permesso per le foto? – taber

2

Da iOS 8.0 e versioni successive, è necessario utilizzare Photos framework anziché il framework Assets Library.

enter image description here

+2

Non dice che dobbiamo "usare" Photos.framework. Il solo dirci che questo è il modo per accedere alle immagini in futuro. –

-1

Dopo aver trovato nessuna risposta per questo ovunque, ho creato la seguente estensione per PHAsset che funziona perfettamente come per iOS 8.2 anche se presumo sia teoricamente lento. Anche se uno dei commenti precedenti dice che questo è stato risolto su iOS8.2 beta, il bug era ancora presente per me ora che iOS8.2 è stato rilasciato.

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 
     } 
    } 
} 
1

Testato con mini iPad su iOS 8.1, questo è come si dovrebbe fare con il nuovo Photos Framework:

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 
}]; 
1

Ho fatto l'osservazione che il tentativo di recuperare una risorsa utilizzando assetForURL all'interno un blocco di successo di writeImage toSavedPhotosAlbum per lo stesso asset produrrà un asset di zero (la maggior parte delle volte).

Tuttavia, il recupero della risorsa con assetForURL un po 'di tempo dopo il il blocco di successo writeImage ha completato l'esecuzione produce l'asset corretto.

Attendere 1 secondo ha funzionato, mentre l'attesa per soli 300 ms non ha funzionato. Ma questo ovviamente sarà diverso per ogni dispositivo e situazione.

Questo in realtà non risponde alla domanda in modo soddisfacente, ma forse aiuta qualcun altro a capire il problema sottostante.

+0

Provare lo stesso problema. Anche se la scrittura è stata risolta correttamente, restituisce nil nella richiesta di assetForURL. Curioso di cosa sta realmente accadendo. – nudies

Problemi correlati