2

I've got a weird issue with accessing member fields using dot notation. Example:

SettingsModel

class SettingsModel: PFObject, PFSubclassing {

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

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

    @NSManaged var name:String
    @NSManaged var code:String
    @NSManaged var friend:FriendsModel

}

FriendsModel

class FriendsModel: PFObject, PFSubclassing {

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

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

    @NSManaged var user:PFUser
    @NSManaged var settings:SettingsModel
}

When I try to access friends name using mySettings.friend.settings.name I'm getting unrecognized selector on "settings".

But interestingly enough when I use (mySettings.friend["settings"] as SettingsModel).name it works. I've intentionally omitted all the conditional unwrapping, etc. - I've got valid PFObject of the right type with all the data...

I'm sure it's something trivial but can't figure it out... Any help would be appreciated. Using Parse 1.8.2.

Tom
  • 1,516
  • 1
  • 14
  • 34
  • Would you give us more context? Like the whole class declarations? – Jason Nam Sep 09 '15 at 07:52
  • You mean the model classes? They are just standard Parse subclass templates but I've added them anyway. Cheers – Tom Sep 09 '15 at 09:31
  • @Tom Did you figure out what the issue was? I'm running into the same issue. – otusweb Dec 31 '15 at 14:49
  • Unfortunately no, it's still not working for me. I'm using the workaround mentioned in original question – Tom Jan 01 '16 at 09:31
  • Why using `@NSManaged` which is for CoreData? So the work around for the getter/setter and the issue with the dot notation seems correct (see the quote from https://stackoverflow.com/a/24015789/1801544) – Larme Sep 22 '17 at 15:58

3 Answers3

3

It looks like FriendsModel was not successfully registered as a Parse subclass, despite your implementation of PFSubclassing. It could be the case that the initialize() of FriendsModel is not yet called when you access it via mySettings.friend.settings.name.

To solve this issue you can register your FriendsModel subclass earlier with Parse by calling FriendsModel.registerSubclass(), just before the location where you call Parse.setApplicationId(..).

This is how I solved these kinds of issues myself, I hope it helps in your case too.

Peter Fennema
  • 1,650
  • 12
  • 14
  • I suspected that might be the problem originally so I've added SettingsModel.initialize() and FriendsModel.initialize() as the very first thing in AppDelegate. But alas didn't help. – Tom Sep 09 '15 at 10:32
  • 1
    registerSubclass() method worked for me and solved the problem :) – user4478383 Jan 08 '16 at 12:11
  • I am having the same issue, definitely calling [MyClass registerSubclass], and even tried re-arranging it to make sure that the class that gets nested is registered first in case that causes a problem. Although, the key accessor worked for me to get around the issue for now. – Jake T. Oct 27 '16 at 17:36
3

wow...I think I found the reason behind your problem, but it would be one of those "how in hell can this be the reason" type of solutions. I came across this thread because I received the same error message and I'm pretty much in a similar environment (parse, subclassing, swift). The line where my app crashed was this one:

let setOpts = self.thing?.settingOptions

where the variable "thing" represents a PFObject as well as "settingOptions". So I thought that maybe it was also a problem of falsely registered subclasses, although I think that's not necessary anymore in the recent Parse versions (I'm using v1.15.1). Anyway, the workaround you provided helped at first, but made my app crash at that next line:

if (self.thing?.setting != nil) {...}

and then it got me thinking...wait a minute...there were several other properties of "thing" accessed through dot notation in between which did not crash, so why again here?! When I checked back at your post it hit me right in the face. I hope everybody sees it by now because you might not believe me if I tell you...but I'm gonna anyways:

The properties we use all start with setting.

And that seems to be it. I don't know if they shouldn't start with "set" or "setti", but definitely not with "setting". As soon as I changed the name to something completely different it worked. Maybe the classname is relevant, too, but mine starts with a prefix so "setting" is only part of the name. Hope this helps ;)

tr03lf
  • 43
  • 4
  • wow. I can't believe how lucky I am that I found this answer. I could easily of seen myself troubleshooting this for the next 5 hours. Thanks man. – Alex Ritter Apr 29 '18 at 21:36
  • omfg. I can confirm this. I had a PFObject subclass with a property called "sets". (i.e. sets of repetitions, for an exercise). Inexplicable crash. Googled in desperation, and stumbled across this answer. Changed to "repSets", and works. :/ – James White Oct 30 '18 at 11:28
0

Don't have an answer as to why it's happening but i'm using a workaround that is slightly cleaner in my mind as the workaround is only in one place. Namely using the setter and getter functionality of swift.

class SettingsModel: PFObject, PFSubclassing {

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

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

@NSManaged var name:String
@NSManaged var code:String
var friend:FriendsModel
    {
        get
        {
             return self["friend"] as! FriendsModel 
        }
        set
        {
             self["friend"] = newValue
        }
    }

}
otusweb
  • 1,638
  • 1
  • 19
  • 30