Subclassing Pfobject in Swift

iOS Parse PFObject Subclassing with Swift Behaviour

Yup, it's a bug that will be addressed in 1.7.3 https://developers.facebook.com/bugs/1647055045527392/

subclass PFObject and override init

Try updating your subclass to the following. Notice the NSManaged keywords for the Parse properties you've added to your Wish subclass and the removal of super.init()

You will probably also want to look into replacing the UIImage properties with the Parse-provided PFFile properties. You can easily store and load images using PFImageView included in the ParseUI framework.

import Foundation
import Parse

class Wish: PFObject, PFSubclassing {

// MARK: - Parse Core Wish Properties

@NSManaged var id: String?
@NSManaged var name: String?
@NSManaged var descriptionWish: String?
@NSManaged var photo: UIImage
@NSManaged var photoThumbnail: UIImage
@NSManaged var amount: Double?
@NSManaged var amountDonated: Int?

// MARK: - Lifecycle

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

static func parseClassName() -> String {
return "Wish"
}

convenience init(id: String?, name: String?, descriptionWish: String?, photo: UIImage, photoThumbnail: UIImage, amount: Double?, amountDonated: Int?) {
self.init()
self.id = id
self.name = name
self.descriptionWish = descriptionWish
self.photo = photo
self.photoThumbnail = photoThumbnail
self.amount = amount
self.amountDonated = amountDonated
}
}

Parse - Subclassing with Swift?

Check out this thread. Here is an explanation of the problem:

I already opened a bug to Parse about this point. Basically the issue is with the Parse header files where the protocol definition inside PFSubclassing.h defines this method in this way: + (instancetype)objectWithoutDataWithObjectId:(NSString )objectId; but then the same method is implemented by PFObject+Subclass.h in this way (notice the difference: instancetype --> id) + (id)objectWithoutDataWithObjectId:(NSString )objectId; This is enough for Swift to complain. The only solution I found is to directly change the header in the framework definition by replacing "id" with "instancetype". If you do this, the code will compile.

So, here's your solution, and it's worked for me; I had the same problem:

  • Open PFSubclassing.h (note that this is the PFSubclassing.h under your Parse directory)
  • Find the objectWithoutDataWithObjectId: method
  • Replace the method signature with: (id)objectWithoutDataWithObjectId:(NSString *)objectId;

parse.com in Swift - is it possible to cast retrieved PFObject as subclass?

Be sure you've registered subclass in application:didFinishLaunchingWithOptions:. In my case, it doesn't cast the retrieved object as the PFObject subclass.

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

Armor.registerSubclass()

Parse.enableLocalDatastore()
Parse.setApplicationId(..., clientKey: ...)

return true
}

AppDelegate.swift

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

CatsObject.registerSubclass()

Parse.enableLocalDatastore()
Parse.setApplicationId("...", clientKey: "...")

return true
}

CatsObject.swift

import Foundation

class CatsObject: PFObject, PFSubclassing {
static func parseClassName() -> String {
return "Cat"
}
}

CatViewController.swift

override func viewDidLoad() {
queryData()
}

func queryData() {
let query = PFQuery(className: CatsObject.parseClassName())
query.fromLocalDatastore()
query.findObjectsInBackgroundWithBlock({
(objects:[AnyObject]?, error: NSError?) in
if let error = error {
// There was an error
} else {
println("count local objects = \(objects?.count)")
if let objects = objects as? [PFObject] {
for object in objects {
println("PFObject object retrieved")
if object is CatsObject {
println("object is CatsObject subclass")
}

if let object = object as? CatsObject {
println("PFObject object cast as CatsObject")
}
}
}
}
})
}

Console output

count local objects = Optional(10)
PFObject object retrieved
object is CatsObject subclass
PFObject object cast as CatsObject

Could not init a PFObject subclass

THIS HAS BEEN FIXED IN 1.7.3 PARSE SDK
You can download the new version here:
https://parse.com/docs/downloads

=========================================================================

Though docs are not clear on that, using .object() in Swift is not required anymore.
as said here and in the Swift code snippet found here

Now, this is weird but to make Armor() work you need to reference PFUser class somehow in the same file. Maybe it doesn't have to be PFUser but I havent dug deeper into it.

So, this won't work

import UIKit
import Parse
import Bolts

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Parse.setApplicationId("appID", clientKey: "clientKey")

let myArmor = Armor()

return true
}
}

But this will

import UIKit
import Parse
import Bolts

private let fix = PFUser.hash() // here's the weird trick

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Parse.setApplicationId("appID", clientKey: "clientKey")

let myArmor = Armor()

return true
}
}

Hope this helps and Parse pushes a fix out soon.

Also reported as a bug

Parse.com subclassing in Swift 2

First of all make sure you have the latest Parse SDK. If you have the latest SDK you can create a PFObject Subclass like this;

class Armor: PFObject, PFSubclassing {

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

When you create your custom Subclass, you should register your subclass to Parse SDK in AppDelegate like this;

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

//Registering SubClasses
Armor.registerSubclass()

// Initialize Parse.
Parse.enableLocalDatastore()
Parse.setApplicationId("Your API Key", clientKey: "Your Client Key")

return true
}

Subclass PFUser in swift

BridgingHeader.h:

#import <Parse/Parse.h>
#import <Parse/PFObject+Subclass.h>

User.swift:

import Foundation

class User : PFUser, PFSubclassing {

override class func load() {
self.registerSubclass()
}

//My variables
dynamic var firstname: String
dynamic var lastname: String

}

DONT´T include this snippet when subclassing PFUser:

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


Related Topics



Leave a reply



Submit