Delegation vs. Message Passing - objective-c

I have a class, call it A that parses some data out in an NSDictionary. That class has a table view, and when a cell is selected, a new class instantiates, let's call that class B. Class B in turn instantiates class C. I want class C to receive the NSDictionary that was created in A.
Would delegates work? Would it work even though class C isn't instantiated? If that's true and it really does not, should I pass the data from A-->B-->C in the init method? Are there better message passing methods in Objective-C?

should I pass the data from A-->B-->C in the init method?
I think that's the best plan.
A really shouldn't have to worry about how B does what it does. The fact that B uses C is none of A's business. All A needs to know is that B needs the dictionary in order to do it's thing.
As it happens, B doesn't care all that much about the dictionary, but the dictionary should be part of B's job description, which is something like: Take the data you're given and display it somehow. If B deals with the dictionary by passing it directly to C, that's fine -- not something A should care about.
You could do the same thing with a delegate. A could give B a reference to itself as a data source, and B could eventually pass that on to C. It's the same process you'd have with the dictionary, so there's no real advantage in doing that if you can put everything that C needs into the dictionary. You might consider switching to delegation if A doesn't know in advance exactly what data is needed, or when you want A to be able to somehow customize the behavior of C.

I would go with passing it through the init. Alternatively depending on what kind of class "A" is. You could make it a singleton, or pass the parsed dictionary to a singleton, and then reference it directly from within "C".

Related

Searching Functions in Objective C

