You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在RoomVC中获取System类的_systemImplForCustomerID属性?

如何在RoomVC中获取System实例的_systemImplForCustomerID?

你的临时方案虽然能正常工作,但确实存在不少可以优化的地方,我们先聊聊这个方案的潜在问题,再看看更合理的实现方式。

临时方案的不足

这个全局数组过滤的思路有几个明显的缺陷:

  • 依赖全局状态:newSystems作为全局数组,一旦内容发生变动(比如移除某个System实例),或者在多线程场景下操作,很容易导致匹配出错;
  • 不可靠的匹配依据:用accessibilityIdentifier关联视图和System实例并不合适——这个属性原本是为无障碍功能设计的,业务逻辑依赖它很容易因为视图结构调整、ID误修改而失效;
  • 高耦合度:RoomVC需要知道全局数组的存在,违背了模块化设计的原则,代码的可维护性和可测试性都会变差。

更优的实现方式

方案1:直接给RoomVC添加属性传递ID

这是最直观、低耦合的方式,在创建RoomVC的时候直接把需要的_systemImplForCustomerID传递过去:

  1. 给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
    }
}
  1. 修改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
}
  1. 更新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扩展一个属性:

  1. 给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)
        }
    }
}
  1. 在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
    }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:32:27