I am fairly new to Objective-C and was wondering what the best way to manage collections of tuples was. In C I would use a 2D array or a struct.
Should I be creating objects to contain these tuples? It seems like overkill for just sorting lists or is there no real extra load generated by object initialisation?
There definitely is some overhead in the generation of objects. For a small number of objects, then using ObjC data structures is still appropriate. If you have a large number of tuples, I would manage them in a C array of structs. Remember, Objective-C is really just C. It is appropriate and common to use C constructs in Objective-C (to a point; learning where that point is represents a major milestone in becoming a good Objective-C developer).
Typically for this kind of data structure, I would probably create a single Objective-C object that managed the entire collection. So external callers would see an Objective-C interface, but the internal data would be stored in a more efficient C structure.
If it is common to access a lot of tuples quickly, my collection object would probably provide "get" methods similar to [NSArray getObjects:range:]. ObjC methods that begin with "get" indicate that the first parameter is a pointer that will be overwritten by the method. This is commonly used for high-performance C-like access to things managed by an ObjC object.
This kind of data structure is exactly the way ObjC developers merge the elegance and maintainability of ObjC with the performance and simplicity of C.
I think you'll have to settle for an NSArray of NSArray objects, or maybe an NSArray of NSDictionary objects. You can always roll your own class, or do it the way you would do in C.
There are a couple different ways you could go about this:
CoreData. While it's not technically a database, it can behave a lot like one. If you don't need persistence between app runs, then consider using the NSInMemoryStoreType store type, as opposed to an NSSQLiteStoreType or other option. However, if you're going to want to join tuples together, using CoreData will absolutely not work (this, IMO, is the main reason why CoreData is not a database).
Use a real database. SQLite ships on every Mac and iPhone and is pretty easy to use if you use wrappers like FMDB or SQLite Persistent Objects or PLDatabase or EGODatabase or the GTMSQLite wrapper by Google.
A tuple is really just a collection of key-value pairs, so you could just use an NSMutableArray of NSMutableDictionaries. You obviously won't get to use SQL syntax, and any joins/queries you have to run yourself, but this would definitely have the easiest setup.
Write a tuple class and store those in an NSMutableArray (similar to #3, just enforcing a common set of attributes on your tuples).
Related
I'm reading the book "Programming in Objective C" and he explained not too much on the id type and didn't give much exercise on it, so I'm wondering how often do you use id and if programmers most of the time avoid it? (since he explained some issues with it)
I'm sure it's used, would be great if you can mention some cases it is the only solution..like real life programming cases from some kind of app development.
id is the universal type in Objective C. It can represent a * of any Objective-C type, such as NSString *, NSArray *, etc. The neat thing about Objective-C is that you can send messages to id, and if the object on the other end understands the message, it will get processed as usual without the sender having to know the real type.
It's commonly used when defining anything generic. For example, NSArray is an array of ids; it's up to the programmer to put a specific kind of object in the container (e.g. NSNumber, NSString, etc.). It's used in a lot of other places in Objective-C (such as when defining IBActions for the interface builder, when defining init methods, etc.).
id is the generic object type in Objective-C. It can hold any object.
one real world example: parsing json you wont know, if the root element is a array or a dictionary. But id would take them both.
I use it a lot, but often in conjunction with a protocol definition: id<NetworkPrinterProtocol>. This means that it should be an object of any kind but it does fulfill the NetworkPrinterProtocol. Often used for defining delegates.
see WP: Objective-C — Dynamic Typing
The id is kind of like a catch-all data type. It is used to hold values of any type.
Common uses are for the return type of init... methods. It's used by the collection classes since they can hold any object. See the various getter methods return values and the various methods for adding/setting objects in the mutable version of collection classes.
It's also used in combination with protocols when you need a reference to an object that can be any class but must adhere to a protocol. Examples include many of the delegate properties such as the UITableView delegate.
I have an Objective C++ class, instances of which are required to store an arbitrary set of C++ objects and associate each with a corresponding Objective C object. Looking up the Objective C objects when given the C++ object is killing my performance, so I'm looking for a better solution.
I'm currently storing the pairs in an NSMutableDictionary after creating the keys using [NSValue valueWithPointer:]. The lookup time, in which +valueWithPointer: is about twice as expensive as -objectForKey:, is simply too slow.
The C++ objects are in a third-party framework, and do not provide any unique identifier.
The sets of C++ objects are always smaller than a dozen elements.
What is a faster approach to performing these lookups?
I see three approaches that seem worth trying:
Use NSMapTable
Use objc_setAssociatedObject
Use std::unordered_map or std::map
objc_setAssociatedObject uses std::unordered_map behind the scenes.
I had a similar issue recently with [NSValue valueWithNonRetainedObject:] being too slow.
The solution I went with was to drop down a level and use CoreFoundation's CFMutableDictionary. I would suggest you take a look at it: CFMutableDictionary Reference. It takes regular C pointers in CFDictionaryAddValue(), CFDictionaryRemoveValue, so it's the best thing to use to interface Obj-C and C++ (C is their common denominator).
The reason I'd rather do that than use an std::unordered_map is because I tend to want to minimise C++ in these kind of things. Obj-C++ is a bit of a hack and it's best to just reduce it to glue code between real Obj-C and existing C++ code.
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.
I'm starting to code in objective-c and I've just realized that objects can only be passed by reference.
What if I need an object to use static memory by default and to be copied instead of referenced?
For example, I have an object Color with 3 int components r, g and b. I dont want these objects to be in dynamic memory and referenced when passing to functions, I want them immutable and to be copied like an int or a float.
I know I can use a c struct, but I also need the object Color to have methods that gets/sets lightness, hue, saturation, etc. I want my code to be object oriented.
Is there any solution to this?
EDIT: If for example I'm building a 3d game engine, where I'll have classes like Vector2, Vector3, Matrix, Ray, Color, etc: 1) I need them to be mutable. 2) The size of the objects is roughly the same size of a pointer, so why would I be copying pointers when I can copy the object? It would be simpler, more efficient, and I wouldnt need to manage memory, specially on methods that returns colors. And In the case of a game engine, efficiency is critical.
So, if there is no solution to this... Should I use c-structs and use c-function to work on them? Isn't there a better choice?
Thanks.
You can't do this. This isn't how Objective-C works (at least the Apple/GNU version*). It simply isn't designed for that sort of extreme low-level efficiency. Objects are allocated in dynamic memory and their lifetimes are controlled by methods you call on them, and that's just how it works. If you want more low-level efficiency, you can either use plain C structs or C++. But keep in mind that worrying about this is pointless in 99% of circumstances — the epitome of premature optimization. Objective-C programs are generally very competitive with C++ equivalents both in execution speed and memory use despite this minor inefficiency. I wouldn't go for a more difficult solution until profiling had proved it to be necessary.
Also, when you're new to Objective-C, it's easy to psych yourself out over memory management. In a normal Cocoa (Touch) program, you shouldn't need to bother about it too much. Return autoreleased objects from methods, use setters to assign objects you want to keep around.
*Note: There was an old implementation of Objective-C called the Portable Object Compiler that did have this ability, but it's unrelated to and incompatible with the Objective-C used on Macs and iOS devices. Also, the Apple Objective-C runtime includes special support for Blocks to be allocated on the stack, which is why you must copy them (copy reproduces the block in dynamic memory like a normal object) if you want to store them.
What if I need an object to use static memory by default and to be copied instead of referenced?
You don't.
Seriously. You never need an object to use static memory or be allocated on the stack. C++ allows you to do it, but no other object oriented language I know does.
For example, I have an object Color with 3 int components r, g and b. I dont want these objects to be in dynamic memory and referenced when passing to functions, I want them immutable and to be copied like an int or a float.
Why do you not want the objects to be in static memory? What advantage do you think that gives you?
On the other hand it's easy to make Objective-C objects immutable. Just make the instance variables private and don't provide any methods that can change them once the object is initialised. This is exactly how the built in immutable classes work e.g. NSArray, NSString.
One solution that people use sometimes is to use a singleton object (assuming you only need one of the objects for your entire app's lifetime). In that case, you define a class method on the class and have it return an object that it creates once when it is first requested. So you can do something like:
#implementation MyObject
+ (MyObject *)sharedObjectInstance
{
static MyObject *theObject=nil;
if (theObject==nil)
{
theObject = [[MyObject alloc] init];
}
return theObject;
}
#end
Of course the object itself isn't what's being statically allocated, it's the pointer to the object that's statically allocated, but in any case the object will stick around until the application terminates.
There are times when you want to do this because you really only want one globally shared instance of a particular object. However, if that's not your objective, I'm not sure why you'd want to do what you're describing. You can always use the -copy method to create a copy of an object (assuming the object conforms to the NSCopying protocol) to manipulate without touching the original.
EDIT: Based on your comments above it seems you just want to have immutable objects that you can copy and modify the copies. So using -copy is probably the way to go.
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.