Delegate method in the set delegate object not responding - iphone

I have a somewhat similar concern with this question a custom delegate method inside didSelectRowAtIndexPath.
However, in my case before getting to the delegate object which is a UIViewController named BarCodeViewController, I should first pass by 2 view controllers from the initial view controller which is the CardViewController which is a table view controller. I'm setting the delegate object for my custom delegate through this:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
CardDetailsViewController *details = [self.storyboard instantiateViewControllerWithIdentifier:#"cardDetails"];
Card *selectedCard = [self.myWallet objectAtIndex:indexPath.row]; // I want this selected card to be accessible until the user clicks another card or during end of program.
[self.navigationController pushViewController:details animated:YES];
[self.delegate cardWalletViewController:self withCurrentCard:selectedCard];
[self setDelegate:self.barCodeVC]; // barCodeVC is declared in CardWalletViewController.h as #property (nonatomic, strong) BarCodeViewController *barCodeVC;
if (self.delegate) {
NSLog(#"delegate is not nil");
}
}
and this is how I instantiate the view controller which I set as the delegate object
- (void)viewDidLoad
{
[self setBarCodeVC:[self.storyboard instantiateViewControllerWithIdentifier:#"myBarcodeVC"]];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
And in my delegate object, which is the BarCodeViewController I implement the delegate method
#import "CardWalletViewController.h"
#interface BarCodeViewController () <CardWalletDelegate>
#end
#implementation
- (void)cardWalletViewController:(CardWalletViewController *)sender withCurrentCard:(Card *)currentCard
{
Card *myCurrentCard = currentCard;
NSLog(#"This is my current card: %#", myCurrentCard);
}
#end
I think I am able to set my delegate object, but then the delegate method is not being implemented for I don't see in the console the NSLog(#"this is my current......"); when I reach the BarCodeViewController.
Advice please.

That's not a standard use for delegate and it's hard to tell what you really want to happen. but, it looks like your code...
[self.delegate cardWalletViewController:self withCurrentCard:selectedCard];
[self setDelegate:self.barCodeVC];
Is making the call on whatever the "old" delegate is (before setting it to barCodeVC). Are you really trying to make the call on the "new" delegate? Should it be...
[self setDelegate:self.barCodeVC];
[self.delegate cardWalletViewController:self withCurrentCard:selectedCard];
EDIT
What I am saying is that you are sending a message to the delegate in this line...
[self.delegate cardWalletViewController:self withCurrentCard:selectedCard];
and THEN you are setting the delegate to barCodeVC
[self setDelegate:self.barCodeVC];
So, the message is actually being sent to whatever the delegate was set to before it was set to barCodeVC (another view controller, or nil, or...). Maybe that's what you want to happen, but it looks suspicious.

Related

custom delegate being null iOS

I know this should be a simple thing to fix, but I can't see what's going wrong. May be extra pair will help. Here is what I am trying to do.
In my table view controller, there is an (+) button on the navigation controller to add new item.
I have a modal segue that takes it to the next view controller. User fills in a form and hit saves the table view controller reloads with the newly added record.
To do this, I implemented protocol with a delegate.
MyFormViewController.h
protocol MyCustomDelegate <NSObject>
#required
- (void)addNewRecord:(myFormViewController *)formViewController itemToAdd:(Item *)item;
#end
#property (nonatomic,weak) id<MyCustomDelegate> delegate;
MyFormViewController.m
#synthesize delegate;
- (IBAction)addItem:(id)sender {
Item *item = [[Item alloc]init];
item.name = itemName.text;
item.desc = itemDescription.text;
// I am having problem here, self.delegate is being null even though, it's being set in prepareForSegue.
if ([self.delegate respondsToSelector:#selector(addNewRecord:)]) {
[self.delegate addNewRecord:self itemToAdd:item];
}
else{
// delegate is getting set to null for some reason.
NSLog(#"Delegate method not getting called...%#",delegate);
}
}
in MyTableViewController.h
#interface MyTableViewController : UITableViewController
MyTableViewController.m
-(void)addItem:(myFormViewController *)formViewController itemToAdd:(Item *)item{
if(item)
{
MyClass *_itemClass = [[MyClass alloc]initWithPath:#"items/"];
[_itemClass addItemForUser:item];
}
[formViewController dismissViewControllerAnimated:YES completion:nil];
}
in my prepareForSegue method I am setting my tableviewcontroller as delegate.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"addItemSegue"]){
myFormViewController *_showaddTopic = [[myFormViewController alloc]init];
_showaddTopic.delegate = self;
}
After all this, my delegate in myFormViewController is being set to "null". I am not sure why it's not working. It's pretty basic stuff but giving me hard time.
Thank you
myFormViewController *_showaddTopic = [[myFormViewController alloc]init];
_showaddTopic.delegate = self;
There's your problem. You are creating a new MyFormViewController. But that's the wrong MyFormViewController; you want to use the one that is already the segue's destination controller. So you are setting the wrong object's delegate.
(PS Notice my use of a capital letter to start the name of a class? Always do that.)
maybe _showaddTopic.delegate = self; can not written here and shuold this object alloc after at once

IBOutlet UITextView is nil after calling another class initWithNibName and back to the class using method

My problem is that in ProductNote class UIButton Action I did initWithNibName Notes Class to show the popOver with a UITableView in Notes Class. I am fetching data from sqlite and then load it to UITableView in tableViewDidSelectRowAtindexPath:. I got the selectedNote and creates object of ProductNote Class to call selectedNote instance method that only set IBOutlet's textview.text but its nil. Thats my problem, Below is the code please help me to knowing why i face this type of issue. I am using Xcode 4.3.3 and not using ARC. Manually I defined dealloc method on every ViewController
//**ProductNote.h Class****************************
#import <UIKit/UIKit.h>
#class Notes;
#interface ProductNote : UIViewController<UIPopoverControllerDelegate>
{
UIPopoverController *popOverController;
UITextView *txtmesssagenotes;
Notes *objNotes;
}
#property (retain, nonatomic) IBOutlet UITextView *txtmesssagenotes; //It is Connected to ProductNote.xib
#property (retain,nonatomic) UIPopoverController *popOverController;
#property (retain,nonatomic) Notes *objNotes;
-(IBAction)presentPopOver:(UIButton*)sender;
-(void)selectedNote:(NSString*)note;
#end
//ProductNote.m Class
#implementation ProductNote
#synthesize txtmesssagenotes,popOverController,objNotes;
-(IBAction)presentPopOver:(UIButton*)sender
{
self.objNotes=[[Notes alloc]initWithNibName:#"Notes"bundle:nil];
UIPopoverController *popOver=[[[UIPopoverController alloc]initWithContentViewController:objNotes]autorelease];
self.popOverController=popOver;
self.popOverController.delegate=self;
self.popOverController.popoverContentSize=objNotes.view.frame.size;
CGRect rect=[self.view convertRect:objNotes.view.frame fromView:self.view];
rect.origin.y+=110;
rect.origin.x+=23;
[self.popOverController presentPopoverFromRect:rect inView:self.view permittedArrowDirections:0 animated:YES];
//Then I get popOver with tableview
}
-(void)selectedNote:(NSString*)note
{
self.txtmesssagenotes.text=note;
//Here I am getting txtmesssagenotes=0X0 or nil. Using self or without self Please tell me the reason.
}
- (void)dealloc {
[txtmesssagenotes release];
[popOverController release];
[objNotes release];
[super dealloc];
}
#end
#interface Notes : UITableViewController
{
NSMutableArray *arrNotes;
NSString *selectedNote;
UITableView *tblNotes;
}
#property(nonatomic,retain)NSMutableArray *arrNotes;
#property(nonatomic,retain)NSString *selectedNote;
#property(nonatomic,retain)IBOutlet UITableView *tblNotes;
#end
//Actually I skip the other methods that makes larger program to read . other methods only used to fetch data from sqlite and fill up the arrNotes that is used to fill all rows in the tableview.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedNote=[self.arrNotes objectAtIndex:indexPath.row];
//Here self.arrNotes valid object and contains the data, and assigns NSString object to self.selectedNote
ProductNote *productNote=[[ProductNote alloc]init];
[productNote selectedNote:self.selectedNote]; //after calling selectedNote i goto to selectedNote implementation or definition above.
[productNote release];
}
-(void)dealloc
{
[arrNotes release];
[selectedNote release];
[tblNotes release];
[super dealloc];
}
It is because just as you stated that txtmesssagenotes was created using IB. And you never presented your ProductNote UIViewController instant productNote. So the txtmesssagenotes was never allocated and initialized properly.
Are you calling selectedNote: before your view has loaded?
Just because you created a view controller with a xib doesn't mean that it loads all your subviews immediately.
The xib is parsed and all your views are created the first time that the view controller's view property is asked for - this is usually just before it appears for the first time.
Until then, all the IBOutlet connections will be nil.
You need to store the text for your note as an NSString property of you view controller. Then, inside either viewDidLoad you need to call self.txtmesssagenotes.text=self.note; - viewDidLoad is automatically called just after your view is loaded so you are guaranteed to have all your IBOutlets set by then.
You shouldn't rely on your view objects to store the state of your app (in this case, the text of the note). If a low memory warning is received while your view controller isn't visible then all your view objects will be deleted - they will only be recreated when your view controller becomes visible again - if you are storing your note string inside a UITextView then it might no be there the next time you ask for it :) You should always store data in a property of your view controller (or somewhere else you control) and create your views using it.

Delegate not working properly

I am trying to pass some information between a subview and a parentview on the navigation stack using delegates.
However for some reason when the I execute the delegate from the subview then pop the subview from the navigational controller it never enters the delegate method that is set up in the parent view.. I have tried NSLogs & Breakpoints the thread is defiantly not making it to this delegate method in the main view so I was hoping you could help me out.
First Of all I will show you how I have set up my delegate, where I call it in my subview and then where I set it up in the mainview hopefully you guys will be able to see something I have not so far.
Subview.h // I have left out things not related to the delegate
#import <UIKit/UIKit.h>
//Delegate - Protocol stuff for passing data from this view to the parent view
#protocol PassSearchData <NSObject>
#required
- (void) setManufactureSearchFields:(NSArray *)arrayValues withIndexPath:(NSIndexPath *)myIndexPath;
#end
#interface SecondViewController : UITableViewController <UITableViewDataSource> {
//Delegate (Used to pass information back to parent view)
id <PassSearchData> delegate;
}
//Delegate (Used to pass information back to parent view)
#property (strong) id delegate;
#end
SecondView.m
#import "SecondViewController.h"
#import "FirstViewController.h"
#implementation SecondViewController
//..
//Delegate (Used to pass information back to parent view)
#synthesize delegate;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Access selected cells content (cell.textLabel.text)
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
//Parent view logic (sends info back to the correct cell in parent view)
if (parentViewSelectedIndexPath.section == 0)
{
if (parentViewSelectedIndexPath.row == 0)
{
//Predicates restrict the values that will be returned from the query
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K like %#",#"MANUFACTURER",cell.textLabel.text];
filterArray = [parsedDataArrayOfDictionaries filteredArrayUsingPredicate:predicate];
[[self delegate]setManufactureSearchFields:filterArray withIndexPath:indexPath];
// NSLog(#"Filtered Array = %#", filterArray);
}
}
[self.navigationController popViewControllerAnimated:YES]; //pops current view from the navigatoin stack
}//...
Then this is how I set it up inside the FirstViewController
FirstViewController.h
#import <UIKit/UIKit.h>
#import "VehicleResultViewController.h" //With this included I can now use the PassSearchData delegates of this view for passing data
#interface VehicleSearchViewController : UITableViewController <PassSearchData> {
//..
FirstViewController.m
#import "VehicleSearchViewController.h"
#import "VehicleResultViewController.h" //Subview
//..
#pragma mark - Received data from Sub view delegates
//These are the delegate method for passing data from the child to the parent view (parent being this view, with the delegate being declared in the subview)
- (void) setManufactureSearchFields:(NSArray *)arrayValues withIndexPath:(NSIndexPath *)myIndexPath
{
manufactureSearchObjectString = [[arrayValues valueForKey:#"MANUFACTURER"] objectAtIndex:0];
manufactureIdString = [[arrayValues valueForKey:#"MANUFACTURERID"] objectAtIndex:0]; //Restricts Models dataset
manufactureResultIndexPath = myIndexPath;
}
If anyone knows what I'm missing/doing wrong any help would be really really heapful
any questions let me know.
Solution
In the firstviewcontroller when I go to load the secondviewcontroller inside
tableView:didSelectRowAtIndexPath: I forgot to set the secondviewcontrollers delegate before I pushed the view to the navigational stack.. so the missing code was this.
FirstView.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Get the subview ready for use
VehicleResultViewController *vehicleResultViewController = [[VehicleResultViewController alloc] initWithNibName:#"VehicleResultViewController" bundle:nil];
//Pass the selected object to the new view controller.
[self.navigationController pushViewController:vehicleResultViewController animated:YES];
[vehicleResultViewController setDelegate:self];
//etc
thanks guys.
Ok, first, your delegate should be a weak reference to avoid retain cycles. But I suspect maybe the delegate isn't getting set. Can you show the code where SecondViewController is instantiated and the delegate is set? Can you set a breakpoint at the delegate call and verify that it is not nil?
I think you are not setting Delegate.
After Creation Instanace(object)of SecondViewController ,you have to set Delegate.
ie
SecondViewController *secondObj=[[SecondViewController alloc]initWithNibName:#"SecondViewController"> bundle:nil];
[secondObj setDelegate:self];

How to call a method of another Class?

EDIT2: I try to summarize my problem and the solutions:
I've got a TableViewController named DetailedViewController. My intention was to activate TouchesBegan to recognize actions like sliding etc, and normally, the method touchesbegan is replaced with the DidSelectRow method. In many posts on stackoverflow, subclassing the UITableView is the only possibility to realize this.
So i created a SpecificTable with .xib file and i used this as a subclass of UITableViewController by adding the SpecificTable as the nib-file.
Selecting a row works fine, and also the TouchesBegan method (i called a method IN the SpecificTable.m with an Alert.) But now i want to call a Method in the UITableViewController (DetailedViewController) where moveToNextItem is declared like
-(void)moveToNextItem:(id)sender
{
[self.navigationController
pushViewController:bbarChart animated:YES];
}
But by calling this method with [self moveToNextItem] the App crashes by touching. (in the Debugger-Mode, the App crashes in the line of [self moveToNextItem].
What is the right way to call the method of DetailedViewController.m?
Update: You should probably subclass UITableViewCell rather than UITableView. Then in your table view controller's cellForRowAtIndexPath: method, return an instance of this subclass rather than an instance of UITableViewCell.
You will also need to pass a DetailedViewController pointer on to the cell, so that you can invoke its moveToNextItem method in the touchesBegan, etc. methods.
Adapt this example to your needs:
MyTableViewCell.h
#class DetailedViewController;
#interface MyTableViewCell : UITableViewCell {
DetailedViewController *dvc;
}
#property (nonatomic, retain) DetailedViewController *dvc;
#end
MyTableViewCell.m
#import "MyTableViewCell.h"
#import "DetailedViewController.h"
#implementation MyTableViewCell
#synthesize dvc;
- (void)someMethod { // This would be your touchesBegan, etc. methods
[dvc moveToNextItem];
}
- (void)dealloc {
[dvc release]; // We retained dvc so we have to release it when we're done with it
[super dealloc];
}
#end
DetailedViewController.h
#interface DetailedViewController : UITableViewController {
// iVars here
}
// Methods and properties here
- (void)moveToNextItem;
#end
DetailedViewController.m
#import "DetailedViewController.h"
#import "MyTableViewCell.h"
#implementation DetailedViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyTableViewCell"];
if(cell == nil) {
cell = [[[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyTableViewCell"] autorelease];
cell.dvc = self; // This gives the cell a reference to the detailed view controller
}
return cell;
}
- (void)moveToNextItem {
// ...
}
#end
There are probably far better ways to achieve what you want, but this is the best I can do without more information.
Declare the method in DetailedViewController.h, and #import that file in SpecificTable.h.
if SpecificTable is really a subclass of DetailedViewController you can call
[self moveToNextItem];
as already mentioned.
but i think you mean a subview or not? so SpecificTable.view is a subview ob DetailedViewController.view
you have several options then. for example using NSNotificationCenter.
or what is probably also a good way for you is to setup an instance variable of DetailedViewController in your SpecificTable and assign it when you init your SpecificTable.
as an example:
// the parent view .m
testTVC *tableview = [[testTVC alloc] initsomething];
tableview.parentVC = self;
[self.view addSubView:tableview.view];
[tableview release];
now in your testTVC
// the .h
#interface testTVC : UITableViewController {
testVC *parentVC;
}
#property(nonatomic,retain) testVC *parentVC;
#end
// the .m
[parentVC moveToNextItem];
you also have to synthesize and release your parentVC.
Is [NSNotificationCenter defaultCenter] something you are looking for?

How to push UIViewController into UINavigationController from seperate UIView of different UIViewController which uses this view

I have a UIViewController (AbcViewController) with NavigationController. AbcViewController uses UIView (AbcView) as its view. AbcView has a UITableView. I have set this TableView's datasource in AbcViewController and delegate in its SuperView i.e. AbcView. How will I push another UIViewController (XyzViewcontroller) into navigationController when I select a row in this table because it gives
"error: request for member 'navigationController' in something not a structure or union"
when I do this:
[self.navigationController pushViewController:xyzViewcontroller animated:TRUE];
I also did this:
AbcViewController *parentVC;
[parentVC.navigationController pushViewController:xyzViewcontroller animated:TRUE];
Though it builds successfully, XyzViewcontroller's view does not appear. It does not push XyzViewcontroller's view onto navigationController.
We can make a delegate on AbcView so that we can refer back to the view's viewController which in this case is AbcViewController. We can set delegate as:
#interface AbcView : UIView
{
id delegate;
}
#property(nonatomic, assign) id delegate;
Then in AbcViewController, set the view's delegate like this:
[abcView setDelegate:self];
Now in table method using our delegate from within AbcView as:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[delegate pushOtherView];
}
it will call - (void)pushOtherView method in AbcViewController whose definition is:
- (void)pushOtherView
{
XyzViewcontroller * xyzViewcontroller = [[[XyzViewcontroller alloc] init] autorelease];
[self.navigationController pushViewController:xyzViewcontroller animated:YES];
}
But before using this method, it should be mentioned in protocols otherwise it will show
Warniing:
-pushOtherView' not found in protocol(s).