Ошибка миграции SWIFT 3.0 - Расширение универсального класса Obj-C не может получить доступ к универсальному параметру класса во время выполнения

У меня этот код работает нормально в Swift 2.

extension PHFetchResult: Sequence {
     public func makeIterator() -> NSFastEnumerationIterator {
         return NSFastEnumerationIterator(self)
     }
}

Так как я обновился до Swift 3

Расширение универсального класса Objective C не может получить доступ к универсальным параметрам класса во время выполнения

Я понятия не имею, как это исправить. Любая помощь высоко ценится!

4 ответа

Вытащив из Царства, вы можете обойти это, расширив подкласс того, что вы хотите, чтобы соответствовать последовательности и положить makeIerator функционировать там.

// Sequence conformance for ClassA is provided by ProtocolX's `makeIterator()` implementation.
extension ClassA: Sequence {}

extension ProtocolX {
    // Support Sequence-style enumeration
    public func makeIterator() -> RLMIterator {
        return RLMIterator(collection: self)
    }
}

Вы можете увидеть полный код на https://github.com/realm/realm-cocoa/blob/master/Realm/Swift/RLMSupport.swift

О проблеме сообщили здесь: https://bugs.swift.org/browse/SR-1576

Но в конце концов, вы не можете использовать for in с PHFetchResult в Swift 3.0. Давайте посмотрим несколько примеров:

let collections = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: nil)
let collectionLists = PHCollectionList.fetchCollectionLists(with: .momentList, subtype: .momentListYear, options: nil)
let assets = PHAsset.fetchAssets(with: .image, options: nil)

Вы можете использовать встроенное перечисление PHFetchResult (мое рекомендуемое решение):

collections.enumerateObjects(_:) { (collection, count, stop) in
    //...
}
collectionLists.enumerateObjects(_:) { (collectionList, count, stop) in
    //...
}
assets.enumerateObjects(_:) { (asset, count, stop) in
    //...
}

Или получить доступ к каждому объекту по его индексу:

for idx in 0 ..< collections.count {
    let collection = collections[idx]
    // ...
}
for idx in 0 ..< collectionLists.count {
    let collectionList = collectionLists[idx]
    // ...
}
for idx in 0 ..< assets.count {
    let asset = assets[idx]
    // ...
}

Вы можете использовать тип оболочки, предложенный инженером Swift Джорданом Роузом в отчете об ошибке:

import Photos

struct ResultSequence<Element: AnyObject>: Sequence {
  var result: PHFetchResult<Element>
  init(_ result: PHFetchResult<Element>) {
    self.result = result
  }
  func makeIterator() -> NSFastEnumerationIterator {
    return NSFastEnumerationIterator(self.result)
  }
}


func test(_ request: PHFetchResult<PHCollection>) {
  for elem in ResultSequence(request) {
    print(elem)
  }
}

Нет способа исправить это, возможно, вам придется реорганизовать ваш код или использовать другие методы.

Вы можете сослаться на это:

Как использовать быстрый класс с универсальным типом в цели c

документы:

https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

Другие вопросы по тегам