在Swift中创建PFObject子类

16

在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"

5
“方便地跳过”指的是“因为你只能在测试版的集成开发环境中使用该语言,所以尚未添加”? - nhgrif
你只需要在你的类中添加 var displayName = "default",然后就可以完成了...(另外,没有理由使解析类名返回一个 String! - String 十分足够。) - Grimxn
5个回答

22

我曾经遇到了同样的问题。不得不在我想要保存的属性中添加@NSManaged:

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

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

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

希望这个问题能在下一个更新中得到解决。


1
似乎是一个不错的临时解决方案。Swift文档中说:“与Objective-C中的@dynamic属性类似,@NSManaged属性通知Swift编译器该属性的存储和实现将在运行时提供。但是,与@dynamic不同,@NSManaged属性仅适用于Core Data支持。”希望Parse很快发布官方解决方案。 - Arman

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

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

class Armor : PFObject, PFSubclassing {

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


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

2
OP需要接受这个答案,因为它对我也起作用了。由于这个答案,我没有浪费几个小时来解决这个问题,感谢这个答案。Parse还需要更新他们的文档,不要依赖SO来记录他们在Swift中处理事物的方法。 - jpittman
1
你仍然可以使用下标语法 :) self["displayName"] = newValue - wfbarksdale
我需要在类中添加以下内容:override class func load() { self.registerSubclass() },并在我的桥接头文件中添加 #import <Parse/PFObject+Subclass.h>。 - DogCoffee
由于 objectForKey(..) 可能返回 nil,因此 displayName 应该是 String? 类型吗? - user
编辑了您所有的建议。 - Andrew Toth
显示剩余2条评论

6

Swift 1.2

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

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
}

这符合解析文档。您是否知道使用@Andrew Toth答案是否有任何副作用? - Damasio
如果您在AppDelegate中注册,可以删除静态init注册代码。根据我的经验,即使它在官方文档中,静态init代码也会引起问题。因此,我建议在AppDelegate中明确注册子类。 - n13
你还记得遇到了什么问题吗?我刚刚发现了这个线程,试图解决一个问题,因为我的程序在loginWithUsernameInBackground()的中间某个地方一直卡住。如果我注释掉initialize()方法,似乎可以解决问题。 - Michael Rogers

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"

(请注意,“override”是必需的,但在Parse文档中缺失。)

在Swift 2及更高版本中,不允许覆盖load方法。 - Martin R

1
我遇到了相同的问题,不过我应该指出你的类定义应该更像这样:
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的宣布。不过听起来他们正在为即将发布的版本开发更好的Swift支持。
相反,您仍然可以创建PFObject子类(就像您所做的那样),并使用.getObjectForKey("displayName")访问数据,或编写自己的类方法来访问此数据。最大的缺失部分实际上只是一些方便的方法,而SDK通常会为您创建这些方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接