protocol and delegate not accessing method - ios

I am trying to pass some data back to my UIView, its abit of a complicated situation I will try to explain it.
I have my
mainViewController // request is made to RequestClass
requestClass // Request is sent off to DB for data, data is returned then passed to seriesDataClass
seriesDataClass // sorts the data and then sends back the needed info to mainViewController using protocol & delegates
This is what my code looks like for setting up the protocols and delegates
mainViewController.h
#import "SeriesDataClass.h"
#interface MatchingSeriesViewController : UIViewController <GetSeriesViewParsedData>
{
mainViewController.m
#import "SeriesDataClass.h"
// this is where I set up my protocols delegate.
- (void)viewDidLoad
{
//..
// get delegate ready
SeriesDataClass *seriesDataClass = [[SeriesDataClass alloc] init];
[seriesDataClass setDelegate:self];
//..
// pass data over to requestClass so you can get the info from the DB
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//..
[requestClass GetSeries:requestID];
//..
}
requestClass.m
// dose a bunch of stuff then calls seriesDataClass and passes all of its information over to it
//..
SeriesDataClass *seriesDataClass = [[SeriesDataClass alloc] init];
[seriesDataClass recivedData:uncompressedData];
//..
seriesDataClass.h
#import <Foundation/Foundation.h>
// This passes data back to the mainViewController
#protocol GetSeriesViewParsedData <NSObject>
- (void)sendGetSeriesArrays:(NSDictionary *)series LSeries:(NSDictionary *)lSeries;
#end
#interface SeriesDataClass : NSObject <NSXMLParserDelegate> {
//..
}
#property (assign, nonatomic) id <GetSeriesViewParsedData> delegate;
seriesDataClass.m
#implementation SeriesDataClass
#synthesize delegate;
// then in a method later on i call the delegate to pass the information back to mainViewController but this dosnt do anything atm.
//..
[self.delegate sendGetSeriesArrays:seriesDictionary LSeries:lSeriesDictionary];
//..
mainViewController.m
// then back in the mainViewController class I Have the method
- (void)sendGetSeriesArrays:(NSDictionary *)series LSeries:(NSDictionary *)lSeries {
// this method is never accessed
}
So my question is what am i missing in the set up of this protocol/delgate for it not to be working correctly?
I hope the structure of the question makes sense if you need any more information please let me know.

Your problem is that you are creating 2 instances of your SeriesDataClass, one in MainViewController, and another in RequestClass. So, the instance that calls the delegate method is not the same instance that the main view controller set itself as the delegate of. When you create an instance of RequestClass in MainViewController, you need to pass seriesDataClass (the instance you created) to a property in RequestClass, so that it will be working with the same instance.
You should create a property in MainViewController:
#property (strong,nonatomic) SeriesDataClass *seriesDataClass;
The viewDidLoad method should then look like this:
- (void)viewDidLoad {
self.seriesDataClass = [[SeriesDataClass alloc] init];
[self.seriesDataClass setDelegate:self];
}
Then in didSelectRowAtIndexPath, create your RequestClass instance, and pass it seriesDataClass:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
RequestClass *requestClass = [[RequestClass alloc] init];
requestClass.seriesDataInstance = self.seriesDataClass;
[requestClass GetSeries:requestID];
}
In the .h of RequestClass you need to have created that property:
#property (strong,nonatomic) SeriesDataClass *seriesDataInstance;
Then in RequestClass, this:
SeriesDataClass *seriesDataClass = [[SeriesDataClass alloc] init];
[seriesDataClass recivedData:uncompressedData];
should be replaced with just:
[self.seriesDataInstance recivedData:uncompressedData];
I've changed some of the capitalization, to reflect the way you should do it. Classes should start with capital letters, and instances and methods should start with lowercase ones.

