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

Swift中遵循NSCopying协议的类执行copy后属性为空问题求解

问题根因

核心问题出在Team类的初始化方法逻辑顺序错误,连带导致copy方法取值异常:

  1. init方法中,self.data = data的赋值操作写在了guard let判断的后面。如果传入的初始化数据里不存在HomeStamp字段,或者对应值的类型不是PFFileObject,guard判断会触发return,直接中断初始化方法的后续执行。
    此时原实例在guard之前赋值的属性(比如sportsID/team/city等)都是正常的,但是data属性因为还没走到赋值步骤,会保持默认的空字典[:],同时venueLocation的二次拼接逻辑、homeStampImag赋值也不会执行。
  2. 你的copy方法是依赖原实例的data属性创建新实例,原实例的data是空字典,自然复制出来的新实例所有属性都是默认值。

另外你当前的copy实现还有隐含问题:所有没有存入data字典的属性(比如rotationAngle/stampImage/backgroundImage/isHomeTeam/timestamp等),用data初始化的方式根本复制不过去,新实例的这些属性都会重新生成或者保持默认值,和原实例不一致。


修复方案

第一步:调整初始化方法的逻辑顺序

把data赋值、venueLocation处理这些通用逻辑移到guard判断前面,避免guard中断导致通用逻辑不执行:

init(data: [String: Any] = [:], radius: Double, objectId: String = "") {
    super.init()
    // 先赋值data,保证不管后续判断结果如何,data属性都有值
    self.data = data
    self.objectId = objectId
    self.sportsID = data[Keys.sportsID] as? Int ?? -1
    self.stampId = data[Keys.stampId] as? Int ?? -1
    self.date = UserDefaults.standard.string(forKey: "StampIdDate: \(self.stampId)") ?? ""
    self.associationID = data[Keys.associationID] as? Int ?? -1
    self.team = data[Keys.team] as? String ?? ""
    self.conference = data[Keys.conference] as? String ?? ""
    self.stadiumCampus = data[Keys.stadiumCampus] as? String ?? ""
    self.latitude = (data[Keys.latitude] as? Double ?? 0.0) == 0.0 ? data[Keys.GPSLatitude] as? Double ?? 0.0 : data[Keys.latitude] as? Double ?? 0.0
    self.longitude = (data[Keys.longitude] as? Double ?? 0.0) == 0.0 ? data[Keys.GPSLongitude] as? Double ?? 0.0 : data[Keys.longitude] as? Double ?? 0.0
    self.letterName = data[Keys.letterName] as? String ?? ""
    self.letterColor = data[Keys.letterColor] as? String ?? ""
    self.backgroundColorString = data[Keys.backgroundColor] as? String ?? ""
    self.isActive = data[Keys.isActive] as? Bool ?? false
    self.venueLocation = data[Keys.venueLocation] as? String ?? ""
    self.city = data[Keys.city] as? String ?? ""
    self.state = data[Keys.state] as? String ?? ""
    self.radius = radius
    self.backgroundImageId = data[Keys.backgroundImage] as? Int ?? 1
    
    // 把guard改成if let,不要直接return中断后续逻辑
    if let stampImage = data[Keys.homeStampImag] as? PFFileObject {
        self.homeStampImag = stampImage
    }
    
    if self.venueLocation.isEmpty {
        self.venueLocation = self.team
    }
    
    if self.stadiumCampus.isEmpty {
        self.venueLocation = self.city + ", " + self.state
    }
}

第二步:重写copy方法,手动同步所有属性

不要依赖data初始化,直接把原实例的所有属性赋值给新实例,保证完全一致:

func copy(with zone: NSZone? = nil) -> Any {
    let copy = Team(data: data, radius: radius, objectId: objectId)
    // 手动同步所有不在初始化逻辑里的属性
    copy.backgroundImage = backgroundImage
    copy.homeStampImag = homeStampImag
    copy.stampImage = stampImage
    copy.rotationAngle = rotationAngle
    copy.date = date
    copy.timestamp = timestamp
    copy.isHomeTeam = isHomeTeam
    return copy
}

内容的提问来源于stack exchange,提问作者swg1cor14

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 00:27:00