In CoreData, should we always convert an NSSet to NSArray for iteration? - objective-c

So in my Core Data relationships, I have an object with a relationship to other objects that is mapped via an NSSet. When I get my primary object, I will want to iterate over the NSSet. Just iteration, nothing fancy.
Now, according to this article, NSArray is much faster than NSSet. http://www.cocoawithlove.com/2008/08/nsarray-or-nsset-nsdictionary-or.html
My NSSet will never be that big, so I don't think it really matters in this case. However, I just wanted to know in general, is the overhead of converting a NSSet to NSArray for iteration still faster overall?
Thanks!

Converting an NSSet to an NSArray will require iteration over the set, as well as allocating memory for the array so just iterating over the set will be faster unless you're going to iterate over it repeatedly.
But in either case, even with quite a large set, we're likely talking nanoseconds. I really wouldn't worry about it unless you've profiled an actual performance issue and the data tells you its a problem.
Also, the performance figures you've linked only really apply for collections you create yourself. When you get a collection back from a framework, it can (and in the case of core data, will) return you a collection with a custom implementation that has its own performance characteristics.

Related

When to use mutable objects?

There are tons of articles and blog posts over the internet telling that mutable objects are bad and that we shouldn't use them and therefore we shall make all our objects immutable.
I have nothing against this except that the topic has gone so far that some people might be "tricked" into thinking that mutable objects shall never be used at all.
When do we have to resort to use mutable objects? What are the common kinds of problems that are unsolvable without using mutable state?
As to your fear, it's common. Every concept gets taken by some as to mean that nothing else shall ever be done, for any reason.
These are the people who try to make requirements fit their ideology, rather than the other way around (a.k.a. they're not pragmatic).
When to use mutables? Basically when you feel like it, when you think it makes sense.
Prime example is in low memory and high performance situations where creating a new instance that's identical except for one little thing from the old one is too expensive in either memory and/or CPU cycles.

differences between NSArray and CCArray

What are the differences between NSArray and CCArray? Also, in what cases will one be preferred to the other with respect to game programming?
CCArray emulates NSMutableArray. It is a wrapper around a C array (memory buffer). It was developed and is used internally by cocos2d because NSMutableArray was deemed too slow. However the performance improvement is minimal. Any use cases (features) of CCArray that cocos2d itself doesn't use remain a potential source of issues, including weird and hard to debug issues or terrible performance characteristics.
The most important performance critical aspect is reading the array sequential. In my latest tests that's an area where CCArray (no longer?) excels. Specifically fast enumeration: NSMutableArray is around 33 times faster!
CCArray is a perfect example why one should not reinvent the wheel, specifically when it comes to storage classes when there is already a stable, proven, and fast solution available (NSMutableArray). Any speed advantage it may have once had is long gone. What remains is a runtime behavior you will not want to deal with, including some extremely bad performance characteristics (insertion, fast enumeration).
Long story short: do not use CCArray in your own code! Treat CCArray like an internal, private class not to be used in user code (except where unavoidable, ie children array).
NSMutableArray is THE array reference implementation everyone should be using because it's extremely well tested, documented, and stable (both in terms of runtime behavior and speed).
Check it....
http://www.learn-cocos2d.com/2010/09/array-performance-comparison-carray-ccarray-nsarray-nsmutablearray/
Hope this help
Enjoy Programming
CCArray
http://www.cocos2d-x.org/embedded/cocos2d-x/d9/d2e/classcocos2d_1_1_c_c_array.html
In cocos2d-x CCArray is mutable, i.e. you can add elements to it. To create CCArray instance without capacity, you can use CCArray::array() constructor. CCMutableArray is template-based container that can store objects of the same type. CCArray stores objects as CCObject instances, so you have to cast them after getting from CCArray instance
The NSArray class contains a number of methods specifically designed to ease the creation and manipulation of arrays within Objective-C programs.

Worth converting NSMutable<T> to NS<T>

I know the basics of memory management, but not the internals of how iOS handles the different datatypes. Something always nags me that it's best to use an NSData vs NSMutableData or NSString rather than an NSMutableString. Is there really any performance difference unless the code's going to be running in a 10k loop or am I wasting my time?
Use the mutable types where you want to be able to change the contents in place. Use the immutable types otherwise.
In some cases you don't have a choice - such as the data object that holds the returned data from an NSURLRequest: Using a mutable data object is a lot easier than creating a lot of immutable data types and joining them up at the end.
After that, run your code through the profiler and see whether you should do anything differently. i.e. whether the overhead of creating new immutable types to hold objects is more efficient than using a mutable type. Anything else is a premature optimisation.
Like you said its only worth if you call use Mutable many times. But if you call it only a few times this isnt any Problem.
You should think about alternatives, e.g. in a larger TableViews cellForRowAtIndexPath: method. Use [NSString stringWithFormat:#"%#%#", fristString, secondString], Instead of *foo = [[NSMutableString alloc] init] and [foo append:firstString] and so on.

How does one effectively handle temporary objects in Core Data since the objectID changes between temporary objects and permanent objects?

What is the best way to handle temporary objects in Core Data? I've seen solutions where temporary contexts are created, where they are inserted into nil contexts, etc.
However, here's the issue I'm seeing in both of these solutions. I'm using Core Data for my object model and and in some of my views store a NSSet of Core Data objects. The problem I have is when the object is stored, the objectID changes which effectively invalidates anything stored in any NSSet since the isEqual and hash are now different. While I could invalidate the object stored in the NSSet, it often is not practical and certainly not always easy.
Here's the things I've considered:
1) override isEqual method and hash on NSManagedObject (obviously bad)
2) do not place any NSManagedObject in a NSSet (use a NSDictionary where the key is always fixed)
3) use an entirely different type to store in NSSet where I could correctly implement the isEqual and hash code methods
Does anyone have a better solution for this?
ManagedObjects in an NSSet -- that sounds like a Core Data relationship. Why not simply store your temporary managedObjects in a relationship, and have Core Data take care of the problems you're now running into. Then you can concentrate on when and how to delete the temporary objects, or break the relationship or whatever is needed.
However, here's the issue I'm seeing in both of these solutions. I'm using Core Data for my object model and and in some of my views store a NSSet of Core Data objects. The problem I have is when the object is stored, the objectID changes which effectively invalidates anything stored in any NSSet since the isEqual and hash are now different.
tjg184,
Your problem here is not the transition to permanent IDs but that your container class depends upon an immutable hash. Hence, change your container class to an array or dictionary and this problem goes away. (You give up uniquing with an array but that is easy to handle with a trip through a transient set to perform the uniquing.)
Andrew
A possible solution would be to convert the temporary IDs to permanent ones using [NSManagedObjectContext obtainPermanentIDsForObjects:error:].
But be aware that this may be expensive, especially if you have a lot of objects you need to process this way.
You could possibly subclass NSManagedObject and override the willSave and didSave methods to remove and then re-add you objects to your set.
I actually ended up using a different approach, that of using a NIL context and providing a base class to handle insertion into a context. It works really well and is the cleanest solution I have found. Code can be found here... Temporary Core Data

