iOS真机运行时无法正常获取UTType全量Supertypes的问题咨询
问题描述
在iOS模拟器环境下运行代码时,访问JPG文件对应的UTType.supertype属性,返回结果如下:
[<_UTCoreType 0x1121549b0> public.item (not dynamic, declared), <_UTCoreType 0x112154a30> public.data (not dynamic, declared), <_UTCoreType 0x112155090> public.image (not dynamic, declared), <_UTCoreType 0x1121549d0> public.content (not dynamic, declared)]
在硬件真机设备上运行相同代码时,同个属性返回结果如下:
[<_UTCoreType 0x204f85b80> public.jpeg (not dynamic, declared)]
需求:在硬件真机设备上获取UTType对应的所有父类型。
原因说明
这个差异是对API的预期错误导致的:
UTType.supertype官方文档从未承诺会返回所有层级的父类型,模拟器返回全量父链属于框架实现的特例,不是约定行为,不能作为编码依赖。真机上的表现才符合API设计:该属性仅返回当前类型的直接父类型,部分系统版本下甚至会返回类型自身,单次调用自然拿不到完整父类链。- UniformTypeIdentifiers框架没有提供直接返回全量父类型链的现成属性,需要手动沿着类型继承关系遍历收集。
实现方法
通过广度优先遍历逐层收集父类型即可,注意加去重逻辑避免循环引用导致死循环,参考代码如下:
import UniformTypeIdentifiers func fetchAllSupertypes(for type: UTType) -> Set<UTType> { var allSupertypes = Set<UTType>() var searchQueue = [type] var visitedTypes = Set<UTType>() while !searchQueue.isEmpty { let currentType = searchQueue.removeFirst() guard !visitedTypes.contains(currentType) else { continue } visitedTypes.insert(currentType) guard let directSupertype = currentType.supertype else { continue } if !visitedTypes.contains(directSupertype) { allSupertypes.insert(directSupertype) searchQueue.append(directSupertype) } } return allSupertypes } // 调用示例 if let jpegType = UTType.jpeg { let supertypes = fetchAllSupertypes(for: jpegType) // 打印结果可获得public.image、public.data、public.item、public.content等所有层级父类型,和模拟器返回的父类型集合一致 print(supertypes.map(\.identifier)) }
注意事项
- 不要依赖
supertype单次调用的返回结果,这个属性的表现随iOS版本、运行环境(模拟器/真机)、具体类型的不同会有差异,属于未文档化的实现细节,线上代码直接依赖很容易触发兼容性问题。 - 遍历收集父类型必须加去重逻辑,UTI的类型体系不是严格的树状结构,存在多继承、循环引用的场景,不去重会触发死循环。
- 如果需求只是判断当前类型是否属于某个父类的子类型,不需要手动遍历父链,直接调用系统提供的
isSubtype(of:)方法即可,该方法为框架内置实现,准确性和性能都优于手动遍历。
内容的提问来源于stack exchange,提问作者BadmintonCat
相关产品推荐
相关产品推荐

