Following is my code, there is no error but selector is not responding.
Code in ExampleTableviewSubProductDetail.h
#protocol EnterAmountDelegate <NSObject>
-(void)titlechange:(NSInteger)amount;
#end
#class ASIFormDataRequest;
#interface ExampleTableviewSubProductDetail : UIViewController<UIScrollViewDelegate>
{
}
#property (nonatomic, strong) id <EnterAmountDelegate>delegate;
Code in ExampleTableviewSubProductDetail.m
#implementation ExampleTableviewSubProductDetail
#synthesize delegate;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if([delegate respondsToSelector:#selector(titlechange:)])
{
//send the delegate function with the amount entered by the user
[delegate titlechange:20];
}
code in HostProductdetailViewController.h
#import "ViewPagerController.h"
#import "ExampleTableviewSubProductDetail.h"
#interface HostProductdetailViewController : ViewPagerController <ViewPagerDataSource, ViewPagerDelegate, EnterAmountDelegate>
{
}
code in HostProductdetailViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.dataSource = self;
self.delegate = self;
}
-(void)titlechange:(NSInteger)amount
{
NSLog(#"sdfsf");
}
In the viewwillapper following Line always return false
if([delegate respondsToSelector:#selector(titlechange:)])
Please let me know if i am missing anything.
Thanks
When pushing from HostProductdetailViewController to ExampleTableviewSubProductDetail you need to set the exampleTableviewSubProductDetail.delegate = self
As I see some other potentially dangerous things in your code try checking this example. It consists of 2 simple classes which are connected via delegate. Watch out for strong references on delegates as this code of yours will produce a retain cycle and cause a memory leak.
Protocol:
// defining a custom protocol
#protocol PingProtocol <NSObject>
- (void)didPing;
#end
Ping class:
//
// This class will be able to send notifications via delegate for the protocol PingProtocol
// Any object that implements PingProtocol will be able to assign itself to the delegate property and will be notified to all protocol methods
//
#interface PingClass : NSObject
// The listener object that implements PingProtocol
// Note this should be weak or there will a retain cycle
#property (nonatomic, weak) id<PingProtocol> delegate;
#end
#implementation PingClass
// Some event that happens will check if the delegate actually implements this method and call it.
// The respondsToSelector is not necessary in this case since the method is not optional though.
- (void)onEvent:(id)sender
{
if([self.delegate respondsToSelector:#selector(didPing)])
{
[self.delegate didPing];
}
}
// Will create a timer which will call onEvent: every second.
// Note there should be some way to invalidate the timer as this will cause a memory leak for the PingClass
- (void)startPing
{
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(onEvent:) userInfo:nil repeats:YES];
}
#end
Listener:
//
// This class will listen to PingProtocol methods.
// It will need to implement all non-optional methods defined by PingProtocol
//
#interface ListenerClass : NSObject<PingProtocol>
#property (nonatomic, strong) PingClass *someClass;
#end
#implementation ListenerClass
// will create a PingClass object and asign itself as a delegate to start listening to delegate methods
- (void)startListening
{
self.someClass = [[PingClass alloc] init];
self.someClass.delegate = self;
[self.someClass startPing];
}
// A protocol method
- (void)didPing
{
NSLog(#"Ping");
}
#end
Most likely you are missing self:
if([self.delegate respondsToSelector:#selector(titlechange:)])
You need to watch out for these things. The delegate in your case is closer to a function pointer then an actual object. You might also be able access it via _delegate as well.
Related
I've been following this example to help me build a delegate but unfortunately I've missed something so it is not working for me. How do I set up a simple delegate to communicate between two view controllers?
My code looks like this:
// HintsViewController.h
#import <UIKit/UIKit.h>
#protocol HintDelegateProtocol;
#interface HintsViewController : UIViewController
#property (weak, nonatomic) id<HintDelegateProtocol> hintDelegate;
-(IBAction)showFirstLetter:(id)sender
-(IBAction)showHint:(id)sender;
-(IBAction)showAnswer:(id)sender;
#end
#protocol HintDelegateProtocol <NSObject>
-(void)HintsViewController:(HintsViewController*)hintsViewController
showFirstLetter:(NSString*)firstLetter;
-(void)HintsViewController:(HintsViewController*)hintsViewController
showHint:(NSString*)hint;
-(void)HintsViewController:(HintsViewController*)hintsViewController
showAnswer:(NSString*)answer;
#end
//
// HintsViewController.m
#import "HintsViewController.h"
#implementation HintsViewController
#pragma mark -
#pragma mark IBActions
/* As per a suggestion below I changed the code here /*
- (IBAction)showHint:(id)sender
{
[self.hintDelegate HintsViewController:self showHint:#"Hint"];
}
- (IBAction)showFirstLetter:(id)sender
{
[self.hintDelegate HintsViewController:self showFirstLetter:#"FirstLetter"];
}
- (IBAction)showAnswer:(id)sender
{
[self.hintDelegate HintsViewController:self showAnswer:#"Answer"];
}
#end
And then in the a Controller class I have the following:
//
// GameLogicController.h
#import "HintsViewController.h"
#interface GameLogicController : NSObject < HintDelegateProtocol>
#end
And in the implementation I have the following:
// GameLogicController.m
-(void) nextRiddle
{
HintsViewController *hintsViewController = [[HintsViewController alloc] init];
hintsViewController.hintDelegate = self;
}
#pragma mark -
#pragma mark HintsFunctionality
-(void)HintsViewController:(HintsViewController*)hintsViewController
showFirstLetter:(NSString*)firstLetter
{
NSLog(#"Show First Letter called");
}
-(void)HintsViewController:(HintsViewController*)hintsViewController
showHint:(NSString*)hint
{
NSLog(#"show Hint called");
}
-(void)HintsViewController:(HintsViewController*)hintsViewController
showAnswer:(NSString*)answer
{
NSLog(#"Show answer called");
}
Using breakpoints I can see that the IBActions in the HintsViewController are being called, but putting a breakpoint in any of the delegate methods in the gameLogicController are never hit. So I have missed an important step in setting up the connection between the GameLogicController and the HintsViewController. Can anyone help me spot it?
Say you have two files: one is your ViewController, and other is your ConnectionManager Class.
Declare protocol and its methods in your ConnectionManager class, and define your protocol methods in the ViewController class. By setting the delegate of your ConnectionManager class in ViewController Class, you can call your Protocol method.
#protocol ConnManagerDelegate<NSObject>
- (void)didReceiveData:(NSDictionary *)data;
- (void)didFailWithError:(NSError*)error;
#end
#interface ConnectionManager : NSObject<NSURLConnectionDelegate>
#property(nonatomic,assign)id< ConnManagerDelegate > delegate;
And elseswhere in the same file .m, when your response comes just call
[Self.delegate didReceiveData:mDict];
In the ViewController file after you alloc init ConnectionManager class, set its delegate to self and define the protocol methods. It is these methods you will have your response from ConnectionManager class.
This is all Protocol Delegation pattern
I have two Classes - say Class1 and Class2
Class1 has button which when pressed does a push segue to Class2.
Also, when the button is pressed a network call is being done on another class.
Class1 code :
- (IBAction)sellPressed:(id)sender
{
SPNNetworkEngine *networkEngine = [[SPNNetworkEngine alloc] init];
networkEngine.delegate = self;
[networkEngine getFarePrice];
}
In Network class, I have :
In .h file
#protocol SPNNetworkEngineDelegate <NSObject>
- (void) farePriceReceivedWithDetails:(id) farePrice;
#end
#property (nonatomic, weak) id delegate;
- (void) getFarePrice;
In .m file
- (void) getFarePrice
{
...........
.......
//After all the operations, I delegate
if ([delegate respondsToSelector:#selector(farePriceReceivedWithDetails:)])
[delegate farePriceReceivedWithDetails:cost];
}
}
And in Class2 I have,
- (void)viewDidLoad
{
[super viewDidLoad];
SPNNetworkEngine *networkEngine = [[SPNNetworkEngine alloc] init];
networkEngine.delegate = self;
}
// Delegate method
- (void) farePriceReceivedWithDetails:(id)farePrice
{
NSLog(#"FarePrice %#", farePrice);
}
The delegate method in Class2 is never called. What have I done wrong here?
But when I write the delegate method -(void)farePriceReceivedWithDetails:(id)farePrice in Class1, its working fine.
Your Coding approch is wrong You alloc SPNNetworkEngine class in Your Class1 and set delegate of SPNNetworkEngine is self. so The delegate is fire in class1. But you want this method in class2 so you have to assign this delegate with class2 object.
Second point is you have to Change this line with this
#protocol SPNNetworkEngineDelegate <NSObject>
- (void) farePriceReceivedWithDetails:(id) farePrice;
#end
#property (nonatomic, strong) id <SPNNetworkEngineDelegate> delegate;
- (void) getFarePrice;
You should retain this object in Class1.h as instance variable. So that it will be alive till that class object exist. What you are doing currently is simply allocating it in a method. once the method executed & finished, it will be deallocated. So your delegate call back will not work.
So avoid this line
SPNNetworkEngine *networkEngine = [[SPNNetworkEngine alloc] init];
change the above code to like below
Declare in Class1
#property (nonatomic, strong) SPNNetworkEngine *networkEngine;
Then do
self.networkEngine = [[SPNNetworkEngine alloc] init];
In the Class1 you are calling to [networkEngine getTestPrice] and I think that mean the [networkEngine getFarePrice] function (because is where you call the delegate)
In Class2 you must call the same function: [networkEngine getTestPrice]
Have you added the SPNNetworkEngineDelegate to the list of delegates in the Class2.h?
i.e.
#interface Class2 : UIViewController <SPNNetworkEngineDelegate>
I have a protocol in one class:
#protocol DataStorageManager
- (void) saveFile;
#end
#interface DataManager : NSObject
{
id <DataStorageManager> delegate;
}
#property (nonatomic, assign) id<DataStorageManager> delegate;
//methods
#end
and its implementation:
#implementation DataManager
#synthesize delegate;
#end
and I have another class which is the adapter between the first and the third one:
#import "DataManager.h"
#import "DataPlistManager.h"
#interface DataAdapter : NSObject <DataStorageManager>
#property (nonatomic,strong) DataPlistManager *plistManager;
- (void) saveFile;
#end
and its implementation
#import "DataAdapter.h"
#implementation DataAdapter
-(id) initWithDataPlistManager:(DataPlistManager *) manager
{
self = [super init];
self.plistManager = manager;
return self;
}
- (void) saveFile
{
[self.plistManager savePlist];
}
#end
So when I in first method try to call my delegate method like this
[delegate saveFile];
Nothing happened. I don't understand what's wrong with the realization - it's a simple adapter pattern realization. So I need to use the delegate which will call the methods from the third class. Any help?
You are not setting the delegate property. You need to do this,
-(id) initWithDataPlistManager:(DataPlistManager *) manager
{
self = [super init];
self.plistManager = manager;
self.plistManager.delegate = self;
return self;
}
Also, in DataManager class remove the ivar declaration, just declaring property is sufficient, the ivar gets automatically created. Call the delegate method as below,
if([self.delegate respondsToSelector:#selector(saveFile)] {
[self.delegate saveFile];
}
Hope that helps!
In your case you forget to set your protocol delegate and also need to call protocol method
by self.delegate....
I just Give Basic Idea for how to Create Protocol
Also Read This Question
#DetailViewController.h
#import <UIKit/UIKit.h>
#protocol MasterDelegate <NSObject>
-(void) getButtonTitile:(NSString *)btnTitle;
#end
#interface DetailViewController : MasterViewController
#property (nonatomic, assign) id<MasterDelegate> customDelegate;
#DetailViewController.m
if([self.customDelegate respondsToSelector:#selector(getButtonTitile:)])
{
[self.customDelegate getButtonTitile:button.currentTitle];
}
#MasterViewController.m
create obj of DetailViewController
DetailViewController *obj = [[DetailViewController alloc] init];
obj.customDelegate = self;
[self.navigationController pushViewController:reportTypeVC animated:YES];
and add delegate method in MasterViewController.m for get button title.
#pragma mark -
#pragma mark - Custom Delegate Method
-(void) getButtonTitile:(NSString *)btnTitle;
{
NSLog(#"%#", btnTitle);
}
can't understand what's wrong in this case, so I cant use the delegate - there is an exception in self.plistManager.delegate = self; Property 'delegate' not found on object of type 'DataPlistManager *'
#import "DataManager.h"
#import "DataPlistManager.h"
#interface DataAdapter : NSObject <DataStorageManager>
#property (nonatomic,strong) DataPlistManager *plistManager;
- (void) saveFile;
#end
and its implementation
#import "DataAdapter.h"
#implementation DataAdapter
-(id) initWithDataPlistManager:(DataPlistManager *) manager
{
self = [super init];
self.plistManager = manager;
self.plistManager.delegate = self;
return self;
}
- (void) saveFile
{
[self.plistManager savePlist];
}
#end
Your DataPlistManager needs a property delegate:
#property (weak) id<DataStorageManager> delegate;
If you add #import "DataAdapter.h" in your "DataPlistManager.h" file then remove it and add it to "DataPlistManager.m" file, I don't know but some days ago i have same issue, and i solved it by using this trick :)
DataManager class contains delegate property so you should set your object as delegate of DataManager class and call method (send message) saveFile inside delegate class:
#implementation DataAdapter
- (void)someMethod) {
DataManager *dataManagerObject = [[DataManager alloc] init];
dataManagerObject.delegate = self;
}
#implementation DataManager
- (void)someDelegateMethod {
[self.delegate saveFile];
}
Are you sure you understand concept of delegation pattern?
https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/DelegatesandDataSources/DelegatesandDataSources.html
I'm working with a custom delegate and protocol functionality.
I implemented my class like follows:
#protocol MyDelegate <NSObject>
#required
- (void)update;
#end
#interface MyHandlerClass : NSObject
{
id <MyDelegate>delegate;
}
#property (nonatomic, weak) id <MyDelegate>delegate;
#end
My implementation class looks like:
#implementation MyHandlerClass
#synthesize delegate = _delegate;
- (void)updateRequired: (id)sender
{
if(delegate)
{
[delegate update];
}
}
#end
And from another class I'm setting it like:
[sharedManager setDelegate:self];
But when the updateRequired is triggered it is showing as nil.
Then I added a setter method like:
- (void)setDelegate:(id<MyDelegate>)aDelegate
{
delegate = aDelegate;
}
Everything works fine !!!
Then I changed the updateRequired method (without custom setter) like:
- (void)updateRequired: (id)sender
{
if(_delegate)
{
[_delegate update];
}
}
It is also working fine !!!
I couldn't find why it is not worked for the first case and why it is worked for the other two cases ?
Please help me to find the issue, Thanks in advance
When you use
if(delegate)
You are pointing to the instance variable "delegate".
However, when you use
[sharedManager setDelegate:self]
This is setting the instance variable "_delegate" to "self".
Try this:
if (self.delegate) {
[self.delegate update];
}
You have inadvertently declared one ivar called delegate
id <MyDelegate>delegate;
and another ivar called _delegate
#synthesize delegate = _delegate;
Some suggestions...
don't declare the iVar separately from your #property declaration
don't #synthesize, since XCode 4.4 you don't have to. The compiler will autosynthesize and autocreate an iVar with leading underscore
always refer to you ivar via it's property, inside and outside of your class. Only exceptions are in init, dealloc and inside custom setters and getters.
So this is how your code should look
#protocol MyDelegate <NSObject>
#required
- (void)update;
#end
#interface MyHandlerClass : NSObject
#property (nonatomic, weak) id <MyDelegate>delegate;
#end
#implementation MyHandlerClass
- (void)updateRequired: (id)sender
{
if(self.delegate)
{
[self.delegate update];
}
}
#end
To access your delegate property in the updateRequired method, you can do it by either using the private variable _delegate or by using self.delegate. Because when you synthesize using delegate = _delegate, setters and getters are automatically created.
This line tells the compiler to create a setter and getter for delegate, and that they should use the ivar called _delegate. Without the = _delegate part, the compiler would assume that the property and ivar have the same name.