Defining delegate function in separate file (instead of in ViewController) - iphone

I have a ViewController, and a UIView.
The UIView has a delegate, and the delegate function is set in the ViewController.
All I want to do, is have the delegate function defined in a separate file. So the UIView.m #imports the separate file, instead of all the ViewControllers which use the UIView.
I believe this is a standard procedure, but keep falling over myself trying to get it to work. :| Would really appreciate some help. Thanks.
myViewController.h
#import <UIKit/UIKit.h>
#import "myUIView.h"
#protocol ModalViewDelegate
-(void)didReceiveMessage:(NSString *)message;
#end
#interface myViewController : UIViewController <ModalViewDelegate>
#property (nonatomic, strong) myUIView *myUIViewItem;
#end
myViewController.m
#import "myViewController.h"
#import "myUIView.h"
#interface myViewController ()
#end
#implementation myViewController
#synthesize myUIViewItem;
- (void)didReceiveMessage:(NSString *)message { //<<< THIS IS WHAT
NSLog(#"Message from button: %#", message); //<<< NEEDS MOVING
}
- (void)viewDidLoad
{
…
myUIViewItem.delegate = self;
…
myUIView.h
#import <UIKit/UIKit.h>
#protocol ModalViewDelegate;
#interface myUIView : UIView {
id<ModalViewDelegate> delegate;
}
#property (nonatomic, strong) id<ModalViewDelegate> delegate;
myUIView.m
#import "myUIView.h"
#import "myViewController.h"
#implementation myUIView
#synthesize delegate;
...
[delegate didReceiveMessage:#"Data from UIView!"];

well, there is one method actually,
Just take one .h file and lets say connectionDelegate.h and declare your protocol init
In connectionDelegate.h:
#import <UIKit/UIKit.h>
#protocol ConnectionDelegate
-(void)getResult:(NSString*)_result;
#end
Then in your view controller:
#import "ConnectionDelegate.h"
#interface myViewController : UIViewController <ConnectionDelegate>
{
id delegate;
}
then in .m file, by just call the method
[delegate getResult:_result];
Edit regarding the warnings:
You need to declare the method in view controller, you need to do like this.
[self getResult:urlDataString];
-(void)getResult:(NSString*)_result{
[delegate getResult:_result];
}

Based on your comment:
I want to have the function 'didReceiveMessage' defined in a SEPARATE
file. So that I don't have to repeat it in every ViewController that
uses the UIView and delegate. e.g. ModalViewDelegate_Action.h and
ModalViewDelegate_Action.m
The way I was given was to use a subclass, and that's been working great for me. In my iOS projects I have a class called BaseViewController, which is a subclass of UIViewController. I put lots of code in it related to HUD management, NSOperations management, etc. Then virtually all my view controllers are subclasses of it.

Related

It's possible create a custom delegate in AppDelegate?

i want know if it's possible create a custom delegate in the AppDelegate class, like in this way for instance:
#protocol AppDelegateDelegate <NSObject>
- (void)finishSync:(BOOL)success;
#end
#interface AppDelegate : UIResponder <UIApplicationDelegate> {
#property (nonatomic, weak) id <AppDelegateDelegate> delegate;
#end
it's possible create something like this? to notify the classes that are registered for this delegate?
EDIT
How i can use the Delegate? for example if i do this:
#import "AppDelegate.h"
#interface MasterViewController : UIViewController <AppDelegateDelegate>
#end
.m
#implementation MasterViewController
...
- (void)viewDidLoad {
AppDelegate *appController = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appController.customDelegate = self;
}
in i stay only in that view works, but for example if i switch in SecondViewController that have the same code to implement the delegate, the delegate don't works anymore neither in the MasterViewController...what i wrong?
Yes, That is fine. You can create delegates anywhere you want and use it anywhere by importing that class. There are no restrictions.

Getting the delegate to work between two view controllers

I am a newbie to iPhone development and have some basic questions to ask about protocols and delegates. I have two view controllers: view controller and viewcontroller2nd. I have UITextField in one of them and would like to type something (like a name) in it and in the viewcontroller2nd, I have a UILabel and i would like it to appear Hello, name when the UITextField is changed.
I am following this video: http://www.youtube.com/watch?v=odk-rr_mzUo to get the basic delegate to work in a single view controller.
I am using protocols to implement this:
SampleDelegate.h
#import <Foundation/Foundation.h>
#protocol ProcessDelegate <UITextFieldDelegate>
#optional
- (BOOL)textFieldShouldReturn:(UITextField *)textField;
#end
#interface SampleDelegate : NSObject
{
id <ProcessDelegate> delegate;
}
#property (retain) id delegate;
#end
SampleDelegate.m
#import "SampleDelegate.h"
#implementation SampleDelegate
#synthesize delegate;
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
lbl.text = [NSString stringWithFormat:#"Hello, %#",txtField.text];
[txtField resignFirstResponder];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#import "SampleDelegate.h"
#interface ViewController : UIViewController <ProcessDelegate>
{
IBOutlet UITextField *txtField;
}
#end
Viewcontroller.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
ViewController2nd.h
#import <UIKit/UIKit.h>
#interface ViewController2nd : UIViewController <ProcessDelegate> {
IBOutlet UILabel *lbl;
}
#end
and ViewController2nd.m is standard code from Xcode.
My question is how do i link my delegate function to my viewcontroller and viewcontroller2nd to get it working?
Pardon me if the question is stupid.. Need some guidance. Do point me any other mistakes that i am doing as well.. Thanks..
Your delegation is a bit... Off.
Firstly: Don't override UIKit delegate methods through protocol inheritance. It's pointless. Why not just make your class conform to the specified delegate in the first place?
#protocol ProcessDelegate //No more protocol inheritance!
//...
#end
Secondly: When an object has defined a protocol, a valid instance of that object must be in use by its delegate (or at least passed to it). So, anything that wants to be the delegate of SampleDelegate (really a bad name for a class, by the way) would initialize a valid SampleDelegate object, and call -setDelegate: as though it were any other property.
//#import "SampleDelegate"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//make this a property, so it isn't crushed when the function exits.
SampleDelegate *myDelegateObject = [[SampleDelegate alloc]init];
[myDelegateObject setDelegate:self]; //conform to the delegate
}
Thirdly: You don't actually define any delegate methods! What's the point of delegation if there's nothing to delegate!l
#protocol ProcessDelegate
-(void)someMethod;
#end
Fourth, and most important: Never, ever, ever, ever use the retain, or strong storage specifiers with a delegate! Delegate objects are supposed to be weak or assign to prevent nasty retain cycles.
#property (assign, nomatomic) id delegate;

How to call ViewController's method to show 2nd View?

//
// MyGameViewController.h
//
#import < UIKit/UIKit.h >
#import "SecondViewController.h"
#interface MyGameViewController : UIViewController {
IBOutlet SecondViewController *secondViewController;
}
-(IBAction)goToSecondView;
#end
//
// MyGameViewController.m
//
#import "MyGameViewController.h"
#implementation MyGameViewController
-(IBAction)goToSecondView{
[self presentModalViewController:secondViewController animated:YES];
}
//
// MyGameView.h
//
#import < UIKit/UIKit.h >
#import "Sprite.h"
#interface MyGameView : UIView {…}
Currently I have implemented a button on the MyGameView.xib to invoke the secondViewController view and it works. But I want the secondViewController get invoked by programming inside MyGameView.m when there is interruption, not by pressing a button. Therefore, I think there are 2 approaches:
a) Either make the goToSecondView method available to MyGameView.m
b) Implement all the code in MyGameViewController.h and MyGameViewController.m to MyGameView.m.
Issues:
1) When tried to make a) happen, I have to make goToSecondView method starting with (void), not (IBAction). But then how to invoke it in MyGameView.m?
2) I tried to do b) and implemented all code to MyGameView.m. But presentModalViewController is a method of ViewController and does not work in UIView. So what is the solution?
As you stated, you can't call presentModalViewController in a UIView class. This seems like a great opportunity to use a delegate. You could do something along the lines of:
In MyGameView.h
#protocol MyGameViewDelegate
- (void)showSecondView;
#end
#interface MyGameView {
}
#property (nonatomic, assign) id <MyGameViewDelegate> delegate;
...
#end
In MyGameView.m, when you need to show the second view:
[self.delegate showSecondView];
In MyGameViewController.h:
#import "MyGameView.h"
#interface MyGameViewController : UIViewController <MyGameViewDelegate> {
...
In MyGameViewController.m:
#pragma mark MyGameViewDelegate methods
- (void)showSecondView {
[self goToSecondView];
}
Note that you'll also need to set MyGameViewController to be the delegate of MyGameView. You could do that in Interface Builder, or in code, depending on where you create the two objects.
To do it in code, for example in the MyGameViewController.h viewDidLoad method:
myGameView.delegate = self;

