I'm trying to add an extension to PHFetchResult to pull the result objects out as a correctly typed array - and so far I can't figure out how to avoid the replication seen below. Aside from the type constraint the following extensions are identical. If I use PHObject as the constraint it would work, but the result would need to be cast to the more specific type...
extension PHFetchResult where ObjectType == PHAsset {
var objects: [ObjectType] {
var _objects: [ObjectType] = []
enumerateObjects { (object, _, _) in
_objects.append(object)
}
return _objects
}
}
extension PHFetchResult where ObjectType == PHCollection {
var objects: [ObjectType] {
var _objects: [ObjectType] = []
enumerateObjects { (object, _, _) in
_objects.append(object)
}
return _objects
}
}
extension PHFetchResult where ObjectType == PHAssetCollection {
var objects: [ObjectType] {
var _objects: [ObjectType] = []
enumerateObjects { (object, _, _) in
_objects.append(object)
}
return _objects
}
}
This is a general issue with generic types defined in ObjC and imported to Swift. Some relevant compiler bugs:
In short: ObjC generics are type-erasing, Swift generics are type-preserving. You need the latter for tasks like defining type-constrained extensions, but you can't because Swift doesn't know anything about the ObjectType of any particular PHFetchResult
instance.
The swift-evolution proposal that brought widespread ObjC generics import to Swift 3 included a provision for letting ObjC classes provide information about their generic type parameters at runtime... but as of today, that provision has never been implemented.
AFIAK, there's not really a solution to this problem (short of working on the Swift compiler project to improve ObjC generics support), nor similar problems like making PHFetchResult
conform to Sequence
or Collection
.
(I've tried a few angles on extending PhotoKit classes to be more Swifty myself, without much success. About the only thing I haven't tried — largely because it's such a drastic measure — is wrapping/replacing large chunks of the API. In theory, though, you could wrap PHFetchResult
in a non-generic ObjC class, then wrap that in a generic Swift type, and replace all of the PhotoKit fetch methods with ones that provide appropriately specialized versions of your wrapper type.)