2013-11-23 33 views
3

我有一個名爲MediaFile的PFObject子類。爲了從電話找回我的子類的實例的服務器,我已經看到了你可以如何構造查詢瞭解析子這樣的:解析:使用PFCloud調用的PFObject子類

PFQuery *query = [MediaFile query]; 
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { ... }]; 

然而,大多數在我的應用程序調用服務器的都是定製雲調用,返回PFObjects。一旦我檢索到這些對象,我想將它們視爲MediaFile對象,並在它們上調用MediaFile類中定義的自定義方法。投射不起作用,因爲它實際上並不構建MediaFile對象。我做了什麼來解決這個問題是建設新的MediaFiles爲我回去用[MediaFile object]每個PFObject,然後使用方法我編寫的名爲loadFromObject:所有的數據複製到每一個:

[PFCloud callFunctionInBackground:@"func" withParameters:@{} block:^(id objects, NSError *error) { 

    for (PFObject *object in objects) { 

    MediaFile *mf = [[MediaFile object] loadFromObject:object]; 

    [array addObject:mf]; 
    } 
}]; 

在MediaFile.m :

- (MediaFile *) loadFromObject:(PFObject *)object { 
    NSArray *keys = [object allKeys]; 

    for (NSString *key in keys) { 
    id obj = [object objectForKey:key]; 
    [self setObject:obj forKey:key]; 
    } 

    return self; 
} 

這有用,但有沒有更好的方法來解決這個問題?

回答

1

您的自定義類是如何定義的? 因爲它們的子類機制依賴於鍵值編碼(KVC)。 這是KVC Programming Guide。或者,您可以通過here查看指南。

下面的示例應該工作。


在標題:

@interface CustomObject : PFObject <PFSubclassing> 

@property (nonatomic, strong) NSString *propertyName; 

在實施:

#import <Parse/PFObject+Subclass.h> 

#pragma mark - columns of Parse table 
@dynamic propertyName; 

#pragma mark - regiester parse subclass in runtime 
+ (void)load { 
    @autoreleasepool { 
     [self registerSubclass]; 
    } 
} 

#pragma mark - parse cloud table name 
+ (NSString *)parseClassName 
{ 
    return @"CustomObject"; // table name 
} 
0

很簡單畢竟。對我來說有效的是將返回的PFObject簡單地分配給PFObject的Objective-C子類。所以你的情況,

[PFCloud callFunctionInBackground:@"func" withParameters:@{} block:^(id objects, NSError *error) { 

    for (PFObject *object in objects) { 

    MediaFile *mf = object; // simple as that 

    [array addObject:mf]; 
    } 
}]; 
1

TL; DR: 確保您的PFObject子類與解析註冊您的雲代碼淨調用返回這些對象的時間。

如果你已經使用the instructions Parse includes in it's documentation guide子類PFObject,你可以返回你的自定義子類的第一個網內通話之前進行下面的調用:

CustomSubclass.initialize()

一個好地方,添加此代碼是你的應用代理的application(didFinishLaunchingWithOptions:)方法,它可能會在與您的子類相關的任何其他代碼之前運行。


龍版採用的解釋

我的情況是從你的有點不同,但我相信這個問題在很大程度上是相同的。我的問題是我通過PFQuery獲取對象,查詢回調中返回的對象只是通用的PFObject s。

這裏就是看着我的代碼,如:

// Scene is a PFObject subclass func getLatestScenes(completion: ((scenes: [Scene]) -> Void)?) { var query = PFQuery(className: SceneClassName) query.findObjectsInBackgroundWithBlock { (results: [AnyObject]?, error: NSError?) -> Void in if let scenes = results as? [Scene] { // This would never run, as the members of `results` were only PFObjects completion?(scenes: scenes) } else { // Code would always skip to the empty result case completion?(scenes: []) } } }

results陣列的單個成員將與描述中的調試器明確表示,他們被認爲是類Scene的打印出來,如預期,但檢查時只有PFObject s。

(lldb) po results![0] <Scene: 0x7fc743a8f310, objectId: YyxYH9dtBp, localId: (null)> { creator = "<PFUser: 0x7fc74144b320, objectId: FV3cmDI1PW>"; sceneDataFile = "<PFFile: 0x7fc743a96920>"; } (lldb) p results![0] (PFObject) $R6 = 0x00007fc743a8f310 { NSObject = { isa = 0x00007fc743a8f310 } ... // Info on object... ... }

的這裏的問題是,Scene對象沒有被正確使用Parse註冊爲PFObject子類。該initialize方法正確地重寫,像這樣:

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

initalize功能並沒有被查詢被稱爲時間調用。問題是在第一封郵件發送到該類之前,正在調用一個類的initialize方法,但在執行查詢之前沒有將郵件發送到Scene。添加下面一行到我的AppDelegate的application(didFinishLaunchingWithOptions:)解決了這個問題

Scene.initialize()

之後,解析能夠推斷出傳入數據的對象應該是哪一類的客戶端上,並構建了結果數組與類。