Change this:
#import "SeriesDataClass.h"
// this is where I set up my protocols delegate.
- (void)viewDidLoad
{
//..
// get delegate ready
SeriesDataClass *seriesDataClass = [[GetSeriesResultItem alloc] init];
[seriesDataClass setDelegate:self];

Related

custom deleget not responding ToSelector

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.

ios delegate method not being called

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>

how to send data back with dismissViewController

i have 2 views in iPhone application. FirstViewController and MultiSelectViewController.
in FirstViewController there is a button to go to MultiSelectViewController. In MultiSelectViewController i have a tableviewcontroller to multiselect and send result back to FirstViewController with Done button
my problem is with done button. i don't know how to send data back to the FirstViewController. it has to be with dissmissviewcontroller.
this is .h file of MultiSelectViewController
#protocol MultiSelectDelegate <NSObject>
-(void) multiselectViewControllerDismissed;
#end
#interface MultiSelectViewController : UITableViewController
{
__weak id myDelegate;
}
#property(nonatomic,retain)NSArray *myData;
#property(nonatomic, retain)NSMutableArray *selectedData;
#property (nonatomic, weak) id<MultiSelectDelegate> myDelegate;
this is my done button in .m file of MultiSelectViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.allowsMultipleSelection = YES;
selectedData=[[NSMutableArray alloc] init];
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(multiselectViewControllerDismissed)];
self.navigationItem.rightBarButtonItem = barButton;
}
and lastly here is my done button action:
-(void)multiselectViewControllerDismissed
{
NSLog(#"%#",selectedData);
}
i don't understand how can i send data and get back in FirstViewController
You redefine
multiselectViewControllerDismissed delegate method as
multiselectViewControllerDismissedWithData:(NSMutableArray *)dataSelected
And, in .h file of FirstViewController implement the delegate i.e.,
#interface FirstViewController: UIViewController <MultiSelectDelegate>
and in the button action of FirstViewController.m assign delegate of MultipleSelectViewController as self. ie.,
MultipleSelectViewController * msvc = [[MultipleSelectViewController alloc] init];
msvc.myDelegate = self;
and implement
-(void)multiselectViewControllerDismissedWithData:(NSMutableArray *)dataSelected
this method in FirstViewController.m
And, in the Done button action method of MultipleSelectViewController.m, call method multiselectViewControllerDismissedWithData with delegate i.e.,
[self.myDelegate multiselectViewControllerDismissedWithData:selectedData];
That's it.
You could now pass selectedData array from MultipleSelectViewController to FirstViewController
Two standard ways of passing data in obj-c:
Use references and assign manually. In your example, the first view controller passes a reference of itself to the second view controller. The second view controller assigns a designated property with the required data using the reference.
The publisher-subscriber pattern using LocalNotifications. The first view controller listens for a particular location notification, and the second view controller, before being dismissed, does a broadcast with the data.
I'd recommend the 1st approach for your example. Some sample code:
In the .h file:
#interface FirstViewController:UIViewController
#property NSMutableArray *receivedData; //property to receive selected data
#end
In the .m file:
MultiSelectViewController *msvc = [MultiSelectViewController alloc] init];
msvc.presentingViewController = self; // pass reference of 1st VC to 2nd VC
[self presentViewController:msvc animated:YES];
In MultiSelectViewController.h file:
#import "FirstViewController.h"
#interface MultiSelectViewController: UITableViewController
...
#property FirstViewController *presentingViewController;
...
#end
In MultiSelectViewController.m file:
-(void)multiselectViewControllerDismissed
{
NSLog(#"%#",selectedData);
presentingViewController.receivedData = selectedData;
}
first create your delegate method as
-(void)dismiss:(NSString *)str;
while did select get a value from based on indexpath.row
and store it as nsstring.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.valueString=[NSString stringWithFormat:#"%#",[self.arrayValue objectAtIndex:indexPath.row]];
NSLog(#"%d",indexPath.row);
}
done button click:
call your delegate method like
[self. myDelegate dismiss:"your string which you get from table"]
[[self navigationController] popViewControllerAnimated:YES];
and in your first view controller…
import the view controller class and call delegate method..
create instance for second view controller...
MultiSelectViewController *txtNext=[[MultiSelectViewController alloc]init];
txtNext. myDelegate =self;
then
-(void)dismiss:(NSString *)str
{
NSString *strng=str;
nslog("%#",strng);
}

iOS Delegate not called

For a project I need to be able to send a status back from "secondTableViewController" to "firstTableViewController". I followed some tutorials on delegates but I don't seem to get it to work. When I want to call the method in firstTableViewController from the secondTableViewController I do a check to see if "delegate" property is empty, and every time it is..
This is my code:
SecondTableViewController.h
#protocol SendStatusDelegate <NSObject>
#required
-(void)didStatusChanged;
#end // eof delegate protocol
#interface SecondTableViewController : UITableViewController
#property (nonatomic, assign) id<SendStatusDelegate> delegate;
#end
SecondTableViewController.m
// Status is changed on row click
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.delegate) { // This is never called because delegate looks to remain empty
[self.delegate didStatusChanged];
}
}
FirstTableViewController.h
#interface FirstTableViewController : UITableViewController <SendStatusDelegate>
#end
FirstTableViewController.m
The only thing that goes on here is implementing the -(void)didStatusChanged method.
First You need to set the delegate to self in FirstTableViewController when you init the SecondTableViewController. say on didSelectRowAtIndexPath: you are calling the SecondTableViewController in that case,
FirstTableViewController.m
// Status is changed on row click
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SecondTableViewController *secondTableVC = [SecondTableViewController alloc] init];
secondTableVC.delegate = self;
}
In the FirstTableViewController where you create the SecondTableViewController instance you should assign the delegate of the created instance to FirstTableViewController
ie
secondTableViewControllerInstance.delegate = self;
in FirstTableViewController
Your FirstTableViewController Class should conform the SendStatusDelegate Like
#interface FirstTableViewController : UITableViewController <SendStatusDelegate>
And then then assign the delegate of SecondViewController instance by self Like
SecondTableViewControllerInstance.delegate = self;

