Xcode auto-complete suggests mysterious "songsAtIndexes" for NSArray getter - ios

I have a property of type NSArray on my class called "songs". I'm creating a custom getter for it and XCode gives me an option of creating a method:
songsAtIndexes:(NSIndexSet *)indexes
What is this and why is XCode offering this? Is this specific to NSArray properties? What is the purpose of creating a method/getter for this method? If I don't define it manually, will it be automatically created/synthesized?

This is the result of a little-used KVC optimization for indexed collections which can be used on your class. You can read about this here, but to excerpt:
Indexed To-Many Relationship Compliance
For indexed to-many relationships, KVC compliance requires that your class:
Implement a method named -<key> that returns an array.
Or have an array instance variable named <key> or _<key>.
Or implement the method -countOf<Key> and one or both of -objectInAtIndex: or -<key>AtIndexes:.
Optionally, you can also implement -get<Key>:range: to improve performance.
It's only really used with Core Data with KVC (and occasionally NSPredicates), but you can leverage these methods if you'd like to.
It's really not necessary in 99% of cases to implement this, but you can if you'd like.

Related

Upcasting NSObject to RLMObject

How would you upcast an NSObject to a RLMObject?
Say you have a model object that's of type NSObject, and say you wanted to dynamically upcast it to RLMObject, how would you do it?
It's worth mentioning that RLMObject's properties can't be populated at runtime, else I probably would've done it through <objc/runtime.h>. (I mean.. They technically can... It would just be too much of a hack)
What I'm trying to do:
The main purpose behind this is to create a caching framework that would dynamically choose between interchangeable caching dependencies such as Realm, SQLite, Core Data, etc. For example, I imagine having a preprocessor flag to hopefully switch from using Realm to SQLite, without having to change my models subclass.
This would require all of my models being a subclass of NSObject, simply because RLMObject wouldn't make sense in a SQLite environment for example.
I've been thinking about this a whole lot, and here's my approach:
1) Loop through the NSObject's properties at runtime & create a key/value object of them
2) Create a subclass of RLMObject at runtime and copy the property list from the passed NSObject model
3) Utilize Realm's initWithValue: to populate the properties
What's your opinion?
It looks like this method that you mention - RLMObject.initWithValue or a static equivalent createInDefaultRealmWithValue has to be called on an RLMObject subclass, or else it throws an exception: "Object type 'RLMObject' is not managed by the Realm".
You need a dynamic schema creation API (what underlies RLMObject), that I don't see being a public API.
An alternative would be to manually encode the object to some dictionary or NSData and attach it to a fixed RLMObject subclass.
You might lose some Realm features by not inheriting RLMObject like knowing when the object becomes dirty, but still probably get some success.
I think you'll get the same problem with Core Data. Normally Core Data supports only NSManagedObject subclasses, and moreover it requires you to define a fixed schema in advance in a model file (represented in code by NSManagedObjectModel).
Of course you could just treat your objects as dictionaries of property names and values, and place them into a giant ("type","id","property","value") table, but it is not the best approach (likely to be slow).
The same strategy is possible to implement with the SQLite backend. Interesting to see which schema would you choose for this.
I'd recommend to look at key-value stores as the backend for this, and avoid SQL. Or treat SQL as a key-value store, as in ("type+id", "encoded_object_data") :)

Programming methods in a non ARC Xcode project

I need to write some methods in a non ARC project in Xcode. I have to implement a NSXMutableDictionary class, a mutable dictionary that can contain up to four key-value pairs. The methods I have to implement are following:
- (void)setObject:(NSObject *)theObject forKey:(NSObject *)theKey;
- (void)removeObjectForKey:(NSObject *)theKey;
I have no clue how to do it, any help would be highly appreciated.
Thanks.
It's not a lot to go on.
But with what you provided, it's best to subclass NSObject and have a private property that is an NSMutableDictionary.
That allows you to implement all of the same methods of NSMutableDictionary just by declaring them, then in your implementation of each you just call the same method on your actual dictionary property.
The difference you add is a check to see if you already have 4 KVPs or not. And any additional methods you need or want.
This is the design pattern of Composition.
I agree with #uchuugaka. Create an object that has an NSMutableDictionary inside it. (This is a "has-a" relationship rather than an "is-a" relationship)
The NSDictionary family is what's known as a "class cluster". A class cluster is a public interface that's actually implemented by a set of private classes that you don't see.
Subclassing a class that is part of a class cluster is tricky, and not for beginners. There are a whole set of primitive methods you have to implement in order to create a subclass of a class cluster. Plus, your custom subclass will likely not preform as well as the original class because you won't adapt to different use-cases like the class cluster does.

How to add a transient NSIndexPath property to NSManagedObject

