Subclass of subclass of PFObject not being registered - ios

I have a class called Attendee which inherits from PFObject. I also have another class called Speaker which is a child of Attendee.
Below are the class definition for Attendee & Speaker
class Attendee: PFObject, PFSubclassing {
override class func initialize() {
var onceToken : dispatch_once_t = 0;
dispatch_once(&onceToken) {
self.registerSubclass()
}
}
class func parseClassName() -> String {
return "Attendee"
}
}
class Speaker: Attendee {
override class func initialize() {
var onceToken : dispatch_once_t = 0;
dispatch_once(&onceToken) {
self.registerSubclass()
}
}
}
I register both in my applicationDidFinishLaunch method before using any parse features:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Speaker.initialize()
Attendee.initialize()
Parse.setApplicationId(ObjectManager.appID, clientKey: ObjectManager.clientKey)
...
}
However, when I try to use the Attendee and Speaker classes later on in my code, I get this error:
The class MedConf.Attendee must be registered with registerSubclass before using Parse.
The code that triggers the error is:
var attendee = Attendee()
I don't understand why this is happening, as I clearly register both the subclasses before I do anything with them.

My bet is you can't subclass any class the implements a PFSubclassing protocol. Try making the Speaker it's own class and build the relationship use the relationship API in Parse. If you need a resource to build relational data, check here. https://www.parse.com/docs/ios/guide#objects-relational-data

Related

Call a method with dynamic class name in swift

How can we call class functions with a dynamic class name?
Assume the following example where I have two class with methods with same signature
class Foo{
class func doSomething()
}
class Foobar {
class func doSomething()
}
class ActualWork{
//call following method with a variable type so that it accepts dynamic class name
func callDynamicClassMethod(x: dynamicClass)
x.doSomething()
}
How can this be implemented so that x accepts values at run time
Edit: Sorry, I missed to mention that I was looking for any other ways other than protocol oriented approach. This is more of an exploratory question to explore if there is a more direct approach/pods/libraries to achieve this.
I liked this question, because it made me to think a lit'bit outside of the box.
I'll answer it, by dividing it into a few parts.
First
call class functions
Class function is basically a Type methods, which can be achieved using the static word inside the class context.
Taking that into account, you can get a simple solution, using protocol and passing the class reference (conforming to that protocol) like this:
protocol Aaa{
static func doSomething();
}
class Foo : Aaa{
static func doSomething() {
print("Foo doing something");
}
}
class FooBar : Aaa{
static func doSomething() {
print("FooBar doing something");
}
}
class ActualWork{
//Using class (static) method
func callDynamicClassMethod <T: Aaa> (x: T.Type) {
x.doSomething();
}
}
//This is how you can use it
func usage(){
let aw = ActualWork();
aw.callDynamicClassMethod(x: Foo.self);
aw.callDynamicClassMethod(x: Foo.self);
}
Second
In case you don't really need the method on the class context, you may consider using instance methods. In that case the solution would be even simpler, like this:
protocol Bbb{
func doSomething();
}
class Bar : Bbb{
func doSomething() {
print("Bar instance doing something");
}
}
class BarBar : Bbb{
func doSomething() {
print("BarBar instance doing something");
}
}
class ActualWork{
//Using instance (non-static) method
func callDynamicInstanceMethod <T: Bbb> (x: T){
x.doSomething();
}
}
//This is how you can use it
func usage(){
let aw = ActualWork();
aw.callDynamicInstanceMethod(x: Bar());
aw.callDynamicInstanceMethod(x: BarBar());
}
Third
If you need to use the class func syntax, as OP originally did:
class func doSomething()
You CANNOT simply use a protocol. Because protocol is not a class...
So compiler won't allow it.
But it's still possible, you can achieve that by using
Selector with NSObject.perform method
like this:
class ActualWork : NSObject{
func callDynamicClassMethod<T: NSObject>(x: T.Type, methodName: String){
x.perform(Selector(methodName));
}
}
class Ccc : NSObject{
#objc class func doSomething(){
print("Ccc class Doing something ");
}
}
class Ddd : NSObject{
#objc class func doSomething(){
print("Ccc class Doing something ");
}
#objc class func doOther(){
print("Ccc class Doing something ");
}
}
//This is how you can use it
func usage() {
let aw = ActualWork();
aw.callDynamicClassMethod(x: Ccc.self, methodName: "doSomething");
aw.callDynamicClassMethod(x: Ddd.self, methodName: "doSomething");
aw.callDynamicClassMethod(x: Ddd.self, methodName: "doOther");
}
Generics and Protocol oriented programming will do the job:
protocol Doable {
static func doSomething()
}
class Foo: Doable {
static func doSomething() {
debugPrint("Foo")
}
}
class Foobar: Doable {
static func doSomething() {
debugPrint("Foobar")
}
}
class ActualWork {
func callDynamicClassMethod<T: Doable>(x: T.Type) {
x.doSomething()
}
}
let work = ActualWork()
work.callDynamicClassMethod(x: Foo.self)
work.callDynamicClassMethod(x: Foobar.self)
you can achieve this with help of Protocol
protocol common {
static func doSomething()
}
class Foo : common{
static func doSomething() {
print("Foo")
}
}
class Foobar : common {
static func doSomething() {
print("Foobar")
}
}
class ActualWork{
//call following method with a variable type so that it accepts dynamic class name
func callDynamicClassMethod(x: common.Type) {
x.doSomething()
}
}
let fooObj : common = Foo()
let Foobarobj : common = Foobar()
let workObk = ActualWork()
workObk.callDynamicClassMethod(x:Foo.self)
workObk.callDynamicClassMethod(x:Foobar.self)
I think, there are three solutions. I shared an sample below.
Use "protocol" that has "doSomething()" function requirements.
Create a function which gets function definition as a parameter.
Use reflection. you can use EVReflection that is good Api for reflection.
sample code:
protocol FooProtocol {
static func doSomething()
}
class Foo: FooProtocol {
class func doSomething() {
print("Foo:doSomething")
}
}
class Foobar: FooProtocol {
class func doSomething() {
print("Foobar:doSomething")
}
}
class ActualWork {
func callDynamicClassMethod<T: FooProtocol>(x: T.Type) {
x.doSomething()
}
func callDynamicClassMethod(x: #autoclosure () -> Void) {
x()
}
func callDynamicClassMethod(x: () -> Void) {
x()
}
}
ActualWork().callDynamicClassMethod(x: Foo.self)
ActualWork().callDynamicClassMethod(x: Foobar.self)
print("\n")
ActualWork().callDynamicClassMethod(x: Foo.doSomething())
ActualWork().callDynamicClassMethod(x: Foobar.doSomething())
print("\n")
ActualWork().callDynamicClassMethod(x: Foo.doSomething)
ActualWork().callDynamicClassMethod(x: Foobar.doSomething)
Looks like you are searching for duck typing, and this is harder to achieve in a statically typed language (with some exceptions, listed in the linked Wikipedia page).
This is because dynamically calling a method requires knowledge about the layout of the target object, thus either inheritance of the class declaring the method, or conformance to a protocol that requires that method.
Starting with Swift 4.2, and the introduction of dynamic member lookup, there is another approach to solve your problem, however it also involves some ceremony:
// This needs to be used as base of all classes that you want to pass
// as arguments
#dynamicMemberLookup
class BaseDynamicClass {
subscript(dynamicMember member: String) -> () -> Void {
return { /* empty closure do nothing */ }
}
}
// subclasses can choose to respond to member queries any way they like
class Foo: BaseDynamicClass {
override subscript(dynamicMember member: String) -> () -> Void {
if member == "doSomething" { return doSomething }
return super[dynamicMember: member]
}
func doSomething() {
print("Dynamic from Foo")
}
}
class Bar: BaseDynamicClass {
override subscript(dynamicMember member: String) -> () -> Void {
if member == "doSomething" { return doSomething }
return super[dynamicMember: member]
}
func doSomething() {
print("Dynamic from Bar")
}
}
func test(receiver: BaseDynamicClass) {
receiver.doSomething()
}
test(receiver: Bar()) // Dynamic from Bar
To conclude, in the current Swift version there is no way to have both the argument and the method dynamic, some common ground needs to be set.

