If I know a UIView has been added to a parent, is there a native way to access the parent from within the child?
eg.
[self parent] // returns parent UIView
Sure: UIView has the superview property.
You could try UIViews property superview
[self superview]
in the Childs .h create a property for the parent:
ParentView *parentView;
#property (nonatomic, retain) ParentView *parentView;
(make sure to #synthesize your property in Childs .m)
then, when you alloc an instance of child imediatly asign self to the parentView property
in Parent .m:
Child *child = [[Child alloc] init];
[child setParentView:self];
then you can access the Parent view from the Child with:
[self parentView];
Related
In ARC, I want to release the custom view added to parent view and array.
#property (nonatomic, weak) IBOutlet UIScrollView* panelScroll;
#property (nonatomic, retain) NSMutableArray *medsSectionViews;
Above are the two properties in which a customview object is added as below:
CustomView* newView;
newView = [[CustomView alloc] init];
[panelScroll addSubview:newView];
[self.medsSectionViews addObject:newView];
newView = nil;
Its not releasing the object. What is the problem? How can I achieve it? Please mention the reference count at required points.
CustomView *newView = [[CustomView alloc] init]; // 1 owner (the newView local variable)
[panelScroll addSubview:newView]; // 2 owners (local variable, the superview panelScroll)
[self.medsSectionViews addObject:newView]; // 3 owners (local variable, superview, array medsSectionViews)
newView = nil; // 2 owners (superview, array)
now
[array removeAllObjects]; // 1 owner (superview)
[newView removeFromSuperview]; // 0 owners
// view gets deallocated because it has no owners
Some method will retain object:
In your code:
1. addSubview:
2. addObject:
retain your view;
so your just need:
[array removeAllObjects];
[newView removeFromSuperview];
and why newView = nil can't release view ?
Because In ARC it's use Reference counting to management object life cycle.
Your newView variable appears to be a local variable. As soon as that goes out of scope it will release it's strong reference to your view. Thus you don't really have to set it to nil.
You have 2 other strong references:
Arrays maintain strong references to their contents.
When you add a view to a superview, the superview holds a strong reference.
If you want it released, you need to both remove it from the array and remove it from it's superview. Note that it will then be deallocated.
I have main view controller that contain an NSMutableArray. I want to open a subview with stepper to change quantity of a product included in that NSMutableArray.
How can I access to the NSMutableArray from subview and change an object inside it?
In your SubView class make a property of class NSMutableArray as
#interface SubViewClass : UIView
#property (strong, nonatomic) NSMutableArray *array;
#end
Now in your main view controller when calling this SubView you can assign your NSMutableArray instance into SubView array;
subViewInstance.array = mainControllerArray;
Now you can modify this array the way you want in your SubView Class.
Create a modal class. Then assign all the data to it and access that modal class from your other subview class.
I have two UIView contained in a UIViewController - firstView and secondView - that I initialize pragmatically. I have a UILabel in the firstView, and a UIButton in the secondView. I would like the button in the second view to change the label in the first view. In the implementation file of the second view I have the following code:
- (void) changeLabel: (UIButton *) sender{
firstView *view = [[firstView alloc] init];
view.label.text = #"Changed Text";
}
However I figured out that the above method just initializes a new class of firstView and does not link to the existing UIView. How can I change properties of firstView from within secondView?
Create properties in your view controller's header file for the views:
#property (nonatomic, retain) UIView *firstView;
#property (nonatomic, retain) UILabel *label;
When you create the view and label assign them to the properties:
self.firstView = // create your view here
self.label = // create your label here
Create a button property on your UIView object so you can access it later:
#property (nonatomic, retain) UIButton *button;
Then in your view controller file, when you create everything, access the view's button property and add a target, like this:
[firstView.button addTarget:self action:#selector(changeLabel) forControlEvents:UIControlEventTouchUpInside];
Then you can simply have the method your button calls be like this:
- (void)changeLabel {
self.label.text = #"Changed Text.";
}
I prefer to create custom views for all my view controllers. And I define it in code by using weak references for custom views like this:
#import "MyViewController.h"
#import "MyCustomView.h"
#interface MyViewController ()
#property (nonatomic, weak) MyCustomView *customView;
#end
#implementation MyViewController
- (void) loadView
{
MyCustomView *view = [MyCustomView new];
self.view = view;
self.customView = view;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// work with custom view
self.customView.tableView.delegate = self;
....
}
#end
Is this the correct use of weak references? Will the application crash or leak, or will there be other problems?
In this case weak is fine. You assign your CustomView to self.view which is defined in the UIViewController header as
#property(nonatomic,retain) UIView *view;
so the view property has a retaining reference.
There is a possibility that your view and customView could get out of sync - so I would be tempted to define customView as readonly and implement the getter as
- (CustomView *)customView
{
return (id)self.view;
}
As you can see in the documentation of UIViewController the view controller's view property has a strong reference to the view. So the custom view object will be retained as long as you don't set the view property to something else. In short, your method works.
As you create the instance from within this controller programatically, you should use a strong reference to set the ownership clearly to this controller.
In the event that you create the view object in IB or soryboard respectively, then a weak reference to the related IBOutlet would do.
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];
}