Swift 2.x到swift 3,XCode抱怨:无法转换PHFetchResult类型的值

时间:2016-10-17 17:13:30

标签: swift swift3 photokit

这是我的代码:

    var galleryController: GalleryController!
    var albums: PHFetchResult = PHFetchResult()
    var cameraRoll: [PHFetchResult] = [PHFetchResult]()

    albums=getAlbums()
    cameraRoll=getcameraRoll()

func getAlbums()->PHFetchResult<AnyObject>
{
    let fetchOptions=PHFetchOptions()
    fetchOptions.predicate=NSPredicate(format:"estimatedAssetCount > 0")
    return PHAssetCollection.fetchAssetCollections(with: PHAssetCollectionType.album, subtype: PHAssetCollectionSubtype.albumSyncedAlbum, options: fetchOptions) as! PHFetchResult<AnyObject>
}    

func getcameraRoll()->[PHFetchResult<AnyObject>]
{
    self.photosFromCameraRoll=PHAsset.fetchAssets(with: PHAssetMediaType.image, options: nil)
    return [self.photosFromCameraRoll]
}

对于行var albums: PHFetchResult = PHFetchResult() Xcode抱怨此消息:&#34;无法将PHFetchResult<_>类型的值转换为指定的PHFetchResult&#34;

对于第var cameraRoll: [PHFetchResult] = [PHFetchResult]()行,Xcode也会抱怨同一条消息:&#34;无法将PHFetchResult<_>类型的值转换为指定的PHFetchResult&#34;

1 个答案:

答案 0 :(得分:4)

在Swift 3中,PHFetchResult是一个通用类。 (自去年iOS 9 SDK以来,它一直在ObjC中,Swift 3 now imports ObjC generics。)通用类型必须始终是专用的。在ObjC中,泛型类可以使用或不使用类型参数(也就是说,您可以使用PHFetchResult<SomeObjectType *> *PHFetchResult *,在后一种情况下,类型参数假定为id )。但是在Swift中你不能 - 你总是要声明一个元素类型。

因此,如果您声明一个变量来保存Photos获取结果,则需要声明这些获取结果的预期对象类型。

  • 你的第一个看起来像是一张专辑列表 - 也许是通过fetchTopLevelUserCollections(with:)获取的?因此,其类型应为PHFetchResult<PHCollection>PHFetchResult<PHAssetCollection>,具体取决于您正在使用哪种获取方法以及接下来要对其执行的操作。

  • 第二个是获取结果数组?鉴于变量名cameraRoll,仅此一点听起来很可疑。如果您只想获取相机胶卷中的所有资源,只需使用fetchAssets(in:options:),将相机胶卷作为要取的集合传递。 (您可以使用.smartAlbum类型和.smartAlbumUserLibrary子类型使用fetchAssetCollections(with:subtype:options:)进行相机拍摄。)

    无论是单个获取结果还是获取结果数组,如果您希望fetch包含资源,则类型(或数组的元素类型)应为PHFetchResult<PHAsset>

    < / LI>

您的代码的另一个更小的问题是,您正在创建虚拟的空提取结果,仅供他们(可能)稍后被实际提取覆盖。 (PHFetchResult是一个不可变的集合,因此它的初始值设定项创建一个空集合,你无法用它做任何事情。)

最好使用可选类型声明这些变量(或者,如果您计划提前初始化它们并期望在此之后所有代码路径都在初始化之后,隐式展开的可选类型)。或者,如果它适合您的使用案例,请让它们变得懒惰:

class PhotosAlbumsController: UITableViewController {

    var galleryController: GalleryController!

    lazy var albums = PHCollection.fetchTopLevelUserCollections(with: nil)
    // ^- implicitly typed PHFetchResult<PHCollection>

    lazy var cameraRoll = PHAssetCollection.fetchAssetCollections(with: .smartAlbum,
        subtype: .smartAlbumUserLibrary, options: nil).firstObject!
    // ^- implicitly typed PHAssetCollection
    // safe to force unwrap because there's always a Camera Roll / Saved Photos album

    // ...
}

这里需要注意延迟初始化的一件事(无论是使用lazy还是通过在其他时间直接获取),都要确保首先获得照片访问的用户授权,和/或确保首先注册为PHPhotoLibrary观察员。如果您在获得授权之前获取,则您的提取将为空。如果您首先注册为观察者,那么您的提取仍然是空的,但是一旦用户接受授权,您将收到填充它们的photoLibraryDidChange电话。