Method cannot be marked #objc because its result type cannot be represented in Objective-C

am exposing swift API's in Objective-C and the Objective-C runtime.
When i add "#objc" before the function throws an error "Method cannot be marked #objc because its result type cannot be represented in Objective-C"
My code is here
#objc public static func logIn(_ userId: String) -> User? { }
User is optional struct. how to solve this.
The key bit of information is this:
User is optional struct
If User is a struct, then it can't be represented in Objective-C, just the same as a Swift class that doesn't inherit from NSObject.
In order for the method logIn(_:) to be able to be marked #objc, then every type referenced in the method declaration has to be representable in Objective-C. You're getting the error message because User isn't.
To fix it, you're either going to have to change the declaration of User from this:
struct User {
// ...
}
...to this:
class User: NSObject {
// ...
}
...or redesign logIn(_:) so that it doesn't return a User.
You can find more information about this here. In particular, this answer offers the following potential solution:
The best thing i found was to wrap in a Box class
public class Box<T>: NSObject {
let unbox: T
init(_ value: T) {
self.unbox = value
}
}
Change the definition of your class as below
class User: NSObject {
}
In this way this class will be available in Objective-C
Your class or protocol, must be inherited (extended) by NSObject or anyother class in its hierarchy, containing your code (function) with #objc notation.
Example:
class TestClass {
public static func logIn(_ userId: String) -> User? { }
}
To use/declare #objc with this function, class must extend NSObject (or any other class in its hierarchy)
class TestClass {
#objc public static func logIn(_ userId: String) -> User? { }
}
Update:
struct may not work with optional value in Objective-C, as a work around, you should change User from struct to class
Try following code and see:
public class User : NSObject {
// Your code
}
public final class Manager : NSObject {
#objc public static func logIn(_ userId: String) -> User? {
return nil
}
}
Here is snapshot with editor
Only an NSObject-derived class type can be seen by Objective-C. Use:
class User : NSObject {
}

