如何在RoomVC中获取System类的_systemImplForCustomerID属性?
如何在RoomVC中获取System实例的_systemImplForCustomerID?
你的临时方案虽然能正常工作,但确实存在不少可以优化的地方,我们先聊聊这个方案的潜在问题,再看看更合理的实现方式。
临时方案的不足
这个全局数组过滤的思路有几个明显的缺陷:
- 依赖全局状态:
newSystems作为全局数组,一旦内容发生变动(比如移除某个System实例),或者在多线程场景下操作,很容易导致匹配出错; - 不可靠的匹配依据:用
accessibilityIdentifier关联视图和System实例并不合适——这个属性原本是为无障碍功能设计的,业务逻辑依赖它很容易因为视图结构调整、ID误修改而失效; - 高耦合度:RoomVC需要知道全局数组的存在,违背了模块化设计的原则,代码的可维护性和可测试性都会变差。
更优的实现方式
方案1:直接给RoomVC添加属性传递ID
这是最直观、低耦合的方式,在创建RoomVC的时候直接把需要的_systemImplForCustomerID传递过去:
- 给
RoomVC添加存储ID的属性:
class RoomVC: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { @IBOutlet weak var collectionView: UICollectionView! // 添加属性接收System的ID var systemImplID: String! override func viewDidLoad() { super.viewDidLoad() } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCellIdentifier", for: indexPath) // 直接使用self.systemImplID即可 print("当前System的ID:\(systemImplID)") return cell } }
- 修改
System类的setSystemView方法,初始化视图控制器时传递ID:
private static func setSystemView(_systemType: String, systemID: String) -> UIViewController{ var sysView: UIViewController! switch _systemType { case "Room": let navController = mainStoryboard.instantiateViewController(withIdentifier: "View1") as! UINavigationController // 获取导航控制器的根视图控制器(RoomVC)并赋值ID if let roomVC = navController.topViewController as? RoomVC { roomVC.systemImplID = systemID } sysView = navController case "Kitchen": sysView = mainStoryboard.instantiateViewController(withIdentifier: "View2") as! KitchenVC default: break; } return sysView }
- 更新
System的初始化方法,把systemID传给setSystemView:
init(name: String, type: String, systemID: String) { _systemName = name _systemType = type _systemImplForCustomerID = systemID systemView = System.setSystemView(_systemType: type, systemID: systemID) }
修改后,RoomVC不需要依赖全局数组,直接就能拿到需要的ID,逻辑清晰且耦合度极低。
方案2:给ViewController关联System实例(适用于多场景复用)
如果你需要在多个视图控制器中获取对应的System实例(而不仅仅是ID),可以用Objective-C的关联对象给UIViewController扩展一个属性:
- 给UIViewController添加关联属性:
import ObjectiveC // 定义关联对象的唯一Key private var systemAssociationKey: UInt8 = 0 extension UIViewController { var associatedSystem: System? { get { return objc_getAssociatedObject(self, &systemAssociationKey) as? System } set { objc_setAssociatedObject(self, &systemAssociationKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } }
- 在
System的初始化方法中,给对应的视图控制器关联当前System实例:
init(name: String, type: String, systemID: String) { _systemName = name _systemType = type _systemImplForCustomerID = systemID systemView = System.setSystemView(_systemType: type) // 根据视图控制器类型设置关联 if let navVC = systemView as? UINavigationController { navVC.topViewController?.associatedSystem = self } else { systemView?.associatedSystem = self } }
- 在RoomVC中直接获取关联的System实例:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCellIdentifier", for: indexPath) if let system = self.associatedSystem { let systemID = system._systemImplForCustomerID print("当前System的ID:\(systemID)") // 还可以直接使用system的其他属性,比如_systemName等 } return cell }
这个方案的优势在于可以在任何视图控制器中获取对应的System实例,适合需要复用System数据的场景。
总结
优先推荐方案1,它更简单直接,完全避免了全局状态的依赖,代码的可维护性更好。如果你的项目中有多个视图控制器需要访问System的信息,再考虑方案2。
内容的提问来源于stack exchange,提问作者Micgal
相关产品推荐
相关产品推荐

