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
Ios: Usage of Self and Underscore(_) with Variable
How to Share My Current Location to Uiactivityviewcontroller
Stroke Width with a Scenekit Line Primitive Type
How to Do Authorization and Login with Wechat Using the iOS Sdk
How to Get Static Image from Google Maps in iOS
Facebooksdk(4.1.X) Custom Login UI Button - Swift(1.2)
Asynchronous Upload with Nsurlsession Will Not Work But Synchronous Nsurlconnection Does
Using the C API for Imagemagick (On Iphone) to Convert to Monochrome
Learn About the Nsxmlparser in iOS
How to Parse Array of JSON to Array in Swift
Shrink Large Title When Scrolling (Not Uitableviewcontroller) iOS 11
Uploads Using Backgroundsessionconfiguration and Nsurlsessionuploadtask Cause App to Crash
Flutter iOS Build Failure Error with Multiple Commands After the Xcode Upgrade
Uiscrollview with Dynamically Sized Content
iOS Are Methods Called by Delegates and Observers Executed on the Main Thread