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

Codable CoreData模型解码崩溃:-[Land setGun:]未识别选择器问题

CoreData + Codable 解码崩溃问题求助

各位大佬,我最近在做iOS项目时遇到了个头疼的问题:想让CoreData的模型类同时遵循NSManagedObject(用于CoreData持久化)和Codable(用于JSON序列化/反序列化)协议,结果JSON解码器在反序列化到一半时直接崩溃,报错信息如下:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Land setGun:]: unrecognized selector sent to instance 0x60400028f780'

我参考了Stack Overflow上《How to use swift 4 Codable in Core Data?》的指南,但有两个点实在搞不懂:

  • A)错误并不是在解码Land类的JSON时触发的(这个类单独解码是正常的),最后命中的断点居然停在了Sea类的JSON解码器里;
  • B)Land类里确实存在setGun方法啊!为了排除CoreData自动生成代码的问题,我还手动声明了一个占位方法。

下面是Land类的完整代码:

import Foundation
import CoreData

@objc(Land)
class Land : NSManagedObject, Equipment {
    var type = EquipmentType.LAND
    
    enum CodingKeys: String, CodingKey {
        case id
        case name
        case desc = "description"
        case groupIconUrl
        case individualIconUrl
        case photoUrl
        case primaryWeapon
        case secondaryWeapon
        case atgm
        case armor
        case speed
        case auto
        case weight
    }
    
    required convenience init(from decoder: Decoder) throws {
        guard let context = decoder.userInfo[CodingUserInfoKey.context!] as? NSManagedObjectContext else {
            fatalError()
        }
        guard let entity = NSEntityDescription.entity(forEntityName: "Land", in: context) else {
            fatalError()
        }
        self.init(entity: entity, insertInto: context)
        
        let container = try! decoder.container(keyedBy: CodingKeys.self)
        self.id = try container.decode(Int64.self, forKey: .id)
        self.name = try container.decodeIfPresent(String.self, forKey: .name)
        self.desc = try container.decodeIfPresent(String.self, forKey: .desc)
        self.groupIconUrl = try container.decodeIfPresent(String.self, forKey: .groupIconUrl)
        self.individualIconUrl = try container.decodeIfPresent(String.self, forKey: .individualIconUrl)
        self.photoUrl = try container.decodeIfPresent(String.self, forKey: .photoUrl)
        self.primaryWeapon = try container.decodeIfPresent(Gun.self, forKey: .primaryWeapon)
        self.secondaryWeapon = try container.decodeIfPresent(Gun.self, forKey: .secondaryWeapon)
        self.atgm = try container.decodeIfPresent(Gun.self, forKey: .atgm)
        self.armor = try container.decode(Int64.self, forKey: .armor)
        self.speed = try container.decode(Int64.self, forKey: .speed)
        self.auto = try container.decode(Int64.self, forKey: .auto)
        self.weight = try container.decode(Int64.self, forKey: .weight)
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(name, forKey: .name)
        try container.encode(desc, forKey: .desc)
        try container.encode(groupIconUrl, forKey: .groupIconUrl)
        try container.encode(individualIconUrl, forKey: .individualIconUrl)
        try container.encode(photoUrl, forKey: .photoUrl)
        try container.encode(primaryWeapon, forKey: .primaryWeapon)
        try container.encode(secondaryWeapon, forKey: .secondaryWeapon)
        try container.encode(atgm, forKey: .atgm)
        try container.encode(armor, forKey: .armor)
        try container.encode(speed, forKey: .speed)
        try container.encode(auto, forKey: .auto)
        try container.encode(weight, forKey: .weight)
    }
    
    public func setGun(gun: Gun){}
}

我的CoreData数据模型如下:
CoreData 数据模型

如果以上信息还不足以定位问题,大家可以克隆我的公开GitHub仓库本地运行排查,仓库里有完整的项目代码。

内容的提问来源于stack exchange,提问作者James Jordan Taylor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:11:37