【问题标题】:"Extensions may not contain stored properties" unless your are Apple? What am I missing?除非您是 Apple,否则“扩展程序可能不包含存储的属性”?我错过了什么?
【发布时间】:2017-11-24 06:23:28
【问题描述】:

Apple 怎么能做到这一点:

import CoreGraphics
import GameplayKit
import simd

/**
 @header


 SceneKit framework category additions related to GameplayKit integration.


 @copyright 2017 Apple, Inc. All rights reserve.

 */

extension SCNNode {


    /**
     * The GKEntity associated with the node via a GKSCNNodeComponent.
     *
     * @see GKEntity
     */
    @available(OSX 10.13, *)
    weak open var entity: GKEntity?
}

/**
 * Adds conformance to GKSceneRootNodeType for usage as rootNode of GKScene 
 */
extension SCNScene : GKSceneRootNodeType {
}

...我不能这样做:

extension SCNNode {
    weak open var ntity: GKEntity?
}

得到两个错误:

  • 'weak' 只能应用于类和类绑定协议类型,而不是 '>'
  • 扩展可能不包含存储的属性

我真正想做的是在 10.13 之前的 OSX 版本上提供实体属性,因此也欢迎对此提出其他建议。

【问题讨论】:

  • 他们真的做不到。 SCNNode 可能是一个 Obj-C 扩展,这就是 Swift 接口的生成方式。这真的不是有效的 Swift。
  • 它可以是计算属性,它们看起来与生成界面中存储的属性相同。

标签: swift xcode swift4 xcode9


【解决方案1】:

Swift 4 / iOS 11 / Xcode 9.2

这里的答案在技术上是正确的,但无论如何这里有一个解决方案。

在您的扩展中,使用您想要的字段定义一个私有结构。将所有内容设为静态,如下所示:

private struct theAnswer {
    static var name: String = ""
}

我知道,我知道,静态意味着它是一个类范围的变量/属性,而不是一个实例。但我们实际上并不打算在这个结构中存储任何东西。

在下面的代码中,obj_getAssociatedObjectobjc_setAssociatedObject 都需要一个 UnsafeRawPointer 作为键。我们使用这些函数来存储与此唯一实例关联的键/值对。

下面是完整的字符串示例:

import Foundation

class ExtensionPropertyExample {

    // whatever
}


extension ExtensionPropertyExample {
    private struct theAnswer {
        static var name: String = ""
    }

    var name: String {
        get {
            guard let theName = objc_getAssociatedObject(self, &theAnswer.name) as? String else {
                return ""
            }
            return theName
        }
        set {
            objc_setAssociatedObject(self, &theAnswer.name, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }
}

【讨论】:

    【解决方案2】:

    目前这在 Swift 中是不可能的。正如 Sulthan 所说,这是一个 Objective-C 类别,您可以看到 Swift 版本,它是由 Xcode 生成的。

    现在,Objective-C 不支持在类别中添加属性(扩展在 Objective-C 中称为类别),但是您可以使用关联的对象来获得所需的内容。

    Mattt Thompson 在他的 NSHipster 博客上有一篇关于关联对象的精彩文章:Associated Objects - NSHipster

    【讨论】:

      【解决方案3】:

      有趣的是我和OP有同样的感觉。查看 Apple 自己的这篇博文:https://developer.apple.com/swift/blog/?id=37

      您会注意到他们明显违反了他们唯一的规则,并且他们解释了如何将 JSON 与不可编译的代码一起使用。

      extension Restaurant {
          private let urlComponents: URLComponents // base URL components of the web service
          private let session: URLSession // shared session for interacting with the web service
      
          static func restaurants(matching query: String, completion: ([Restaurant]) -> Void) {
              var searchURLComponents = urlComponents
              searchURLComponents.path = "/search"
              searchURLComponents.queryItems = [URLQueryItem(name: "q", value: query)]
              let searchURL = searchURLComponents.url!
      
              session.dataTask(url: searchURL, completion: { (_, _, data, _)
                  var restaurants: [Restaurant] = []
      
                  if let data = data,
                      let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
                      for case let result in json["results"] {
                          if let restaurant = Restaurant(json: result) {
                              restaurants.append(restaurant)
                          }
                      }
                  }
      
                  completion(restaurants)
              }).resume()
          }
      }
      

      整篇文章都是关于如何在 Swift 中处理 JSON,因此任何 Objective-C 代码中都没有定义“餐厅”。

      【讨论】:

        【解决方案4】:

        你可以试试这段代码,我使用的是 Xcode 8.3.3 和 Swift 3.1:

        import SceneKit
        import GameplayKit
        
        extension SCNNode {
        
            @available(OSX 10.13, *)
            public var entity: GKEntity? {
                return self.entity
            }
        }
        

        【讨论】:

        • 只允许获取属性
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-01-16
        • 2020-10-06
        • 1970-01-01
        • 2015-05-23
        • 1970-01-01
        • 1970-01-01
        • 2010-09-07
        相关资源
        最近更新 更多