Is there any reason not to return a mutable object where one is not expected?

I have a number of functions similar to the following:
+ (NSArray *)arrayOfSomething
{
NSMutableArray *array = [NSMutableArray array];
// Add objects to the array
return [[array copy] autorelease];
}
My question is about the last line of this method: is it better to return the mutable object and avoid a copy operation, or to return an immutable copy? Are there any good reasons to avoid returning a mutable object where one is not expected?
(I know that it is legal to return a NSMutableArray since it is a subclass of NSArray. My question is whether or not this is a good idea.)
This is a complex topic. I think it's best to refer you to Apple's guidelines on object mutability.
Apple has this to say on the subject of using introspection to determine a returned object's mutability:
To determine whether it can change a received object, the receiver must rely on the formal type of the return value. If it receives, for instance, an array object typed as immutable, it should not attempt to mutate it. It is not an acceptable programming practice to determine if an object is mutable based on its class membership
(my emphasis)
The article goes on to give several very good reasons why you should not use introspection on a returned object to determine if you can mutate it e.g.
You read a property list from a file. When the Foundation framework processes the list it notices that various subsets of the property list are identical, so it creates a set of objects that it shares among all those subsets. Afterwards you look at the created property list objects and decide to mutate one subset. Suddenly, and without being aware of it, you’ve changed the tree in multiple places.
and
You ask NSView for its subviews (subviews method) and it returns an object that is declared to be an NSArray but which could be an NSMutableArray internally. Then you pass that array to some other code that, through introspection, determines it to be mutable and changes it. By changing this array, the code is mutating NSView’s internal data structures.
Given the above, it is perfectly acceptable for you to return the mutable array in your example (provided of course, you never mutate it yourself after having returned it, because then you would be breaking the contract).
Having said that, almost nobody has read that section of the Cocoa Objects Guide, so defensive programming would call for you to make an immutable copy and return that unless performance profiling shows that it is a problem to do that.
Short Answer: Don't do it
Long Answer: It depends. If the array is getting changed while being used by someone who expects it be static, you can cause some baffling errors that would be a pain to track down. It would be better to just do the copy/autorelease like you've done and only come back and revisit the return type of that method if it turns out that there is a significant performance hit.
In response to the comments, I think it's unlikely that returning a mutable array would cause any trouble, but, if it does cause trouble, it could be difficult to track down exactly what the issue is. If making a copy of the mutable array turns out to be a big performance hit, it will be very easy to determine what's causing the problem. You have a choice between two very unlikely issues, one that's easy to solve, one that's very difficult.