views:

626

answers:

3

Hello, In my iPhone application I have multiple class files, I have my main application's class files, then I have my UIView class files. I have a simple -(void) method declared in my UIView class files, how can I access it from my main applications class files?

A bit more detail: In my application a video is played, when this video finishes playing a notification is sent and actions are preformed, which I have already successfully set up, however when the movie finishes I would like a method declared in another class file to be preformed. If the method was declared in the same class file I would simply use this code: [self mySimpleVoidMethod]; But obviously this doesn't work If the method is declared in a different class file. I believe it is possible to access a method declared in a different class file, but I just haven't got a clue about how to do it. Sorry if I'm using completely incorrect terms to name things. But I am relatively new to programming all together.

A: 

You'll need an instance of the other class, accessible from the code that runs when the movie finishes. Often, this is accomplished by storing an instance of the other class as a field in the class, set either via a "setter", or during construction. You could also use key-value observing, watching a key representing the playstate of the movie; an instance of the other class can register to observe the changes to this key.

Specifically for patterns using UIView, your UIViewController for the view will have access to it (through the view method). If your "main application's class files" have a pointer to the controller - which they probably will, setup via Interface Builder - then that's an easy way to get to a UIView instance.

Adam Wright
+2  A: 

You've got a couple of options, depending on your setup. Here are a few:

1) Add a reference to the class with the function (the callee) as a property in the caller's class:

Caller.h

@interface Caller : SomeObject {
    Callee *myCallee;
    ...
}
@property(nonatomic, retain) Callee *myCallee;

Caller.m

@synthesize myCallee;
-(void)someAction {
    [myCallee doSomething];
}

Something that sets up Caller after initializing both classes:

caller.myCallee = callee;

2) Use another notification event, like it looks like you already know how to do.

3) Use a protocol if you've got a bunch of different classes that Caller might need to call that all support the same method:

DoesSomething.h

@protocol DoesSomething
    -(void)doSomething;
@end

Callee.h

@interface Callee : NSObject<DoesSomething> {  // NSObject or whatever you're using...
    ...
}
-(void)doSomething;

Caller.h

@interface Caller : SomeObject {
    id<DoesSomething> *myCallee;
    ...
}
@property(nonatomic, retain) id<DoesSomething> *myCallee;

... Then as per example 1.

4) Use performSelector to send a message to the class.

Caller.h

@interface Caller : NSObject {
    SEL action;
    id callee;
}
-(void)setupCallbackFor:(id)target action:(SEL)callback;

Caller.m

-(void)setupCallbackFor:(id)target action:(SEL)callback {
    callee = target;
    action = callback;
}

-(void)someAction {
    if([callee respondsToSelector:action]) {
        [callee performSelector:action];
}

I'm sure there are other ways, and there are pros and cons to each of these, but something in there should fit your needs and/or give you enough to scan the documentation to fill in any gaps...

jasondoucette
Hmm, Im still a bit confused, say if I have a pair of classes, second.h and second.m, and declared in those is a method that, lets say sets an image view's alpha to zero, could you show a specific example of a first set of class files (first.h + first.m) using that method in the other class files. This would help make it clearer for me. Thanks so far anyway.
Jessica
It depends on your scenario, but as you've described the classes then for each of the scenarios above first would be Caller and second would be Callee (sorry for the poor choice of class names - I mean, callee? Really? Yeesh...) Sometimes it helps me to copy and paste into an editor and then search/replace until it makes sense.
jasondoucette
Okay, I can make more sense now of your example. I tried your first suggestion, by Adding a reference to the class with the function as a property in the caller's class, but it's making reference to the class thats not working out for me, Using your code, (but changing "SomeObject" to "UIView") I get an error x2 "expected specifier-qualifier-list before 'Callee'" Which makes me wonder if Callee *myCallee; is the correct way to make reference to a class.
Jessica
Any Ideas on how to get rid of that error?
Jessica
Oh wait, I figured it out what I had done wrong, but any way it still doesn't work, I get the error, unrecognized selector sent to instance.... When trying to use a method by making reference to it's class.
Jessica
+1  A: 

I did a blog post a few weeks ago that outlines one way to do this. It is similar to the previous answers, and includes some sample code you can download and look at. It is based on using table view controllers, but you should be able to adapt the ideas to your application without too much difficulty.

Passing values and messages between views on iPhone

BP