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.
Related
I'm trying this
SignUpViewController *userEmail=[[SignUpViewController alloc] init];
userEmail.emailAddress.text=email;
but is not working.
It seems like emailAddress (assuming UITextfeild) is not allocated properly when you called
SignUpViewController *userEmail=[[SignUpViewController alloc] init];
So, it is nil at the point of init.
Better way to do would be, added one public property in SignUpViewController of NSString. Save the value in that property. Like Below
SignUpViewController *userEmail=[[SignUpViewController alloc] init];
userEmail.emailString=email;
in SignUpViewController.h file add
#property (nonatomic, strong) NSString *emailString;
in SignUpViewController.m file in view did load
- (void)viewDidLoad{
//if you have not used nib or stroyboard init you textfield first
emailAddress.text=emailString;
}
Move your emailAddress #property into the .h file of SignUpViewController (Assuming you have an IBOutlet property set from Storyboard or Interface Builder
I think a better way of doing this is using a delegate to communicate between ViewControllers. See this answer for a quick example of creating a protocol for the delegate method, setting the second ViewController as the first one's delegate and then calling that method.
I have implemented a subclass of ECSlidingViewController.
InitialViewController.h
#interface InitialViewController : ECSlidingViewController
#property (nonatomic, strong) WebViewController *webVC;
#property (nonatomic, strong) MenuViewController *menuVC;
#end
I need access to the .webVC from the .menuVC, but am unable to access them from self.parentViewController.webVC getting the error:
"UIViewController does not have a member named webVC"
but when I check in the debugger
po self: <MenuViewController>
po self.parentViewController: <InitialViewController>
po self.parentViewController.webVC: error: property 'webVC' not found on object of type 'UIViewController *'
However, when I navigate the object tree of self in the local variable window, I can go
-self <MenuViewController> 0x0000001
-UITableViewController
-UIViewController
-_parentViewController <InitialViewController>
-webVC <WebViewController
-menuVC <MenuViewController> 0x0000001
Where self and self.parentViewController.menuVC have the same memory address
When I navigate down and right-click->print Description, I get
Printing description of self->_parentViewController->menuVC:
<MenuViewController: 0x8e8c720>
Those '->' and the '_' make me think I'm seriously missing something involving pointers and ivars.
I'm also interested if there is a better way to implement this functionality. This kind of smells like I'm breaking MVC with a child Controller knowing about itself and its parent. However, selections on the menu directly manipulate the webView I have loaded.
Answer:
UIViewController does not have this property built in so you need to cast it:
[(InitialViewController*)self.parentViewController webVC]
Explanation:
This is a question of Classes and SubClasses. Say I have a class MyView which is a subclass of UIView. This class has a couple methods on it, -(void)method1; and -(void)method2;. The .h would look something like this:
#interface MyView : UIView
- (void)method1;
- (void)method2;
#end
I then create a MyView* named thisView and assign it to my ViewController's view property:
#import "MyView.h"
- (void)viewDidLoad
{
MyView* thisView = [[MyView alloc] init];
[self setView: thisView];
}
The UIViewController class's property, view is declared like this:
#property (...) UIView* view;
Pay extra special attention to the UIView* there.
Because view is declared as a UIView*, it will accept values that are subclasses of UIView*, but when I access it later, it will give me a MyView in a box labeled UIView.
In other words, consider this code:
- (void)viewDidLoad
{
MyView* thisView = [[MyView alloc] init];
[self setView: thisView];
UIView* returnedView = thisView; //This is perfectly fine
}
UIViewController will return something along the lines of returnedView, which is a MyView in a UIView container.
When your program goes to access the view, all it knows is that has received something in a box labeled "UIView", so it only knows that it can run methods on it that are present in the UIView class. We have to explicitly tell it "No, this is a MyView," and we do that with casting:
[self.view method1]; //This will break
[(MyView*)self.view method1]; //This will work
Back to your problem
When you access self.parentViewController, you are given a InitialViewController in a UIViewController box, so you have to explicitly tell your program that it is an InitialViewController. You do that by casting:
InitialViewController* parentVC = (InitialViewController*)self.parentViewController;
[parentVC.webVC doSomething];
Warning:
Your VC that is accessing webVC must have a declaration of (InitialViewController*), so you'll need to watch out for forward declaration errors.
If you are unfamiliar with this, it is when Class A imports Class B, but Class B also imports Class A:
A
--->Import B
B
--->Import A
Which results in
A
--->Import B
------->Import A
----------->Import B
and so on.
A class cannot import itself.
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
I'm trying to change the alpha of an UIButton from another class. The function that is called in set the alpha property of my UIButton is actually called because I've put a NSLog there and I can see how it works. I'd be thankful if you could give me any suggestion.
Here's my current code.
ViewController.h
- (void) setAlphaToButton;
#property (strong, nonatomic) IBOutlet UIButton *myButton;
ViewController.m
#synthesize myButton;
- (void) setAlphaToButton {
myButton.alpha = 0.5;
NSLog(#"Alpha set");
}
ImageViewSubclass.m
- (void) tapDetected:(UITapGestureRecognizer *)tapRecognizer {
ViewController *VC = [[ViewController alloc] init];
[VC setAlphaToButton];
}
And when the image view is pressed, in my console I get: Alpha set. And the button doesn't change.
In your code, an instance of ViewController is alloced and inited, and the method setAlphaToButton is called on it. Then the view controller is released because you have no object retaining it. That's why you don't see any effect; the ViewController instance you call the method on never appears on screen.
It's not clear how your code is supposed to work; do you have an instance of ViewController in existence when tapDetected is called? If this is the case, and this is the ViewController whose button you want to alter the alpha of, then you need to have a reference to that instance of ViewController and call setAlphaToButton on it.
Your view is not loaded at the moment you trying to set alpha! You need to call this method after your viewDidLoad fired. You can force it by calling view, but it's kind of hackand not recommended!
MyViewController *vc = [MyViewController new];
vc.view; // this string will force view loading
[vc setAlphaToButton];
Add a property of uiviewcontroller class in imageviewsubclass as
ImageViewSubclass.h
#propery (nonatomic, retain) uiviewController *parent;
ImageViewSubclass.m
#synthesize parent;
And initialize it with "self" in view controller class when initalize object of imageviewsubclass and add on the view like
ImageViewsubclass *oneObj = [ImageViewsubClass alloc] init];
oneOBj.parent = self;
do the same for all objects of ImageviewsubClass objects.
and in
- (void) tapDetected:(UITapGestureRecognizer *)tapRecognizer {
[parent setAlphaToButton];
}
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.