Passing around sets of data - objective-c

A question that has pondered me for the last while. I am primarily a .net developer who dabbles in Objective-C for iPhone and Mac.
How do you go about sending "datasets" between methods in objective-c. For example in C# you can populate a custom class with data and pass it around in a List of type custom class. EG if you had a customer class you would just do something like:
List<Customer> customers = DataLayer.GetAllCustomers();
The only way I can see how this could be done in obj-c would be to populate an NSArray with custom objects? Is this an efficient way to do things? Any other recommendations? I am using sqlite as the database/data I want to return.

You're on the right track.
Cocoa's collection classes — which all have mutable an immutable variants — are:
NSArray: ordered, can contain an object multiple times
NSDictionary: unordered, mapping from keys to values, keys are copied
NSSet: unordered, can contain an object only once
NSCountedSet: unordered, can contain an object multiple times
The immutable variants help a lot with efficiency. The standard pattern for accessors of classes that have mutable variants is to copy rather than retain. This is codified in the #property mechanism, by using the copy attribute on the property:
// Department.h
#interface Department : NSObject
#property (readwrite, copy) NSSet *employees;
#end
This means that if you pass a mutable array to something that takes an array, it will be copied, and if you pass that to something else, it will be copied again. The trick is though that "copying" an immutable object really just retains it, so you only take a hit for that first copy. You probably want to make a copy that first time anyway so you don't pass a mutable array to something else, then mutate it behind the back of whatever you passed it to.
For Cocoa on Mac OS X, I'd also strongly encourage you to take a look at Core Data. It's an alternative to the "data set" pattern you might be used to from .NET/ADO/etc. With Core Data, you don't "get all customers" and then pass that collection around. Instead you query for the customers you care about, and as you traverse relationships of the objects you've queried for, other objects will be pulled in for you automatically.
Core Data also gets you features like visual modeling of your entities, automatic generation of property getters & setters, fine-grained control over migration from one schema version to another, and so on.

Related

Linked list creation in objective c

Is there a way to create linked list in objective c. I'm a newbie and so far I've researched in apple developer guides, there isn't any function predefined for linked list. Is doubly linked list same as linked list in objective-c?
Please help.
First thing to keep in mind is that Objective-C is C, it's just a lot more, too.
Next thing is that Objects are passed around as (essentially) pointers (which the compiler knows point to objects).
So you can certainly make and manage your own linked list, and you can do it with structs or objects. With objects (perhaps preferred), just create a #property in the class for the "next" object, and use it as you please. Similarly for a doubly-linked list, have a #property for previous.
Perhaps one of the best arguments against caring about liked lists in Objective-C is that usually you have the Cocoa Frameworks at hand, and there is such rich host of features which we used to have to implement ourselves with linked lists. For instance, the conceptually simple NSMutableArray, or NSDictionary are great examples of well-built components which usually spare us the need for linked lists. Going further, Core Data, etc...
A simple abstract linked list class might look like this:
#interface LinkedNode : NSObject
#property (nonatomic, strong) id nextNode;
#end
then you use it as you would expect:
id currentNode = myFirstNode;
do {
[currentNode someMessage];
}
while(currentNode = currentNode.nextNode);
Keep in mind that this is really no "better" than doing it with structs. For the "better" business, move to the Cocoa classes and implement at a "higher level", so-to-speak.
Please check my implementation of some of the common data structures like linked list, stack, binary search tree in objective C.
https://github.com/udaypatial/Data-Structures-in-Objective-C

How to perform an operation before any #synthesize'd accessor?

My model objects are lazy-loaded from an SQLite database. Don't ask why, but the code uses QuickLite to populate the objects, which means that some housekeeping has to be performed before an accessor is used the first time.
I thought, naively, that valueForKey: and setValue:forKey: would be called by the #synthesize'd accessors, so that I could simply overload those 2 methods to fill the object from the db, if necessary. Unfortunately, that doesn't work: the #synthesize'd accessors clearly don't use KVC to get/set their represented value.
My question is therefore: Is there a way to call some code before any #property is accessed, without writing all getters/setters myself?
If your model objects were a subclass of NSManagedObject then your accessors would be using KVC (you declare the properties, then use '#dynamic' rather than '#synthesize' in the .m file to indicate that the accessors will be taken care of by other code).
Basically it sounds like you're re-implementing the faulting behaviour in Core Data.
Based on your comment, the only way I can think of doing this would be to have a sort of proxy object which contains your actual object. So, your proxy object would have a single visible property, which is your actual object, and in the accessor for that, you would then check to see if you'd gone to the database for this particular object, if not, do your housekeeping.
So, your calls would be
NSString *someProperty = proxyObject.realObject.someProperty;
Within proxyObject, the accessor for realObject:
if (beenToTheDatabase)
return realObject;
else
{
// Do your business
beenToTheDatabase = YES;
return realObject;
}
Whether this is more or less effort than manually writing your accessors or migrating to core data, I don't know.

struct or class