Why isn't my delegate object responding to method calls?

I ultimately want to write an iOS app incorporating ALAssetsLibrary, but as a first step toward understanding delegation, I'm trying to pass a simple message between two view controllers. For some reason, I can't seem to get the message to pass. In particular, the delegate object (derpy) doesn't appear to exist (if(self.derpy) returns NO)).
I asked the same question on the Apple forums and was told that I should be using segues and setting properties / calling methods using self.child instead, but that seems strange. If I were to pass messages using the parent / child properties, would I still be able to create my views in Interface Builder? Once I have my two views set up, say inside a UINavigationController, I'm not sure how to actually "wire them up" so I can pass messages between them. Sorry if the question is overly broad.
Here's the controller I'm declaring the protocol in (called PickerViewController):
Interface:
#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
#protocol DerpDelegate <NSObject>
#required
- (void) test;
#end
#interface PickerViewController : UIViewController
#property (nonatomic, assign) id<DerpDelegate> derpy;
#end
Implementation:
#import "PickerViewController.h"
#interface PickerViewController ()
#end
#implementation PickerViewController
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.derpy) { // If the delegate object exists
[self.derpy test]; // send it this message
} else {
NSLog(#"Still not working."); // This always returns (i.e., self.derpy doesn't exist)
}
}
Delegate controller (MainViewController) interface:
#import <UIKit/UIKit.h>
#import "PickerViewController.h"
#interface MainViewController : UIViewController <DerpDelegate> // public promise to implement delegate methods
#property (strong, nonatomic) PickerViewController *picker;
- (void) test;
#end
And lastly, the delegate controller (MainViewController) implementation:
#import "MainViewController.h"
#import "PickerViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
// Here's that method I promised I'd implement
- (void) test{
NSLog(#"Test worked."); // This never gets called
}
- (void)viewDidLoad {
[super viewDidLoad];
self.picker.derpy = self;
//lazy instantiation
- (PickerViewController *) picker{
if(!_picker) _picker = [[PickerViewController alloc]init];
return _picker;
}
EDIT: Many thanks to rydgaze for pointing me in the right direction with self.picker.derpy = self, but for some reason, things still aren't working properly. Importantly, once that property has been set, if(self.picker.derpy) returns YES from MainViewController. But if(self.derpy) is still returning NO when called from inside the PickerViewController's viewDidLoad. How can the property exist and not exist at the same time?
You need to be sure that you're setting the delegate on the instance of the view controller that you put on screen. If you're using a navigation controller and segues to go between MainViewController and PickerViewController, then you should set the delegate in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
self.picker = (PickerViewController *)segue.destinationViewController;
self.picker.derpy = self;
}
You need to populate the delegate first.
Basically, your MainViewController shoudl at somepoint do a
picker.derpy = self;
Then when the delegate fires in PickerViewController, the callback will happen.
Edit:
A good practice is to do something like in PickerViewController
#property (nonatomic, assign) id<DerpDelegate > derpy;
and in your MainViewController indicate that you will implement the delegate
#interface MainViewController : UIViewController<DerpDelegate>
Eventually in your implementation of MainViewController
You will have something like
picker = [[PickerViewController alloc]init];
picker.derpy = self;
[picker doYourThing];
Once picker is all done, it may want to return results using the delegate.

Resources