Swift中遵循NSCopying协议的类执行copy后属性为空问题求解
问题根因
核心问题出在Team类的初始化方法逻辑顺序错误,连带导致copy方法取值异常:
init方法中,self.data = data的赋值操作写在了guard let判断的后面。如果传入的初始化数据里不存在HomeStamp字段,或者对应值的类型不是PFFileObject,guard判断会触发return,直接中断初始化方法的后续执行。
此时原实例在guard之前赋值的属性(比如sportsID/team/city等)都是正常的,但是data属性因为还没走到赋值步骤,会保持默认的空字典[:],同时venueLocation的二次拼接逻辑、homeStampImag赋值也不会执行。- 你的
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
相关产品推荐
相关产品推荐