I'm developing an iPhone 3.1.3 application.
I have a class, called Object2D, with fields and methods; which represent a shape. Object2D has a field that represents its size, and another field that represent its type.
Now, I need another class called Pattern, which is a set of shapes. In Pattern I'm going to have an array of shapes. From these shapes I only need their size, their type and their location inside pattern, I don't need any method.
I'm wondering it is better to have a new struct that represent a shape instead of using Object2D class.
I ask this because I think on memory performance. I'm not sure, but struct are smaller than classes and maybe it's better to use them instead of classes.
What do you think?
If you're looking at memory use, the difference is truly negligible in almost every situation. Objects are one pointer bigger than an equivalent struct.
The greater difference is in how you can use them. Objects can have methods and hierarchies and interact with the rest of Cocoa. With structs, you need to make custom functions for each struct type or hack together a pseudo-object system. On top of that, arbitrary structs don't interact well with the rest of Cocoa (Touch). For example:
If you store objects in them, you have to be very careful to do your own memory management correctly
You can't store them in NSArrays without creating an object wrapper (since NSArray is an array of objects)
You can't hook structs up in Interface Builder — it doesn't know anything about them
You can't do KVO or KVC with structs
In general, if you're working with a Cocoa-like framework, objects are a good default choice. Use structs once you've decided you really need them.
Objective-C classes are in fact structs, and, provided the instance variables are laid out in the same order as the structure members are, the only difference in size is the 4 or 8 bytes of NSObject's isa variable.
NOTE: the answer above assumes the legacy Objective-C runtime, without the use of #property and #synthesize directives, which could potentially affect their size.

Objective C #property for to-many relationships

I've had various cases where an Objective-C class has a property that needs to be a collection class (NSArray usually). Is there a standard way to implement this? It would be great to be able to just use #synthesize to set this up. I could just declare the property as NSMutableArray and #synthesize that, but that doesn't allow me to enforce what types of objects can be placed into the collection, nor does it prevent the client code from modifying the array. What I typically do is something like this:
#property(nonatomic, readonly) NSArray *widgets;
- (void)addWidget:(Widget*)widget;
- (void)removeWidget:(Widget*)widget;
...
The collection is implemented as an NSMutableArray, with an NSArray containing the current contents passed back to the caller. This seems like a lot of coding for what must be a common scenario. Even more coding needs to be done in order to set up key-value observing.
Am I missing something, or is it really this much to work to set up a collection property?
You can prevent client code from modifying your array by declaring the property as an NSArray, but using an NSMutableArray as the storage mechanism. The #property and #synthesize directives will still work.
There isn't really a good way to ensure type-safety of the objects returned by your array, but Objective-C programmers almost never worry about that. Its just not a common concern. If you really want to ensure that only objects of a certain type go into and come out of your array, you're going to have to write a wrapper class for NSArray to do so.

NSArray property: copy or retain?

According to this: NSString property: copy or retain?
For NSString/NSMutableString, copy is recommended.
How about NSArray/NSMutableArray?
Since you're asking about NSArray (rather than NSMutableArray), you should use copy. NSArray is immutable, so you don't expect a property of that type to change. But NSMutableArray is a subclass of NSArray, so it's perfectly valid for someone to pass in a NSMutableArray. If you just retain that object, then it may change right under your nose. If you copy rather than retain, then the object won't change.
However, you should be aware that when you copy a container like NSArray, you're copying the container only and not its contents. If the array contains mutable objects, the contents of those objects may change even though the array itself is immutable.
choose copy, unless you have a very specific reason not to, as well as all the supporting code/interface to back that up.
i detailed the rationale and several implications here:
NSMutableString as retain/copy
that example is based on NSStrings, but the same applies for NSArrays.
If it is a problem when the underlying data changes, use copy. In fact, this is what you want most of the time, as changing data behind someone's back is a good source for bugs.
Note that copy will essentially just be a retain for an NSArray. Only when you throw an NSMutableArray in, there is more work involved.
From the link you included, it pretty much comes down to this: NSString property: copy or retain?
If you want to make sure the value of the object won't change during execution, you use the copy attribute, otherwise retain will be fine. Generally, retain will be ok for NSMutableArrays and NSArrays (as well as many other objects) as you are (usually) more interested in the object then in the value it contains. In case of an NSString you are always interested in the value, so you copy it to make sure it won't change.
#jlehr:
It depends if the developer is interested in the actual value or not. Whenever interested in the actual value, use copy (since you don't want the value to change during execution), otherwise retain is fine. From Apple's docs:
It is common practice in Objective-C code to copy value objects—objects that represent attributes. C-type variables can usually be substituted for value objects, but value objects have the advantage of encapsulating convenient utilities for common manipulations. For example, NSString objects are used instead of character pointers because they encapsulate encoding and storage.
Also from Apple's docs, on the topic of value objects:
A value object is in essence an object-oriented wrapper for a simple data element such as a string, number, or date. The common value classes in Cocoa are NSString, NSDate, and NSNumber. Value objects are often attributes of other custom objects you create.