1) I Am passing the value between two view controller using custom
protocol..But the value always showing NULL.
I need to pass the value from second view controller to first view controller
2) In Secondview controller.h
#protocol PopoverTableViewControllerDelegate <NSObject>
#property (nonatomic, strong) id<PopoverTableViewControllerDelegate>myDelegate;
3) secondview controller.m
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary*dict=[sercharray objectAtIndex:index];
str=[dict objectForKey:#"id"];
NSLog(#"test value %#",str);
[self.myDelegate didSelectRow:str];
NSLog(#"delegate value %#",self.myDelegate);
//THIS VALUE ALWAYS SHOWING NULL AND ALSO I SHOULD PASS THIS VALUE TO FIRST VIEW
CONTROLLER.I SHOULD USE DISMISS VIEW CONTROLLER.
[self dismissViewControllerAnimated:YES completion:nil];
}
4) First View controller.h
#interface Firstviewcontroller :
UIViewController<PopoverTableViewControllerDelegate>
5) First view controller.m
secondviewcontroller *next=[[seconviewcontroller alloc]init];
next.myDelegate=self;
(void)didSelectRow:(NSString *)cellDataString {
passstring = cellDataString;
NSLog(#"pass string %#",pass string);
//first view controller str variable value i need to pass this string[passstring].
}
I think you might be a little confused about what Delegation is used for and why. For example you might want to make a protocol in a UIViewController subclass if you were doing some kind of action in that ViewController and needed to inform another subclass that that action is being taken, or of the result of that action. Now in order for the subclass that wants to know about the action(the receiver), it has to conform to that protocol in it's header file. You also must "set" the delegate to the receiving class/controller. There are many ways to get a reference to the receiving controller/class to set it as the delegate but a common mistake is allocating and initializing a new instance of that class to set it as the delegate, when that class has already been created.What that does is set your newly created class as the delegate instead of the class that's already been created and waiting for a message. What your trying to do is just pass a value to a Newly created class. Since your just creating this UIViewController class all thats needed for that is a Property in the receiver(ViewControllerTwo). In your case a NSString:
#Property (nonatiomic, retain) NSString *string; //goes in ViewControllerTwo.h
and of course don't forget in the main:
#synthesize string; //Goes in ViewControllerTwo.m
Now there is no need for a setter in your ViewControllerTwo.
- (void)setString:(NSString *)str //This Method can be erased
{ //The setter is created for free
self.myString = str; // when you synthesized the property
}
The setter and Getters are free when you use the #synthesize. Just Pass the value over to the ViewController. The implementation is identical to your code except for the delegate:
ViewControllerTwo *two = [[ViewControllerTwo alloc] initWithNibName:#"ViewControllerTwo" bundle:nil];
[two setString:theString];
[self.navigationController pushViewController:two animated:YES];
[two release];
Related
I have a class that subclasses UITableViewController. Based on user actions that are recognized in this class, I need to call a method on a table in the UIViewController were the table is instantiated. I can't figure out how to do this.
I tried to make the function static, but that won't work since there is an instance variable that I need to reach. I could probably use NSNotificationCenter but my intuition is that there is a better way. Can someone help? Thanks!
MonthsTableViewController.h
#interface MonthsTableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate>
{
NSArray *monthsArray;
}
#end
MonthsTableViewController.m
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSLog(#"calling the UIViewController");
//this is where I am stuck!!!
}
SubscribeViewController.h
#interface SubscribeViewController : UIViewController <SIMChargeCardViewControllerDelegate>
{
MonthsTableViewController *monthsController;
IBOutlet UITableView *monthsTable;
}
- (void) snapMonthsToCenter;
#end
SubscribeViewController.m
- (void) snapMonthsToCenter {
// snap the table selections to the center of the row
NSLog(#"method called!");
NSIndexPath *pathForMonthCenterCell = [monthsTable indexPathForRowAtPoint:CGPointMake(CGRectGetMidX(monthsTable.bounds), CGRectGetMidY(monthsTable.bounds))];
[monthsTable scrollToRowAtIndexPath:pathForMonthCenterCell atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
Basically in order to do this, you need a reference to your UIViewController from your UITableViewController. This will allow you to call the methods of this object. Typically you would call this property a delegate, because you're assigning the "parent" UIViewController as the delegate of the "child" UITableViewController.
Modify your UITableViewController (MonthsTableViewController.h) to add a delegate property like so:
#interface MonthsTableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate>
{
NSArray *monthsArray;
id delegate;
}
#property (nonatomic, retain) id delegate;
#end
You will need to #synthesize the property in your .m file. You'll also want to import SubscribeViewController.h in your header here, if you haven't already.
Then, when you instantiate your MonthsTableViewController, set the delegate to your current object MonthsTableViewController like so:
MonthsTableViewController *example = [[MonthsTableViewController alloc] init.... // This is the line you should already have
[example setDelegate:self]; // Set this object's delegate property to the current object
Now you have access to the parent SubscribeViewController from your MonthsTableViewController. So how do you call functions? Easy! You can either hardcode the method call, or, to be super safe, use respondsToSelector::
[(MonthsTableViewController*)[self delegate] snapMonthsToCenter];
In your case, the above code is absolutely fine, because you know that this method will always exist on this object. Typically, however, delegates are declared as protocols that may have optional methods. This means that although methods are declared in the #interface, they may not actually exist (be implemented) in the object. In this case, the following code would be used to make sure that the method can actually be called on the object:
if([[self delegate] respondsToSelector:#selector(snapMonthsToCenter)]) {
[[self delegate] snapMonthsToCenter];
}
I feel frustrated with this problem, I my delegate doesn't work, Here's the code snippet below. I'm just using xib in this application.
//classA.h file
ClassA.h
#import "ClassB.h"
#interface ClassA : UIViewController< ClassBDelegate >
//classA.m file
**ClassA.m**
-(void)didSuccessPreview:(ClassB *)controller andLog:(NSString *)log{
NSLog(#"%#", log);
}
//classB.h file
**ClassB.h**
#import <UIKit/UIKit.h>
#class ClassB;
#protocol ClassBDelegate <NSObject>
- (void)didSuccessPreview:(ClassB *)controller andLog:(NSString *)log;
#end
#interface ClassB : UIViewController
#property (weak, nonatomic) id< ClassBDelegate >delegate;
//classB.m file
**ClassB.m**
I add this code below inside view did load
[self.delegate didSuccessPreview:self andLog:#"zz"];
I have other delegate inside my application same as the code above, but it works but this one is not, I don't know why. Inside my classA I have a button then when i click it it goes to classB, then when it goes to viewdidload in ClassB, the delegate doesn't fired.
Depending on where you assign the delegate, your code might need to look like this:
ClassB viewController = [ClassB new];
ClassA delegateStrongRef = [ClassA new]
viewController.delegate = delegateStrongRef; // <-- you are missing this now;
// Fixed: the ClassA object must be referenced strongly somewhere else
// besides the (weak)delegate property, otherwise it will be deallocated.
(The code above is the part where you create the instance of ClassB, the view controller. It might be inside the AppDelegate, another viewController's implementation, anything - depending on how your app is structured).
Then, in the view controller's -viewDidload method, you can have the delegate execute a method like this:
- (void)viewDidLoad
{
[self.delegate didSuccessPreview:self andLog:#"zz"];
}
so, at some point after instantiating your view controller, you need to assign an object of type ClassA (the class that adopts the delegate protocol) to its delegate property, otherwise it will be nil and any messages sent to it will be ignored (no method executed).
Properties and instance variables of object type are not allocated automatically, but initialized to nil (ints, floats etc, are initialized to 0, 0.0f, etc.)
EDIT: If you are assigning the delegate from ClassA's code, then it might look like this:
ClassA.m:
- (void) someMethodOfClassA
{
ClassB viewController = [ClassB new];
viewController.delegate = self;
// e.g., Do something with the view controller...
[navigationController pushViewController:viewController animated:YES];
}
Since the delegate property is defined as a weak reference, before calling any method of the delegate make sure it has not been deallocated and its reference set back to nil (use NSLog or set a breakpoint).
I have a View Controller class which contains a button property, and I need to change its enabled stated from a different class (Table View Controller). I'm also calling a method that's in that VC class. I can call the method just fine, but when I try to access the button property, it's nil. Actually all of its properties are nil. I must have something not set up quite right.
//ViewController.h
#property (strong, nonatomic) IBOutlet UIButton *aButton;
- (IBAction)myButtonTapped;
//ViewController.m
//did not override setter or getter for aButton
- (IBAction)myButtonTapped {
//code here
}
//Table VC.m
#property (strong, nonatomic) ViewController *myVC;
- (ViewController *)myVC {
if (!_myVC) _myVC = [[ViewController alloc] init];
return _myVC;
}
- (void)userEnteredText:(NSNotification *)notification {
[self.myVC myButtonTapped]; //runs method without issue
self.myVC.aButton.enabled = YES; //does not occur since aButton is nil - myVC is not nil
}
You need to study the information provided by #Hot Licks to understand how to keep references between your objects, but I can tell you that part of your problem is your getter method -
- (ViewController *)myVC {
if (!_myVC) _myVC = [[ViewController alloc] init]; // <-- This is a problem
return _myVC;
}
If your _myVC variable is nil then your getter method allocates a new ViewController - so you won't get a reference to the existing viewController. As you then call the plain init method for your new viewController none of its properties will be initialised - so you get nil for your button.
You don't need to write any code for a simple property like this - the default code that is created for you is all you need. What you do need to do is set the myVC property from your current viewController instance. So somewhere in your viewController you will have
tableVC.myVC=self;
You will need to do this somewhere where you have a reference to your tableVC - so this could be inprepareForSegue if you are using storyboards and segues or wherever you present or push the table vc if you aren't
In my childview controller I have this property:
#property (nonatomic, assign) NSInteger currentItemIndex;
In parent view controller, I want to set that value.
[childViewController setCurrentItemIndex:5];
[self.navigationController pushViewController:childViewController animated:YES];
But in the childViewController, currentItemIndex is 0.
Why I cannot set it? Where am I wrong?
ReceiverViewController.h
#property (nonatomic, assign) NSInteger currrentIndex;
ReceiverViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(#"Index value %d",self.currrentIndex);
}
DataPassingViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
DataPassingViewController *detailViewController = [[DataPassingViewController alloc] initWithNibName:#"DataPassingViewController" bundle:nil];
detailViewController.currrentIndex = 5;
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
}
I used the above code which gives a output as follows:
2013-07-10 17:50:10.230 DataPassing[3881:c07] Index value 5
Try to read _CurrentIndex inside your childview class, this variable should be autogenerated and set using the setter setItemIndex method.
I had too an experience with Xcode that when i did a build for 64 bit target, the internal variable with underscore was generated automatically, but for 32 bit target i had to declare it in interface and use the #synthesize statement in inplementation to get the code to compile.
Just declare simply, as
#property NSInteger currentItemIndex;
And if it dont solve the problem, you have to tell where you declare the property, which class, in interface declaration or not, which xcode you are using etc. post more code.
e.g. for xcode 4.6 this is okay. but for old xcode you have synthesize the property.
I´m having problems declarating my own delegate. Well...thats not exactly true: i have it declarated and, when i build the project, the compiler reports no issues. I declarated it in this way:
I made a file (enviarDatos.h) for declare the protocol:
#protocol enviarDatos <NSObject>
- (void)addItemViewController:(NSMutableArray *)item;
#end
In the Vista2.h (ViewController) file I imported the file enviarDatos.h and declared a property:
#property (nonatomic, weak) id <enviarDatos> delegare;
In the Vista2.m (ViewController) file I use the protocol method:
#interface ViewController : UIViewController <enviarDatos> {
And, finally, in the ViewController.m file I implement the delegates method:
- (void)addItemViewController:(NSMutableArray *)ar {
origen = ar;
}
Does anyone see something wrong? the code of the last function its never executing.
Thanks for your help.
EDIT:
What i need is to change an array in ViewController from Vista2 (another viewcontroller)
Then create delegate property in next view(child view) & set it to self in parent view while pushing or showing child view.
ParentView.m
1.Implement protocol methods
- (void)addItemViewController:(NSMutableArray *)ar
{
origen = ar;
}
2.While showing child view
ChildViewController *child = [[ChildViewController alloc] init];
child.delegate = self;
//present child view
ChildView.h
#property (nonatomic, weak) id <enviarDatos> delegare;
ChildView.m
-(void) anyMethod
{
if([self.delegate respondsToSelector:#selector(addItemViewController:)])
{
[self.delegate addItemViewController:mutableArray];
}
}
Ah, it looks like you are declaring the delegate property in the wrong place.
You should declare the property delegate in enviarDatos.h.
#property (nonatomic, weak) id <enviarDatos> delegate;
Then in Vista2.m you will do something like this...
EnviarDatos *myObject = [[EnviarDatos alloc] init];
myObject.delegate = self;
This then sets up the EnviarDatos object and assigns the Vista2 object as the delegate.
Now, in EnviarDatos.m you can run...
[self.delegate addItemViewController:someObjectArray];
And this will then run that code in the Vista2 object.
Delegates are used for calling back to objects that create them (or some other objects). If you create an object and then want to run a method in it then you won't need a delegate.
Can you say at what condition addItemViewController is invoked?
You seem to be on the right track, but are you sure you are setting the delegate as
[yourObject setDelegate: self];
Have you tried debugging it? Does the debugger pause at addItemViewController if you set a breakpoint there? Can you confirm the delegate is not null inside the method? I may post some code but your seems to be right except for the assigning of delegate, I think you should check it.