IOS Swift:在初始化方法(构造函数)之前运行一次代码块

时间:2019-10-23 13:31:00

标签: ios swift

在IOS SWIFT中,如何实现类似的功能,例如C#中提供的 静态构造函数

即:

  1. 在init方法之前执行代码块(在类中执行的第一个代码块)
  2. 自动致电
  3. 在类的生命周期中仅执行一次

这是设置全局翻译映射,以使用提供的名称而不是真实的类名称(类名称为“ Order”)对类的实例进行编码。

NSKeyedUnarchiver.setClass(Order.self, forClassName: "OldModuleName.Order")

从begininig编写旧的APP(用SWIFT 1.2编写),并且项目名称不同,因此模块名称与旧版本不同。

我需要在初始化类之前一次运行上述代码。

class Order: NSObject, NSCoding
{
    var orderID: Int = 0
    var description: String = ""

    // NEED TO RUN THIS LINE BEFORE INIT METHOD >>>>
    // NSKeyedUnarchiver.setClass(Order.self, forClassName: "OldModuleName.Order")

    override init()
    {
        super.init()
    }

    required init?(coder aDecoder: NSCoder)    
    {
        self.orderID = (aDecoder.decodeInteger(forKey: "OrderID"))
        self.description= (aDecoder.decodeObject(forKey: "Description") as? String) ?? ""
    }

    func encode(with aCoder: NSCoder)    
    {        
        aCoder.encode(self.orderID, forKey: "OrderID")
        aCoder.encode(self.description, forKey: "Description")
    }
}

编辑

我尝试编写如下所示的静态常量,并在“ 必需的init?(coder aDecoder:NSCoder) ”方法中对其进行调用(因为此类符合NSCoding协议在这种情况下,不会调用默认的init方法)

static let ConfigureEncodeTranslationMapping: Void =    
{               
    NSKeyedUnarchiver.setClass(Order.self, forClassName: "OldModuleName.Order")        
    return()    
}()

required init?(coder aDecoder: NSCoder)    
{
    // call static constant here to test
    Order.ConfigureEncodeTranslationMapping

    self.orderID = (aDecoder.decodeInteger(forKey: "OrderID"))
    self.description= (aDecoder.decodeObject(forKey: "Description") as? String) ?? ""
}

但是APP崩溃了

*由于未捕获的异常'NSInvalidUnarchiveOperationException'而终止应用程序,原因:'***-[NSKeyedUnarchiver encodeObjectForKey:]:无法解码键(NS.objects)的类(OldModuleName.Order)的对象,因为没有名为“ OldModuleName”的类“订单”已找到;该类需要在源代码中定义或从库中链接(确保该类是正确目标的一部分)。如果重命名了类,请使用setClassName:forClass:将类转换映射添加到NSKeyedUnarchiver *

1 个答案:

答案 0 :(得分:0)

有一个名为load()的类方法,该方法在每次加载类时自动调用,并在每次应用启动时自动调用一次。但是它定义了Objective-C类方法“加载”,这是 Swift 所不允许的。您可以使用Objective-C类并将其桥接回Swift。

尝试此操作以查看问题:

override class func load() {
    print("Loaded")
}

这是动态行为, Swift 是静态的!因此,如果没有Objective-C的帮助,您将无法迅速完成此任务。

相似但不相同

您可以拥有一个静态常量,然后调用一次(或多次,无关紧要):

class Order {
    static let loadOnce: Void = { print("Loaded") }()
}

Order.loadOnce
Order.loadOnce
Order.loadOnce
Order.loadOnce

查看输出显示它刚刚被调用为once,而无需加载该类。因此,您可以使用以下命令确保在初始化完成之前调用它。

init() { Self.loadOnce }

或者甚至在致电super.init

之前
override init() {
    Self.loadOnce
    super.init()
}