在Swift中使用ALAsset

Phi*_*ler 5 ios alasset alassetslibrary swift

我知道Swift和Xcode 6都处于测试阶段,但我认为在我的情况下,存在一个与Swift或Xcode 6无关的结构性错误.如果stackoverflow社区将此评为不合适的问题,我可以立即将其删除.

但现在让我们回答我的问题.我有一个UIViewController,我正在尝试将相机胶卷中的最后一个图像添加到此视图控制器(显然是通过UIImageView).这是我的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)

    })
}
Run Code Online (Sandbox Code Playgroud)

问题是,每次我编译程序崩溃和Xcode承诺我进入这个漂亮的小文件:

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
...
...
Run Code Online (Sandbox Code Playgroud)

该文件很长,所以我不会在这里发布整个内容......正如你所看到的,它似乎与Swift选项有关.这就是为什么我试图添加一个!在每个闭包变量之后,例如在enumerateAssetsAtIndexes方法块中

{(result: ALAsset!, index: Int!, stop: CMutablePointer<ObjCBool>!) in 
...
}
Run Code Online (Sandbox Code Playgroud)

有些元素有!之前,因为在类引用和一些互联网示例中我找到了它们(在这种情况下是结果).好吧,在这一举动后,程序仍然崩溃,但另一个原因......在

group.enumerateAssetsAtIndexes(NSIndexSet(index: group.numberOfAssets()-1), options: nil, usingBlock: {
Run Code Online (Sandbox Code Playgroud)

行,我得到EXT_BAD_ACCESS.

我对资产这样的东西真的很新,我不知道为什么会这样.我按照Apple AV Foundation编程指南中的示例进行操作:https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/01_UsingAssets.html我不知道我的更改是否与!可以帮助你理解发生了什么,但我发布它是因为我认为这是一个有趣的事实,可能有所帮助.谢谢你的建议!

PS:对一般代码的任何帮助表示赞赏!

编辑:

这是回溯:

尝试在路径文件中添加只读文件:///var/mobile/Media/PhotoData/Photos.sqlite?readonly_shm = 1读/写.将其添加为只读.这将是一个很难的错误; 您必须指定NSReadOnlyPersistentStoreOption.致命错误:无法打开Optional.None

编辑: 在Bill的精彩帮助下,我修改了代码,以便应用程序不再崩溃!这是新版本:

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)

    })
}
Run Code Online (Sandbox Code Playgroud)

如上所述,应用程序不再崩溃,但图像视图没有添加,UIViewController仍然是一个白色画布...在我的测试中,这发生是因为资产在

assetLib.assetForURL(url, resultBlock: {
(asset: ALAsset!) in
if asset != nil {
 ...
}
}
Run Code Online (Sandbox Code Playgroud)

是零,块永远不会执行...我添加了if asset!= nil条件,因为没有它,应用程序仍然崩溃.现在,Xcode揭示了这个问题.回溯:

尝试在路径文件中添加只读文件:///var/mobile/Media/PhotoData/Photos.sqlite?readonly_shm = 1读/写.将其添加为只读.这将是一个很难的错误; 您必须指定NSReadOnlyPersistentStoreOption.

那么我该如何解决这个问题呢?

Bil*_*ill 2

如文档中所指定,可以作为组enumerateGroupsWithTypes返回。nil您需要处理这种nil情况 -!如果您尝试使用非零组,则将 放在组参数后面会告诉 Swift 使程序崩溃。

修理:

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

    if group != nil { 
       group.setAssetsFilter(ALAssetsFilter.allPhotos())    
       ...
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 我做了group一个可选的
  2. 我检查以确保它group不为零。
  3. 我没有使用命名usingBlock参数,而是使用 Swift 对尾随闭包的支持来简单地在参数列表后面传递一个块。