2014-07-13 12 views
5

So che Swift e Xcode 6 sono entrambi ancora in beta, ma penso che nel mio caso ci sia un bug strutturale che non è correlato a Swift o Xcode 6 in alcun modo. Se la community di stackoverflow considera questa come una domanda inappropriata, posso eliminarla immediatamente.Utilizzo di ALAsset in Swift

Ma ora passiamo alla mia domanda. Ho un UIViewController e sto cercando di aggiungere l'ultima immagine dal rullino fotografico a questo controller di visualizzazione (ovviamente attraverso un UIImageView). Qui è il mio metodo viewDidLoad:

override func viewDidLoad() { 
    super.viewDidLoad() 

    var assetLib = ALAssetsLibrary() 

    var url: NSURL = NSURL() 

    var imageView = UIImageView(frame: self.view.bounds) 

    assetLib.enumerateGroupsWithTypes(ALAssetsGroupType(ALAssetsGroupSavedPhotos), usingBlock: { 
    (group: ALAssetsGroup!, stop: CMutablePointer<ObjCBool>) in 

    group.setAssetsFilter(ALAssetsFilter.allPhotos()) 

    group.enumerateAssetsAtIndexes(NSIndexSet(index: group.numberOfAssets()-1), options: nil, usingBlock: { 
     (result: ALAsset!, index: Int, stop: CMutablePointer<ObjCBool>) in 
     if result { 
     var alAssetRapresentation: ALAssetRepresentation = result.defaultRepresentation() 
     url = alAssetRapresentation.url() 

     if group == nil { 

      assetLib.assetForURL(url, resultBlock: { 
      (asset: ALAsset!) in 

      var assetRep: ALAssetRepresentation = asset.defaultRepresentation() 
      var iref = assetRep.fullResolutionImage().takeUnretainedValue() 
      var image = UIImage(CGImage: iref) 

      imageView.image = image 

      self.view.addSubview(imageView) 

      }, failureBlock: { 
       (error: NSError!) in 

       NSLog("Error!", nil) 
      }) 
     } 
     } 
     }) 
    }, failureBlock: { 
     (error: NSError!) in 

     NSLog("Error!", nil) 

    }) 
} 

Il problema è che ogni volta che compilare il programma si blocca e Xcode mi promts in questo bel piccolo file:

