I have a UIViewController class called , classA . This class is connected to buttons outlets of its connected view (from storyboard ).
What i would like to do , is to create another classB , that will handle all the buttons actions.
My question is, how can i set the delegates of a button in classA to be handled in classB, and how i make classB to be alive for all that time.
I was thinking about this .
in classA :(the main view controller that have the buttons outlets )
ClassB *buttonsResponder=[[classB alloc]init]; //initialize buttons class
[self.button addTarget:buttonsResponder action:#selector(do:) forControlEvents:UIControlEventTouchDown];
My main problem is, when classB handle the action, and lets say he has to open some mail composer view controller, how can classB open that mail composer "inside" classA view ? or even some UIView that i want to show in classA , but from classB
I was thinking of sending a pointer to the current view controller as an argument of the button, but i dont know how, and if it will work :
[self.button addTarget:buttonsResponder action:#selector(do:and
controller pointer?) forControlEvents:UIControlEventTouchDown];
The best way to keep ClassB alive in ClassA instance is make it a private property in class extension:
// In CalssA
#property (nonatomic, strong) ClassB *buttonsResponder;
You need to allocate it somewhere, viewDidLoad is good place:
self.buttonsResponder = [[classB alloc]init];
and in the same method you can make it a button(s) delegate:
[self.button addTarget:self.buttonsResponder action:#selector(do:) forControlEvents:UIControlEventTouchDown];
// Extended
If you want to present another view controller from your ClassB you can create property to hold weak reference to classA in classB:
// In ClassB.h
#property (nonatomic, weak) ClassA *myClassA;
Pass a reference to of classA when you initialise classB in viewDidLoad:
// In ClassA.m
self.buttonsResponder = [[classB alloc]init];
self.buttonsResponder.myClassA = self;
And when you want to present another view controller you can do it from classB:
[self.myClassA presentViewController:...];
[self.button addTarget:self.buttonsResponder action:#selector(do:)
forControlEvents:UIControlEventTouchDown];
If you want to present another viewcontroller from buttonsResponder:
[self.window.rootViewController presentViewController:anotherViewController animated:YES completion:nil];
Related
ClassA *a = [[ClassA alloc] initWithNibName:#"classA" bundle:nil];
a.viewInClassA.hidden = NO;
When i Run this code, the a.viewInClassA.hidden = NO do not make any effect PLEASE HELP
This is happen because you are making new class you not taking reference. So make property of that class and pass reference of class c in another class and then you can do hide using that property
In ClassA for example you have tableview.
Put this in ClassA.h file
#property (weak, nonatomic) IBOutlet UITableView *tableview;
From classB.h file make property of classA
#property (Strong, nonatomic) classA *classAObject;
And form classb.m where you want to hide table view write this
self.classAObject.tableview.hidden = YES;
when you open classB pass classA reference
ClassB *classB = [[ClassB alloc] initWithNibName:#"ClassB" bundle:nil];
classB.classAObject = self;
[self.navigationController pushViewController:classB animated:YES];
Don't try and manipulate another view controllers views. It's a violation of the principle of encapsulation. It's bad design, and sometimes it fails, as in your case.
Instead, add a property to your ClassA view controller that tells whether or not your view should be hidden. In your ClassA view controller's viewWillAppear read the property and use it to hide or show the view.
In my project, I have two ViewControllers - mapViewController and dataViewController.
In mapViewController, I have outlets for two buttons :
#property (weak, nonatomic) IBOutlet UIButton *previousButton;
#property (weak, nonatomic) IBOutlet UIButton *nextButton;
For fetching mapViewController in dataViewController,
self.MapViewController = ((OTPAppDelegate *)[[UIApplication sharedApplication] delegate]).mapViewController;
Using the above technique, I can manipulate the properties of mapViewController inside dataViewController by accessing self.MapViewController.property
However, if I wish to add a target for the two buttons inside dataViewController using the following code:
[self.MapViewController.previousButton addTarget:self action:#selector(doNothing:) forControlEvents:UIControlEventTouchDown];
It throws a BAD access error. I was wondering what needs to be fixed, in order to achieve the desired button click behavior.
Create a protocol in MapViewController
#Protocol prtocol_name <NSObject>{
-(void)method_name;
#end
create an object for protocol in MapViewController.
#property(nonatomic) id< prtocol_name> delegate;
in button methods implementation call protocol method like following
[self.delegate method_name];
And finally implement protocol method in DataViewController.
Thanks
If you want the target/selector in different view controller, then pass the delegate parameter as other view controller's instance. For eg:
[self.MapViewController.previousButton addTarget:otherControllerInstance action:#selector(doNothing:)
forControlEvents:UIControlEventTouchDown];
Detailed Explanation:-
You have two classes named FirstVC and SecondVC. A button is present in FirstVC, on which you want to add target in SecondVC.
[button addTarget:objSecondVC action:#selector(doSomething:)
forControlEvents:UIControlEventTouchDown];
I hope you have create property of mapViewController into dataViewController.
If you choose wrong property attributes then it can raise error you got.
Another possibility is, MapViewController property not assigned/initialized properly and it is nil while you are trying to add target of its subview.
The best way to get callback event is to use delegate.
Below are some information on how delegate works:
Delegate are function pointers. Using it, one can call another class' function easily.
To create delegate, common procedure is to, first create protocol and add relevant methods in it (in the class you want to initiate delegate method). This methods can be implemented by class that adopts protocol.
You also need to create generic property of protocol type called delegate property. This will be assigned to instance of class that conforms to protocol.
In your case, class mapViewController define some protocol in it. Here, dataViewController conforms class mapViewController's protocol.
Now, class dataViewController has object defined of class mapViewController in it. In class dataViewController, here we need to assign class mapViewController's delegate to instance of dataViewController(self). (now in class mapViewController, delegate property contains instance of dataViewController and one can easily call protocol method implemented in class dataViewController from class mapViewController).
I hope this will help you.
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 want to set the alpha of a UIImageView in a different class. In Class1.h I have a UIImageView that needs to change in Class2.m in IBAction. The alpha of the UIImageView initially is 1. This is my code that does not work despite not having errors.
Class1.h
{
IBOutlet UIImageView *Livello2Image;
}
-(void)setAlpha:(int)a;
Class1.m
- (void)setAlpha:(int)a
{
Livello2Image.alpha = a;
}
Class2.m
-(IBAction)ALP{
Class1 *class = [[Class1 alloc]init];
[class setAlpha: 0];}
Thanks and sorry for my english.
In your Class2 when you do
Class1 *class = [[Class1 alloc]init];
That creates a new instance of Class1 and then you set its alpha (then this new instance is destroyed or leaked depending on your ARC setting). This isn't what you want because you already have an existing instance of Class1 that you should be changing. That means you need a reference (pointer) to the instance.
When you create your Class2 instance, you should give it a reference to the Class1 instance. Class2 should have a property in which to store the reference.
So in your ViewController class you should implement prepareForSegue:sender:. This will give you the new instance of ProvaViewController (via segue.destinationViewController). You need to add the property to ProvaViewController (#property (strong, nonatomic) ViewController *viewController;) and then use that property to change the alpha ([self.viewController Trasparenza:0];).
Though... Your 'go back' button does seem to push a new view controller modally rather than actually go back (dismiss the current view as it is also presented modally). So really you need to think about your view controller structure as it's a bit mad currently...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:...]) {
[(ProvaViewController *)segue.destinationViewController setViewController:self];
}
}
Read the guide here, particularly the section "Send Data to the Detail Scene".
when you create class1 instance
Class1 *class = [[Class1 alloc]init];
class did not link the Livello2Image outlet, Livello2Image is nil.
I have 2 classes
ClassA: UIView
ClassB: UIViewController
I have a UIButton in ClassA
The button is declared in the header and as an #property of A
UIButton *selectBtn;
}
#property (nonatomic, strong) UIButton *selectBtn;
in the .m file of Class A the button is initialized and shows up on screen
ClassB imports ClassA's header file and from it I'm trying to set the target and the action for my button with the following
[ClassA.selectBtn addTarget:self action:#selector(getSomething:) forControlEvents:UIControlEventTouchUpInside];
But i keep getting an Error message saying
"Property "selectBtn" not found on object of type "ClassA"
What am I doing wrong ?
any help or guidance is very appreciated
[ClassA.selectPicBtn addTarget:self action:#selector(getSomething:) forControlEvents:UIControlEventTouchUpInside];
use selectPIcBtn instead of selectBtn
I don't know if I'm missing something because none of the other posters brought this up but from what I see selectBtn is a property of a ClassA instance, not a property of the class itself. Try grabbing an instance of a ClassA object and then accessing the property from that instance:
//WRONG
[ClassA.selectBtn addTarget:self action:#selector(getSomething:) forControlEvents:UIControlEventTouchUpInside];
//Correct
ClassA *aClassAObject = [[ClassA alloc] init];
[aClassAObject.selectBtn addTarget:self action:#selector(getSomething:) forControlEvents:UIControlEventTouchUpInside];
Please keep in mind, the above code is just an example and is not likely the object you are looking for. If you are doing this inside the ClassB object you have to grab the ClassA UIView that is actively being used by the ClassB UIViewController. Typically, I would create a property in ClassB to access the ClassA object similar to the way you created a property for a UIButton object but I'm not sure how you have your classes setup without seeing the header files.
Problem is here.
UIButton *selectBtn;
}
#property (nonatomic, strong) UIButton *selectPicBtn;
selectBtn and selectPicBtn are different. property name should be same as variable name. If you have declared a property then you don't need variable declaration.
Only declare property and use it. While initializing, initialize self.selectPicBtn = [UIButton.... in Class A