【问题标题】:How to conform to NSCopying and implement copyWithZone in Swift 2?如何在 Swift 2 中符合 NSCopying 并实现 copyWithZone?
【发布时间】:2015-08-20 07:19:29
【问题描述】:

我想在 Swift 2 中实现一个简单的 GKGameModel。Apple 的示例用 Objective-C 表示,并包含此方法声明(根据协议 NSCopying 的要求,GKGameModel 继承自该协议):

- (id)copyWithZone:(NSZone *)zone {
    AAPLBoard *copy = [[[self class] allocWithZone:zone] init];
    [copy setGameModel:self];
    return copy;
}

这如何转化为 Swift 2?以下在效率和忽略区域方面是否合适?

func copyWithZone(zone: NSZone) -> AnyObject {
    let copy = GameModel()
    // ... copy properties
    return copy
}

【问题讨论】:

    标签: swift swift2 gameplay-kit


    【解决方案1】:

    NSZone 在 Objective-C 中已经很久不用了。并忽略传递的zone 参数。引用allocWithZone... 文档:

    此方法存在历史原因;记忆区不再 由 Objective-C 使用。

    你也可以忽略它。

    这是一个如何遵守NSCopying 协议的示例。

    class GameModel: NSObject, NSCopying {
    
      var someProperty: Int = 0
    
      required override init() {
        // This initializer must be required, because another
        // initializer `init(_ model: GameModel)` is required
        // too and we would like to instantiate `GameModel`
        // with simple `GameModel()` as well.
      }
    
      required init(_ model: GameModel) {
        // This initializer must be required unless `GameModel`
        // class is `final`
        someProperty = model.someProperty
      }
    
      func copyWithZone(zone: NSZone) -> AnyObject {
        // This is the reason why `init(_ model: GameModel)`
        // must be required, because `GameModel` is not `final`.
        return self.dynamicType.init(self)
      }
    
    }
    
    let model = GameModel()
    model.someProperty = 10
    
    let modelCopy = GameModel(model)
    modelCopy.someProperty = 20
    
    let anotherModelCopy = modelCopy.copy() as! GameModel
    anotherModelCopy.someProperty = 30
    
    print(model.someProperty)             // 10
    print(modelCopy.someProperty)         // 20
    print(anotherModelCopy.someProperty)  // 30
    

    附:此示例适用于 Xcode 版本 7.0 beta 5 (7A176x)。尤其是dynamicType.init(self)

    为 Swift 3 编辑

    以下是 Swift 3 的 copyWithZone 方法实现,因为 dynamicType 已被弃用:

    func copy(with zone: NSZone? = nil) -> Any
    {
        return type(of:self).init(self)
    }
    

    【讨论】:

    • 我尝试为我的班级实现这一点,但是如何在复制班级变量的同时创建副本?现在,我得到了一个新实例,它没有从旧实例复制的属性。
    • 如何一次复制一个类的所有属性,而不是一个一个地做赋值。因为您看到我有一个包含大约 50 个属性的类,我很可能会错过其中一些属性的分配。有什么办法吗?
    【解决方案2】:

    Swift4,Helium 的 PlayItem 对象:

    // MARK:- NSCopying
    convenience required init(_ with: PlayItem) {
        self.init()
    
        self.name  = with.name
        self.link  = with.link
        self.date  = with.date
        self.time  = with.time
        self.rank  = with.rank
        self.rect  = with.rect
        self.plays = with.plays
        self.label = with.label
        self.hover = with.hover
        self.alpha = with.alpha
        self.trans = with.trans
        self.agent = with.agent
        self.tabby = with.tabby
    }
    
    func copy(with zone: NSZone? = nil) -> Any
    {
        return type(of:self).init(self)
    }
    

    【讨论】:

      【解决方案3】:

      A COPY OF ALREADY PRESENT array 字典的最后一个元素被复制并使用值创建。

      曾在 Xcode 12.1 swift 5 中工作

      // 模型类,其中为该类定义模型

      import Foundation
         class SampleClass: NSObject, NSCopying, Codable {
          
          var variable1: String?
          var variable2: String?
          var variable3: String?
          
          required override init() {
      
            }
          
          required init(_ model: SampleClass) {
      
              self.variable1 = model.variable1
              self.variable2 = model.variable2
              self.variable3 = model.variable3
          }
          
          func copy(with zone: NSZone? = nil) -> Any
          {
              return type(of:self).init(self)
          }
          
          init(_ dictionary: [String: Any]) {
              
          self.variable1 = dictionary["variable1"] as? String
          self.variable2 = dictionary["variable2"] as? String
          self.variable3 = dictionary["variable3"] as? String
          }
      
      }
      
      // How to use it in ViewController in a button where data from the model is already in a array of dictionary
      
       @IBAction func duplicate(_ sender: Any) {
              
              if self.currentArray > 0 {
                  if let content = self.self.currentArray.last {
                      let anotherCopy = content.copy() as! SampleClass
                      self.self.currentArray.append(anotherCopy)
                  }
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-24
        • 2011-08-18
        • 2015-06-30
        • 1970-01-01
        • 2011-05-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多