I mean to add a property of type NSIndexPath to my NSManagedObject but it doesn't seem to be one of the recognized property list types. I also mean to make it transient since index paths change depending on the UI, hence I have no reason to save it in the managed document.
I'm thinking of creating two separate NSNumber properties called section and row instead but it'll be much easier if I had an NSIndexPath instead. Help?
Just make it a transformable attribute with no value transformer name. The default transformer-- NSKeyedUnarchiveFromDataTransformerName-- takes any class that conforms to the NSCoding protocol and saves it as NSData.
Works for me with NSIndexPath, NSArray, and NSDictionary. The accessors just work... I believe by setting and getting an id type, so it's not as typesafe as an NSIndexSet* property would be, but it's good enough.
[edit...]
Err, actually. I use Mogenerator, which may take care of the issue mentioned in the docs:
In principle, you don’t have to do anything else. In practice, to suppress compiler warnings you should declare a property for the attribute...
... it's Mogenerator that makes a property of type id. The Apple example creates a property of the specific type in the entity class.

Creating a Model Object with an NSDictionary

This is something I have been playing with, and have yet to make my mind up about.
When querying a database, it is extremely common that you will use the data in the response to create custom model objects. Let's use 'Book' as an example.
I have received JSON describing multiple Book objects. I parse the JSON into an NSArray of NSDictionarys. I now have a few options:
Make all properties on Book mutable (I hate this option). You could then have a BookManager class with takes an NSArray of NSDictionarys and maps the data in the dictionary to the correct properties.
Add an initialiser to the Book object which accepts the important details.
Example:
- (instancetype)initWithTitle:(NSString *)title author:(NSString *)author publishDate:(NSDate *)publishDate;
The aforementioned BookManager class could then take the NSDictionarys as before, but create the Book objects with this initialiser. This is nice, because you could then make all of the public facing properties on Book readonly. However, it is very limited, and if (as is often the case) there are a lot of properties on the model, this is not feasible.
Add an initialiser to Book which accepts the NSDictionary representation of itself. I dislike this approach in one way because I feel the responsibility is not the model's to create itself from a dictionary. I prefer the idea of a manager class mapping the dictionary to the model. However, I do like the fact that it means that all properties can be readonly.
There is no doubt in my mind I am missing other options, and if you are aware of them, please point them out. The aim of this question is to finally determine the best way to approach this scenario.
I regularly use an init method with the important arguments, but yes, it becomes very unwieldily when the number of arguments reach double digits and/or several of the arguments can be nil. The longest such method I have seen in the iOS SDK is CLLocation's
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate
altitude:(CLLocationDistance)altitude
horizontalAccuracy:(CLLocationAccuracy)hAccuracy
verticalAccuracy:(CLLocationAccuracy)vAccuracy
course:(CLLocationDirection)course
speed:(CLLocationSpeed)speed
timestamp:(NSDate *)timestamp
Regarding your last option, adding an initWithDictionary: method to Book could be expanded to also include a class-level method for creating instances of Book from an NSDictionary.
+ (instancetype)bookWithDictionary:(NSDictionary *)dictionary
And optionally a convenient way to get a dictionary representation from a Book instance.
- (NSDictionary *)dictionaryRepresentation
If you search the iOS documentation for "withDictionary" and "dictionaryRepresentation" you will see a few places where this is used. In other SDKs, you will sometimes see the method named as someObjectFromDictionary:
I think u can do this using JSONModel
see this
http://code.tutsplus.com/tutorials/getting-started-with-jsonmodel--cms-19840
https://github.com/icanzilb/JSONModel

Why isn't there a default implementation of NSCoding?

I understand how to use NSCoding to convert my objects to archive objects. That's not my question.
What I'm wondering is why there isn't a default implementation of NSCoding that could handle probably 99% of cases.
For instance, every time I write a custom class that I want to archive, I perform the following:
Implement -(void)encodeWithCoder: and -(id)initWithCoder:.
Go down my property list, writing a pair of statements (one encode, one decode) for each property.
If the property is an object, I use the encode/decodeObject method.
If the property is a value, I use the corresponding encode/decode method.
I always use the property's name as my key.
I would suspect that almost every implementation of NSCoding is exactly like mine, with the only changes being the particular properties that need to be manipulated.
It seems to me that this would be a perfect place for a standard implementation, with the option to override if your particular case if funky.
Do I have a misunderstanding of what's going on? If not, could I add a category on NSObject to implement this common method on all objects in my projects?
I suspect that the answer to your question is simply that NSCoding was designed long before Objective-C properties existed. (NSCoding was part of the OpenStep spec in 1994, whereas properties arrived with Objective-C 2.0 in 2007.) Additionally, some classes have properties that are not appropriate to be serialized for later.
However, your proposed solution could be a great time-saver! At least one such solution already exists. Check out AutoCoding.

Resources