Swift Framework Class to Swift Application

Getting problem with adding my Swift Framework to Test Swift Application.
What i have:
Framework class code, Target Called 'Project':
public let Instance = Library()
public class Library {
public class var sharedInstance: Library {
return Instance
}
/* SOME CODE */
}
Than i build it and add Project.framework to Test Swift Application
Usage:
import Project
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
/* NOT WORKING
ERROR: Use of Unresolved Identifier 'Instance' */
Instance.Setup("d573732b9f8b478d",apiKey: "3XmdIY=", enablePush: true)
/* NOT WORKING TOO
ERROR: Use of Unresolved Identifier 'Library' */
let lib = Library()
return true
}
Functions public, DeviredData deleted, what i'm doing wrong?
Answer was very easy:
Adding constructor function
public init(){
}
Problem solved.
Yes, making public constructor will help you, as per my knowledge default constructor has internal scope. It works for me.
public override init() {
}

Parse SDK and Swift 1.2: Can´t subclass PFUser

Before updating to Swift 1.2 subclassing PFUser worked just fine, now I can´t make it work.
My custom PFUser-class:
public class CustomUser: PFUser, PFSubclassing {
#NSManaged var fullName : String!
#NSManaged var phone : String!
public override class func initialize(){
self.registerSubclass()
}
}
When I use this class in my code the method calls still goes to the PFUser class:
reason: '-[PFUser fullName]: unrecognized selector sent to instance
0x17018fbe0'
This behavior started with Swift 1.2. I´ve updated the Parse SDK to the lastest version as well.
I've just been through this. The change in behaviour is a huge pain. You need to register your subclasses before you set your Parse app ID (typically in your application delegate).
So, in your app delegate...
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
CustomUser.registerSubclass()
Parse.setApplicationId("XXX", clientKey: "YYY")
......
return true
}
Another solution seems to be a singleton, provided in the Parse manual as follows, which works without any problems. This code works for all subclasses not only PFUser. If done this way, there is no need to register the subclass in didFinishLaunchingWithOptions.
class User: PFUser, PFSubclassing {
// MARK: PFUser Subclassing
override class func initialize() {
struct Static {
static var onceToken : dispatch_once_t = 0;
}
dispatch_once(&Static.onceToken) {
self.registerSubclass()
}
}
// non essential code removed
}

Swift Passing data from appDelegate to another class

I need to pass a variable from the AppDelegate to another class that I have created to hold global variables of the project and I'm not able to find a way to make it work.
This is the code in the AppDelegate:
func application(application: UIApplication!, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData!) {
println("Device's token is: \(deviceToken)")
//Global Variables Class Instance
let globals:Globals = Globals()
globals.setDeviceToken("test1") //method1 not working
globals.deviceToken = "test2" //method2 not working
}
This is my Globals Class:
public class Globals {
var deviceToken = String()
init() {
//nothing
}
func setDeviceToken(s:String){
deviceToken = s
}
func getDeviceToken() -> String {
return deviceToken
}
}
If i try to print the value, from other files of the project, I'm not able to get anything, just an empty string.
class ViewController: UIViewController {
//Global Variables Class Instance
let globals:Globals = Globals()
override func viewDidLoad() {
println(globals.getDeviceToken()) //return empty string
println(globals.deviceToken) //return empty string
There are several patterns you can use to achieve what you want
You could access the AppDelegate through the UIApplication:
let delegate = UIApplication.sharedApplication().delegate as AppDelegate
let deviceToken = delegate.deviceToken
Look into singletons. A quick google search for 'Swift singleton' will get you a long way. The first result:
class SingletonB {
class var sharedInstance : SingletonB {
struct Static {
static let instance : SingletonB = SingletonB()
}
return Static.instance
}
}
Then use sharedInstance to instantiate the singleton anywhere and access the same variables.
The first one is quick and dirty, so for more serious projects I would recommend the singleton pattern.
There are probably a million ways to do this, but this should get you started
(More at this link, which explores a few ways to implement singletons: https://github.com/hpique/SwiftSingleton )
I simply solved my problem using NSUserDefaults
in the AppDelegate:
NSUserDefaults.standardUserDefaults().setObject(deviceToken, forKey: "deviceToken")
NSUserDefaults.standardUserDefaults().synchronize()
From other classes:
NSUserDefaults.standardUserDefaults().objectForKey("deviceToken")
Honestly I don't know if this is a good way to do it but it's working

Resources