在 Swift 中子类化 PFObject

Posted

技术标签:

【中文标题】在 Swift 中子类化 PFObject【英文标题】:Subclassing PFObject in Swift 【发布时间】:2014-07-05 00:38:00 【问题描述】:

用于在 PFObject 子类上添加属性和方法的 Parse 文档在其示例代码中方便地跳过了 Swift 语法,仅列出了 Objective-C 语法:

https://parse.com/docs/ios_guide#subclasses-properties/iOS

// Armor.h
@interface Armor : PFObject<PFSubclassing>
+ (NSString *)parseClassName;
@property (retain) NSString *displayName;
@end

// Armor.m
@dynamic displayName;

有没有人想出解决 Swift 缺少动态合成器的方法,以便使用 PFSubclassing 实现属性和方法?我希望能够做类似的事情:

class Armor : PFObject, PFSubclassing 
    class func parseClassName() -> String! 
        return "Armor"
    


var armor = Armor()
armor.displayName = "Iron Clad"

【问题讨论】:

“方便跳过”是指“尚未添加,因为您只能在 beta IDE 中使用该语言”? 所有你需要做的就是在你的类中添加var displayName = "default",你应该完成......(另外,没有理由让 parseClassName 返回一个String! - String 是完全足够的。 【参考方案1】:

我遇到了同样的问题。必须将 @NSManaged 添加到我想要保存的属性中:

class Armor : PFObject, PFSubclassing 
    @NSManaged var displayName: String

    class func parseClassName() -> String! 
        return "Armor"
    


var armor = Armor.object()
armor.displayName = "Iron Clad"

希望在下一次更新中解决这个问题。

【讨论】:

似乎是一个很好的临时解决方案。 Swift 文档说:Like the @dynamic attribute in Objective-C, the @NSManaged attribute informs the Swift compiler that the storage and implementation of a property will be provided at runtime. However, unlike @dynamic, the @NSManaged attribute is available only for Core Data support. 希望 Parse 尽快发布官方解决方案。【参考方案2】:

解决方案是使用计算属性而不是存储属性:

class Armor : PFObject, PFSubclassing 

    var displayName: String? 
        get 
            return self["displayName"] as? String
        
        set 
            self["displayName"] = newValue
        
    


    class func parseClassName() -> String 
        return "Armor"
    

【讨论】:

OP 需要接受这个作为答案,因为它也对我有用。多亏了这个答案,我不必浪费几个小时来解决这个问题。 Parse 还需要更新他们的文档,而不是依赖 SO 来记录他们快速做事的方法。 你仍然可以使用下标语法:) self["displayName"] = newValue 我需要添加这个,在类中覆盖 class func load() self.registerSubclass() ,并在我的桥接头中添加 #import 跨度> 我需要添加这个,在类中覆盖 class func load() self.registerSubclass() ,并在我的桥接头中添加 #import 完美. displayName 应该是 String? 类型,因为 objectForKey(..) 可能返回 nil?【参考方案3】:

Swift 1.2

首先:创建一个swift文件并定义子类。不要忘记导入 Parse! (例如盔甲)

import Foundation
import Parse


class Armor: PFObject, PFSubclassing 

    // MARK: - PFSubclassing

    override class func initialize() 
        struct Static 
            static var onceToken: dispatch_once_t = 0;
        
        dispatch_once(&Static.onceToken) 
            self.registerSubclass()
        
    

    class func parseClassName() -> String 
        return "Armor"
    


    // MARK: - Parse Core Properties

    @NSManaged var displayName: String?


注意:您可以将属性定义为可选项。 Parse Core Manager 中的每个“未定义”值都将被转换为“nil”。

第二:在你的AppDelegate.swift中注册所有子类。

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 
    // Override point for customization after application launch.

    // MARK: - Parse Setup
    Parse.setApplicationId("YOUR_ID", clientKey: "YOUR_KEY")

    // MARK: - Parse Register Subclasses
    Armor.registerSubclass()

    return true

【讨论】:

这符合 Parse 文档。您知道使用@Andrew Toth anshwer 是否有任何副作用? 如果在AppDelegate注册,可以去掉静态init注册码。根据我的经验,静态初始化代码——即使它在官方文档中——也会导致问题。所以我建议在 AppDelegate 中显式注册子类。 你还记得你遇到过什么样的问题吗?我刚刚找到了这个线程,试图解决一个问题,因为我的程序一直锁定在 loginWithUsernameInBackground() 中间的某个地方。如果我注释掉了似乎解决问题的initialize()方法。【参考方案4】:

原型是正确的。截至目前,它不适用于动态属性,但代码示例不包含 Parse 推荐的 registerSubclass,因此代码应该像这样包含它:

class Armor : PFObject, PFSubclassing 
    @NSManaged var displayName: String

    override class func load() 
        self.registerSubclass()
    
    class func parseClassName() -> String! 
        return "Armor"
    


var armor = Armor.object()
armor.displayName = "Iron Clad"

(请注意,“覆盖”是必需的,但 Parse 文档中缺少。)

【讨论】:

在 Swift 2 及更高版本中不允许覆盖 load【参考方案5】:

我遇到了同样的问题,但我应该注意你的类定义应该更像这样:

class Armor : PFObject, PFSubclassing 
    var displayName: String

    class func parseClassName() -> String! 
        return "Armor"
    


var armor = Armor()
armor.displayName = "Iron Clad"

我尝试了一些不同的方法,但都没有成功。 Parse SDK 似乎还不支持这一点,请记住,Parse iOS SDK 的当前版本早于 swift 公告。听起来他们正在努力为即将发布的版本提供更好的快速支持。

相反,您仍然可以创建 PFObject 子类(就像您所做的那样)并使用 .getObjectForKey("displayName") 访问数据,或者编写您自己的类方法来访问这些数据。最大的缺失实际上只是 SDK 通常为您创建的一些便利方法。

【讨论】:

以上是关于在 Swift 中子类化 PFObject的主要内容,如果未能解决你的问题,请参考以下文章

想知道如何以编程方式在 swift 3.0 中对 UITableViewCell 进行子类化?

子类化 NSControl,在 Swift 中不调用 IBAction

将 NSManagedObject 子类化 Core Data 对象打印到控制台在 Swift 中返回空行

使用 Swift 子类化 UIApplication

Swift 中的 NSWindowController。使用 Nib 进行子类化和初始化

UIViewController 的 Swift 子类化子类