IdealityS`Swift._getOptionalValue <A>(Swift.Optional<A>) -> A: 
0x6540: pushl %ebp 
0x6541: movl %esp, %ebp 
0x6543: pushl %ebx 
0x6544: pushl %edi 
0x6545: pushl %esi 
0x6546: subl $0x8c, %esp 
0x654c: calll 0x6551     ; Swift._getOptionalValue <A> (Swift.Optional<A>) -> A + 17 
... 
... 

Il file è lungo, quindi non sono postare l'intero contenuto qui ... Come puoi vedere sembra essere qualcosa correlato agli optionals Swift. Ecco perché ho provato ad aggiungere un! dopo ogni variabile chiusura, ad esempio nel blocco metodo enumerateAssetsAtIndexes

{(result: ALAsset!, index: Int!, stop: CMutablePointer<ObjCBool>!) in 
... 
} 

Alcuni degli elementi aveva la! prima, perché nella classe di riferimento e in alcuni esempi di internet li ho trovati (in questo caso i risultati). Bene, dopo questa mossa il programma si blocca ancora, ma per un altro motivo ... In linea di

group.enumerateAssetsAtIndexes(NSIndexSet(index: group.numberOfAssets()-1), options: nil, usingBlock: { 

, ottengo EXT_BAD_ACCESS.

Sono davvero nuovo per cose come Assets e non ho idea del perché questo accada. Ho seguito l'esempio nella guida alla programmazione di Apple AV Foundation qui: https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/01_UsingAssets.html Non so se il mio cambiamento con il! può aiutarti a capire cosa è successo, ma l'ho postato perché penso che sia un fatto interessante che potrebbe aiutarti. Grazie in consiglio!

PS: Qualsiasi aiuto con il codice in generale è apprezzato!

EDIT:

Ecco il backtrace:

Attempt to add read-only file at path file:///var/mobile/Media/PhotoData/Photos.sqlite?readonly_shm=1 read/write. Adding it read-only instead. This will be a hard error in the future; you must specify the NSReadOnlyPersistentStoreOption. fatal error: Can't unwrap Optional.None

EDIT: Con l'aiuto impressionante di Bill, ho modificato il codice in modo che l'applicazione non va in crash più! Ecco la nuova versione:

override func viewDidLoad() { 
    super.viewDidLoad() 

    var assetLib = ALAssetsLibrary() 
    var url: NSURL = NSURL() 

    var imageView = UIImageView(frame: self.view.bounds) 

    assetLib.enumerateGroupsWithTypes(ALAssetsGroupType(ALAssetsGroupSavedPhotos), usingBlock: { 
    (group: ALAssetsGroup?, stop: CMutablePointer<ObjCBool>) in 
    if group != nil { 
    group!.setAssetsFilter(ALAssetsFilter.allPhotos()) 
    group!.enumerateAssetsAtIndexes(NSIndexSet(index: group!.numberOfAssets()-1), options: nil, usingBlock: { 
     (result: ALAsset!, index: Int, stop: CMutablePointer<ObjCBool>) in 
     if result { 
     var alAssetRapresentation: ALAssetRepresentation = result.defaultRepresentation() 
     url = alAssetRapresentation.url() 
     } 
     }) 
    } 
    else if group == nil { 

     assetLib.assetForURL(url, resultBlock: { 
     (asset: ALAsset!) in 
     if asset != nil { 
     var assetRep: ALAssetRepresentation = asset.defaultRepresentation() 
     var iref = assetRep.fullResolutionImage().takeUnretainedValue() 
     var image = UIImage(CGImage: iref) 

     imageView.image = image 


     self.view.addSubview(imageView) 

     } 
     }, failureBlock: { 
      (error: NSError!) in 

      NSLog("Error!", nil) 
     }) 
    } 

    }, failureBlock: { 
     (error: NSError!) in 

     NSLog("Error!", nil) 

    }) 
} 

Come detto, l'applicazione non va in crash più, ma la vista dell'immagine non viene aggiunto e l'UIViewController è ancora una tela bianca ... Nel mio test, questo accade perché patrimoniale in

assetLib.assetForURL(url, resultBlock: { 
(asset: ALAsset!) in 
if asset != nil { 
... 
} 
} 

è pari a zero, e il blocco non esegue mai ... ho aggiunto la risorsa se! = condizione zero perché senza di essa l'applicazione blocca ancora. Ora, il problema è rivelato da Xcode. Il backtrace:

Attempt to add read-only file at path file:///var/mobile/Media/PhotoData/Photos.sqlite?readonly_shm=1 read/write. Adding it read-only instead. This will be a hard error in the future; you must specify the NSReadOnlyPersistentStoreOption.

Quindi, come posso risolvere questo?

+0

Perché 'group.enumerateAssetsAtIndexes (NSIndexSet (index: group.numberOfAssets() - 1) ...' invece di una 'self.group.enumerateAssetsUsingBlock (' – Bill

+0

non sono sicuro (come detto ho seguito un tutorial?) ma penso che sia perché voglio accedere solo all'ultima foto e non enumerarli tutti ... –

+0

Puoi postare il backtrace quando si verifica l'errore? – Bill

risposta

2

Il enumerateGroupsWithTypes può restituire nil come gruppo, come specificato nei documenti.È necessario gestire la custodia nil - inserendo lo ! dopo che il parametro di gruppo indica a Swift di arrestare il programma se si tenta di utilizzare un gruppo diverso da zero.

Per fissare:

assetLib.enumerateGroupsWithTypes(ALAssetsGroupType(ALAssetsGroupSavedPhotos)) { 
    (group: ALAssetsGroup?, stop: CMutablePointer<ObjCBool>) in 

    if group != nil { 
     group.setAssetsFilter(ALAssetsFilter.allPhotos())  
     ... 
    } 
} 
  1. ho fatto group un optional
  2. verifico per garantire che group è non-zero.
  3. Invece di utilizzare un parametro denominato usingBlock, utilizzo il supporto di Swift per le chiusure finali per passare semplicemente un blocco dopo l'elenco dei parametri.
+0

Grazie per la tua risposta! Ma ho bisogno di aiuto per modificare il codice ... Non sono sicuro di averlo fatto bene perché ho ancora degli errori. Pubblicherò presto la nuova versione del codice, con l'errore "nuovo" incluso. –

0

In XCode 6 Beta 3 il problema sembra essere risolto. Sono stato in grado di eseguire correttamente l'iterazione e visualizzare le risorse nella libreria fotografica. Tuttavia avevo bisogno di filtrare i null sia per ALAssetsGroup che per ALAsset, quindi entrambi i parametri dove dichiarato? invece di !.

Problemi correlati