Closed bonroyage closed 8 years ago
Thanks for your PR Roy! I've thought about adding such functionality multiple times before. Every time I decide not to do so though. I think the base Resource
class should be responsible for decoding/encoding its own properties only. It's up to the developer to decide and implement the coding for subclasses. Perhaps not every field should be encoded, or perhaps they should be encoding in a different way. This is pretty much how it's done all throughout the Cocoa frameworks, you need to implement your own coding, and call super
in both methods.
I appreciate your work but I don't think I'll merge it at this point. If you want this behaviour you can subclass Resource
and then subclass that into concrete resource classes.
That's a fair reasoning. I'll subclass Resource
then :) Thanks!
I seem to be having problems subclassing resource.
I created a new file, lets say MyResource.swift
with the following contents:
import Foundation
import Spine
public class MyResource : Resource {
public required init(coder: NSCoder) {
super.init(coder: coder)
for field in fields {
if coder.decodeObjectForKey(field.name) != nil { // here
setValue(coder.decodeObjectForKey(field.name), forField: field.name) // here
}
}
}
override public func encodeWithCoder(coder: NSCoder) {
super.encodeWithCoder(coder)
for field in fields {
coder.encodeObject(valueForField(field.name), forKey: field.name) // here
}
}
}
However it complains that Value of type 'Field' has no member 'name'
while following fields
clearly reveals it uses the Field
class, which does have the property name
, this exact same code worked while it was in your Resource
class.
Any ideas what I'm missing here?
The name
variable is internal to the Spine module, so it's not visible in your application code. You can use the serializedName
variable.
Edit: No, I now see that you can't actually because serializedName
is internal too. Hmm, might need to make that public.
Okay, making that public solved one issue. But in my own class I had to "override" the init(coder) function (without actually using the word override
) but now it expects me to add the coder
parameter to all places where I call my resource (ie. Event)
spine.registerResource(Event.resourceType) { Event() }
throws Missing argument for parameter 'coder' in call
I managed to fix the above issue by overriding the regular init
public override init() {
super.init()
}
Instead of making serializedName
public, please make name
public because name
is the one that is used to store the data in the model whereas serializedName
is the one used in the JSON response and doesn't necessarily correspond to the key in the model.
I'm thinking about getting rid of the name variable as a whole. It don't that that it is an implicitly unwrapped optional to support fieldsFromDictionary
. I think changing Resource.fields
to [String: Field]
, getting rid of fieldsFromDictionary
is the way to go.
I ran into this problem where I wanted to store a record in NSData so I could temporarily cache it and share among targets (ie. the app and a today extension) but none of the fields were populated anymore.
So I added an iterator to loop over the fields to the encoder/decoder of the resource and store/load those values.