能否传递对象类型给函数?泛型简化视图控制器数组类型检测方案
当然可以用泛型简化这类类型检查代码!
我之前也踩过重复写检查逻辑的坑——手里一堆不同类型的VC数组,每次检查是否包含某类VC都要写一遍contains { $0 is XXXViewController },重复代码多到头疼,泛型正好能完美解决这个问题。
第一步:写一个基础的泛型检查函数
先从最直接的泛型函数开始,它能接收VC数组和你要检查的类型,返回是否包含该类型的元素:
import UIKit func containsViewController<T>(in array: [UIViewController], ofType type: T.Type) -> Bool { return array.contains { $0 is T } }
调用的时候直接传数组和VC类型的.self就行:
let myVCs: [UIViewController] = [HomeVC(), SettingsVC(), ProfileVC()] let hasSettingsVC = containsViewController(in: myVCs, ofType: SettingsVC.self)
第二步:用扩展让代码更优雅
上面的函数已经能用,但我们可以给[UIViewController]写个扩展,让调用方式更自然,就像数组自带的方法一样:
extension Array where Element == UIViewController { // 检查是否包含某类VC func contains<T>(type: T.Type) -> Bool { return contains { $0 is T } } // 顺便加个实用的:获取第一个该类型的VC(自动强转类型) func first<T>(ofType type: T.Type) -> T? { return first { $0 is T } as? T } }
现在调用起来就清爽多了:
// 检查是否存在SettingsVC if myVCs.contains(type: SettingsVC.self) { print("找到了设置页面!") } // 获取第一个ProfileVC并直接使用 if let profileVC = myVCs.first(ofType: ProfileVC.self) { profileVC.loadUserInfo() // 这里不用再手动强转,直接是ProfileVC类型 }
额外说明:严格匹配类型 vs 包含子类
上面的代码用$0 is T会匹配该类型及其子类的VC。如果你的需求是严格匹配类型(不包含子类),只需要把判断条件改成:
func containsExact<T>(type: T.Type) -> Bool { return contains { type(of: $0) == T.self } }
这样一来,所有类型检查的逻辑都被复用起来,不用再重复写闭包,代码简洁性和可读性都提升了不少~
内容的提问来源于stack exchange,提问作者Piepants
相关产品推荐
相关产品推荐