Properly declare delegation in Objective C (iPhone)

Ok, This has been explained a few times (I got most of the way there using this post on SO), but I am missing something. I am able to compile cleanly, and able to set the delegate as well as call methods from the delegate, but I'm getting a warning on build:
No definition of protocol 'DetailViewControllerDelegate' is found
I have a DetailViewController and a RootViewController only. I am calling a method in RootViewController from DetailViewController. I have the delegate set up as so:
In RootViewController.h:
#import "DetailViewController.h"
#interface RootViewController : UITableViewController <NSFetchedResultsControllerDelegate, DetailViewControllerDelegate> //Error shows up here
{
//Some Stuff Here
}
//Some other stuff here
#end
In RootViewController.m I define the delegate when I create the view using detailViewController.delegate = self
In DetailViewController.h:
#protocol DetailViewControllerDelegate;
#import "RootViewController.h"
#interface DetailViewController : UITableViewController <UITextFieldDelegate>
{
id <DetailViewControllerDelegate> delegate;
}
#property (nonatomic, assign) id <DetailViewControllerDelegate> delegate;
#end
#protocol DetailViewControllerDelegate
//some methods that reside in RootViewController.m
#end
I feel weird about declaring the protocol above the import in DetailViewController.h, but if I don't it doesn't build. Like I said, the methods are called fine, and there are no other errors going on. What am I missing here?
pheelicks is pretty much there but it looks like some of your protocol methods also use the DetailViewController class, I imagine it looks something like this :
#protocol DetailViewControllerDelegate <NSObject>
- (void) controller:(DetailViewController *)controller hasSomething:(id)thing;
#end
#class DetailViewController : UITableViewController <UITextFieldDelegate> {
id <DetailViewControllerDelegate> delegate;
}
#property (nonatomic, assign) id <DetailViewControllerDelegate> delegate;
#end
and you haven't defined DetailViewController yet so you will get an error in the protocol definition.
You can fix this in two ways :
a) Declare (but don't define yet) the class before the protocol
#class DetailViewController;
#protocol DetailViewControllerDelegate <NSObject>
- (void) controller:(DetailViewController *)controller hasSomething:(id)thing;
#end
b) Just use UITableViewController instead of DetailViewController in your protocol methods.
#protocol DetailViewControllerDelegate <NSObject>
- (void) controller:(UITableViewController *)controller hasSomething:(id)thing;
#end
Personally, I choose solution (a) but it really depends on what you're trying to do.
Hope that helps.
Try:
In DetailViewController.h:
#import "RootViewController.h"
#protocol DetailViewControllerDelegate <NSObject>
//some methods that reside in RootViewController.m
#end
#interface DetailViewController : UITableViewController <UITextFieldDelegate>
{
id <DetailViewControllerDelegate> delegate;
}
#property (nonatomic, assign) id <DetailViewControllerDelegate> delegate;
#end
Here is another way that you could tackle this, similar to the solution proposed by deanWombourne.
#protocol DetailViewControllerDelegate;
#interface DetailViewController : UITableViewController <UITextFieldDelegate> {
id <DetailViewControllerDelegate> delegate;
}
#property (nonatomic, assign) id <DetailViewControllerDelegate> delegate;
#end
#protocol DetailViewControllerDelegate <NSObject>
- (void) controller:(DetailViewController *)controller hasSomething:(id)thing;
#end

Syntax for creating View delegate in Objective-C

I am trying to create a delegate protocol for a custom UIView. Here is my first attempt:
#protocol FunViewDelegate
#optional
- (void) funViewDidInitialize:(FunView *)funView;
#end
#interface FunView : UIView {
#private
}
#property(nonatomic, assign) id<FunViewDelegate> delegate;
#end
This doesn't work because the FunView interface has not been declared at the time of the FunViewDelegate declaration. I have tried adding a prototype ala C++ before the #protocol:
#interface FunView;
But this just drives the compiler nuts. How am I supposed to do this?
Forward class syntax is #class Foo;, not #interface Foo;.
It would seem that you can forward declare protocols:
#protocol FunViewDelegate;
#interface FunView : UIView {
#private
id<FunViewDelegate> delegate;
}
#property(nonatomic, assign) id<FunViewDelegate> delegate;
#end
#protocol FunViewDelegate
#optional
- (void) funViewDidInitialize:(FunView *)funView;
#end