Reputation: 1189
I am developing and iOS app for iPad. I have an UIView subclass and I'd like to call a method of the ViewController from that subclass. I've tried to code a delegate but it doesn't work. Is that a good solution or I have to do it another way?
Upvotes: 1
Views: 3780
Reputation: 5175
Try block, here is the sample:
MyView.h
@interface MyView: UIView
...
@property (nonatomic, copy) void(^myEventCallBack)(id someData);
...
@end
MyView.m (How to call block sample)
...
- (IBAction)buttonTapped:(UIButton *)sender {
if (self.myEventCallback) {
self.myEventCallback(self.someImportantData);
}
}
...
in your UIViewController:
self.myView = [[MyView alloc] initWithFrame:someFrame];
// THIS IS VERY IMPORTANT, USE __weak COPY OF YOUR UIViewController OBJECT (owner of object which contains block) INSIDE BLOCK TO PREVENT RETAIN CIRCLE, CAUSE BLOCK RETAINS ITS CONTENT
__weak MyViewController *self_ = self;
self.myView.myEventCallback = ^(id someData){
[self_ doSomeProcessingWithData:someData];
};
also block can be used with return value, sample:
@property (nonatomic, copy) BOOL(^shouldStartProcessing)(void);
self.myView.myEventCallback = ^BOOL{
return (self_.state == MyViewControllerStateReady);
};
Upvotes: 3
Reputation: 536047
In general the problem of communication between conceptually "distant" objects is tricky one, but it is the heart of Cocoa programming. Getting a reference from one instance to another is crucial! I discuss the problem in general here:
http://www.apeth.com/iOSBook/ch13.html#_instance_visibility
Here's one possibility. If this UIView instance is in the interface, then either its nextResponder
is the view controller or it is the subview of a superview whose nextResponder
is the view controller. Moreover, the view hierarchy parallels the responder chain. So simply walk up the responder chain until you come to the view controller.
UIResponder* r = someView; // the view instance, living in the interface
while (![r isKindOfClass:[UIViewController class]])
r = [r nextResponder];
Now r
is the view controller. Now cast to what you know is the actual view controller's class, and you will be able to call methods on it:
MyViewController* vc = (MyViewController*)r;
Here's my book's summary of the responder chain:
http://www.apeth.com/iOSBook/ch11.html#_the_responder_chain
However, there are many other possibilities. As someone has already suggested, you could set up lines of communication by means of NSNotification (shoutcasting); it's ugly, but it does work, and it's intended in part to cover just this sort of tricky situation.
Upvotes: 1