I have a strange task. I need to get an array that contains all the functions in an objective c object. I then need to be able to tell if each function is a class method or not. Then I need to get the names (preferably an NSString) of each parameter and the type each parameter takes. Is there a way to do this? If not, does anyone know how to access the keys and values coded in the NSCoding Protocol function -(void)encodeWithCoder:(NSCoder*)aCoder; without using NSKeyedArchiver? What I am trying to do here is display a list of properties required to initialize an object. All my objects use class methods to initialize themselves. I am making a level editor that allows me to edit properties that differ between objects and I don't feel like writing getPropertyList and initWithProperties functions for every single object since I have already done this by implementing the NSCoding protocol.
I need to get an array that contains all the functions in an objective c object. I then need to be able to tell if each function is a class method or not.
Easy enough: you want class_copyMethodList(), which gets you just the instance methods for that class. To get the class methods, pass the class object, e.g. class_copyMethodList(object_getClass([NSString class]), &count);
Then I need to get the names (preferably an NSString) of each parameter and the type each parameter takes.
The parameter name part is probably not possible. They're not included in the method's metadata, and I'm pretty sure that they don't survive compilation at all; digging them out of the executable if they're there would certainly not be easy.
The types, however, are easily accessible via one of two runtime functions: either method_getTypeEncoding(), which gets you the signature string for the method's return and arguments, or method_getArgumentType(), which will let you loop over the argument types (the returned strings use the same code as the full type string).
If not, does anyone know how to access the keys and values coded in the NSCoding Protocol function -(void)encodeWithCoder:(NSCoder*)aCoder without using NSKeyedArchiver?
Are you talking about the particular implementation that you've made for encodeWithCoder:? You want the list of ivars implied by [coder encodeObject:firstIvar forKey:#"firstIvar"]; [coder encodeObject:secondIvar forKey:#"secondIvar"];? I'm not sure what that has to do with method signatures, but if so, you could make an NSCoder subclass that creates a dictionary from when you pass it as the coder and send encodeWithCoder: to your objects (see this answer I posted the other day).
What I am trying to do here is display a list of properties required to initialize an object.
What about a class method that returns an array with the names of the properties?
+ (NSArray *)essentialPropertyNames {
return [NSArray arrayWithObjects:#"firstIvar", #"secondIvar", nil];
}
That would probably be less effort than picking through the runtime/class metadata and wouldn't be any less odd.
All my objects use class methods to initialize themselves.
That sounds unusual at best. In Cocoa, instances should use some form of -init to do their initialization.

Why do we have NSNumber and NSTemporaryNumber as two different classes?

I went through the source code of GNUStep's NSNumber's implementation to understand how does factory method implementation works there.
From there What I could understand was we have NSNumber with blank implementation for all initWithXYZ kind of methods. and NSTemporaryNumber was acting like an intermediate class in the hierarchy that implemented all the initWithXYZ methods where it actually created objects of specific types , autoreleased itself and returned the created object.
Also allocWithZone was overridden to avoid creation of NSNumber object and to create object of NSTemporaryNumber if it was so otherwise create objects of specific types.
What I didn't understand was, can't the same things be done by NSNumber itself ?
why give blank implementations at all , create the object of specific type and then autorelease self.
Also if we have implementations of createXYZ methods in NSNumber itself, why have initWithXYZ methods ?
If I have to implement a factory implementation for my project where say I have two mediaItems, video , audio and photo etc.
for which I have separate classes and corresponding enums which I pass to initWithMediaType who will create an object of correct child class, return it and destroy itself.
Have two classes like NSNumber and NSTemporaryNumber: say Media and TemporaryMedia, one with blank implementations other with implementations as mentioned above ?
Should I do something like this ?
Is this the way we have to implement Factory pattern in Objective C ?
My question might seem silly biut I come from a Java, C++ background where things looked different.
The purpose might be the same but I am finding it difficult to understand the way Objective C does it since it does not have abstract classes.
Link to the source:
http://www.koders.com/objectivec/fid46956186C20201706AFE1744AA7AFEEE09D1FE5A.aspx
The point is that NSNumber is a class cluster. The class you actually end up with may be an NSIntNumber, an NSFloatNumber or one of several others. They all respond to the same messages as NSNumber (and, usually in this pattern will be subclasses of it, but that isn't required) so it makes no real difference to the caller.
When you call alloc there's no way to know what sort of object to create, so a neutral type is created and returned instead. It substitutes appropriately upon receiving an appropriate init.
So this pattern is for the implementation of class clusters. You can ignore it if writing a class that provides only instances of itself.

Call an Objective-C function non-virtually

Is it possible to force Objective-C to call a specific instance of a virtual method, rather than going through the standard virtual message dispatch? I know this is generally a Bad Idea, but I'd like to know how to do it using the Objective-C runtime.
For example, given class A and B that implement -(void) foo, where B is a subclass of A, I'd like to call the foo method on A with the B instance (even though B would normally handle this message).
I know that I can make this happen by moving the guts of A's foo method to a new method and delegating to it, but I'd like to figure out some way to do this through the Objective-C runtime.
NOTE: For the purposes of this question, assume that I can't change the source of A or B and I've carefully weighed the risks of breaking encapsulation.
This page is a great source for understanding the runtime; a quick memory-assisted scan shows that the section titled "So what happens in objc_msgSend anyway?" is a good place to start for an immediate answer, but the article as a whole will really help you understand what goes on.
Here's an example where he queries the runtime for the appropriate function pointer, then calls the function directly:
//declare C function pointer
int (computeNum *)(id,SEL,int);
//methodForSelector is COCOA & not ObjC Runtime
//gets the same function pointer objc_msgSend gets
computeNum = (int (*)(id,SEL,int))[target methodForSelector:#selector(doComputeWithNum:)];
//execute the C function pointer returned by the runtime
computeNum(obj,#selector(doComputeWithNum:),aNum);
What Matthias said... however:
For example, given class A and B that implement -(void) foo, where B
is a subclass of A, I'd like to call the foo method on A with the B
instance (even though B would normally handle this message).
In other words, you have an implementation of foo on B that you want to avoid by calling a's implementation directly?
Obviously, if you are the implementer of B, then this is trivial; just implement the appropriate logic to determine when it is needed and call [super foo];.
If you are not the implementer of B, then this is beyond a bad idea. It is pretty much guaranteed to lead to mystery crashers and/or misbehavior. Worse, if B is actually a part of a system framework or something that may be updated via a mechanism other than your app being updated, then you have a ticking time bomb that may start crashing your app at any time on any random configuration of the OS.
Specifically:
B's foo may not be self contained; it may do stuff before/after calling A's foo that sets up internal state that may later be required for continued correct operation. You are breaking encapsulation with a sledgehammer.
calling the implementation directly is going to bypass any KVO in play. Unless you happen to grab a derived method implementation, at which point, your behavior is going to explode when that derived method should no longer be in play.

most elegant way to pass data to rootViewController

i've to pass data from the third viewController to the rootViewController in a navigationController.
I think to do in this way:
A = rootViewController and B = lastViewController
In B i insert a method like this:
-(void)load:(A father)f
{
self.father = f; // where father is a retain property
}
then when i alloc B in A, before push it i will call load method.
Will it work?
Other way to this operation? (also global variables and singleton, i don't want these 2 because i've a lot of data in memory).
Thanks for any help.
Some say singletons are evil, but I think they fill a purpose - but in your case I would go with delegation. Thats IMO the best way to handle data between controllers and models.
Long and more appropriate way: Protocol and delegation
your rootViewController B will have to implement a protocol, then in your lastViewController you will have to declare a delegate of that protocol, then call something like lastViewController.myDelegate = myParent;
this is useful if you want to modularize your components, but based on experience, some classes are very specific with its function and creating a protocol just prolongs the process of doing this basic need of transferring data. In this case, I suggest you use #2.
Short Way: What you said
...but I prefer to pass the parent class on the initialization. I.e. initWithParent: [myParent], but that's just me. Also DO NOT retain the parent from a child classes. Only parent class are allowed to retain its child, else you'll have a memory management problem. Disadvantage of this approach is that if your controllers get complicated, it will be very hard to separate their logic later just in case you need to separate them, like re-using one component in another project.

Specifying which object to get the super of

Like the titles says, I want to specify the super of an NSArrayController, something along the lines of self = [super[NSArrayController] function], but have had no luck searching for this. Any ideas? Thanks in advance.
Edited to remove abstract examples as they're confusing people as to the nature of my question.
The purpose of this is to programmatically do what a simple binding of 'add' from an NSArrayController to an NSButton would do in IB. There are several arrayControllers in my application so I want to be able to specify which one I want to obtain the super of by code.
The reason I am looking for the super of an NSArrayController is because I am under the impression that one should address the model rather than the controller (NSArrayController) and my model is a Core Data model that I believe I could get to by using the super of an NSArrayController I specify by name. Perhaps there is a more direct way of adding to the data model.
You're asking a wrong question.
First, let's distinguish a class and an instance of the class. Note that there can be, and indeed often are, multiple instances of the same class.
A class C can be a subclass of another class A. Then A is the superclass of C. Suppose you have an instance c of the class C. Then, in the implementation of the methods of the class C, self stands for the instance of c itself, and super stands for the instance of c as an instance of its superclass A. In a sense, an instance of the class C is also an instance of the class A.
Objects can have other relationships than being super or subclasses. For example, a class C can have in its interface an instance variable B* b; In this case, an instance c of the class C has a pointer to an instance b of the class B. In this case, c is not an instance of the class B.
The relationship between NSArrayController and the managed object context is one of the latter. An instance of NSArrayController contains a pointer to an instance of NSManagedObjectContext (moc).
So what you want to do is not to get the super of your NSArrayController. Instead, you want to get the moc associated to the NSArrayController. Now, how do you get it? To find it out, you open the reference in XCode or on the web at the Apple Developer Connection, see here. Do that right now. Go through the methods. You don't find one giving you the moc.
Then, you go to the top of that page, and follow the superclass of NSArrayController. See this reference of NSObjectController. Now, go through the list of the methods. You find -[NSObjectController managedObjectContext], which does the job!
In conclusion: if you want the moc associated to the NSArrayController, you just need to do
NSManagedObjectContext* moc= [arrayController managedObjectContext];
where arrayController is the instance of the NSArrayController you want to deal with. e.g. If you have multiple instances of NSArrayControllers in the nib, you should have multiple IBOutlets in the app delegate, say, arrayController1, arrayController2, etc. (which are very bad variable names). Then you choose the one you want to deal with.