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?
Perché 'group.enumerateAssetsAtIndexes (NSIndexSet (index: group.numberOfAssets() - 1) ...' invece di una 'self.group.enumerateAssetsUsingBlock (' – Bill
non sono sicuro (come detto ho seguito un tutorial?) ma penso che sia perché voglio accedere solo all'ultima foto e non enumerarli tutti ... –
Puoi postare il backtrace quando si verifica l'errore? – Bill