Does a UIView not require its UIViewController? - ios

Playing around in Instruments, I noticed something I don't understand. I create a couple of UIViewControllers and add their views to another UIView:
CustomVC *vc = [[CustomVC alloc] initWithCustomInitializer:someParameter];
[mainView addSubview:vc.view];
By logging the memory address of the CustomVC in its init and dealloc, I see that vc is deallocated almost immediately, though the view remains on screen and everything works fine.
Does the UIView not necessarily need its controller? Or is something else going on that I'm misinterpreting?

A UIView doesn't/shouldn't retain its parent (the UIViewController), so if you drop your reference to the UIViewController and only keep the reference to the UIView, nothing keeps a strong reference to it and it will be released.
The weak reference in the UIView to its controller will be automatically set to nil.
Whether the UIView needs its "lost" controller to do its work is another story though, and entirely depending on the UIView.

UIView does not need ViewController by any means. What is happening is that you are probably not retaining pointer to VC. Pointer to view is retained by mainView.
Furthermore regardless wether you are using ARC or not. If you want to keep object in memory you need to have a strong(ARC) or retain property to it. Not to confuse you. It doesn't necessarily need to be your custom subclass. Lets say you are using UINavigationController. You can create a controller in app delegate for instance and push it to UINavigation controller. You dont need to keep a pointer to it as long as something does. This is very fundamental. You need to be clear on memory management I dont think I will be able to explain it here adequately. I would highly recommend you to check Stanford course on iOS development.
http://itun.es/ru/_zEGD

There should be only one UIViewController at a time. Adding a view that belongs to a viewcontroller is bad practice.
To answer your question, because of the above mentioned constraint (or design decision by Apple), the view is probably now retained by the other view controller, and released from vc.

Related

How to remove outside UIViews from UIViewController?

I have added multiples UIViews on outside of UIViewController and all views have week outlet connected. How can i Release memory of all view when pop to back ViewController.
First: Views (or other objects) on the top level of a xib should not have a weak kind of property in their corresponding view controller. Unlike view's in the view hierarchy, they don't have an owner after the xib is loaded and so they get deallocated anyway.
Now you seem to use ivars directly (why?), so I am actually not sure, but I don't think that makes a difference. Assuming Interface Builder accepts those as outlets and sets them, they're gone soon without an owner.
From that point of view, you've already saved memory...
Without knowing more about your project I can't tell, but the fact you're not asking for help on running into nil problems makes me guess you're taking ownership of these views somewhere else. To free them, you need to set whatever property (you are hopefully soon using properties for this) refers to them strongly to nil. ARC does the rest for you. Not using ARC? Start using it...
I would recommend to restructure this. Give the view controller (I guess that's some kind of FirstFlyerViewController) strong properties to the views (if you definitely need to have them outside the view hierarchy, otherwise, just add them as subviews somewhere). Use them, and once you pop the view controller and it gets dealloced (note that this is usually done by the framework and not yourself) they get freed along with it.

IOS where to remove subviews programmatically in ViewController

I'm quite new to IOS so I'm sorry if my question is obvious.
I have set a ViewController's view in storyboard which contains other subviews.
In viewWillAppear I update these subviews depending on the object I passed to this ViewController. This object can have nil attributes and in this case I want to remove these subviews.
What is the right place to remove these subviews and is there a difference in terms of efficiency?
viewDidLoad
viewWillAppear
or viewWillLayoutSubviews ?
and will the constraints set to these removed objects also be removed?
Thx
The constraints will definitely be removed. However, it is possible to save the constraints in an array and add them back again in the future.
I would suggest making changes to the views( orientation, visibility, geometry ) in the viewWillLayoutSubviews method. You wouldn't want to do anything expensive in the ViewWillAppear method, because at that point the view is ready to be displayed to the user and it could impact how quickly the view appears to load for the user.
If you are using Storyboard and ARC do not worry about removing your views, conversely, if you are very interested to keep your memory under very tight control then do not use Storyboard and remove ARC.
What you refer to subviews are not subviews, the methods you listed are not UIView methods, and instead are UIViewController methods. However, if you have UIView objects that you are trying to remove, then those will also be handled for you. If you want more tight control, then declare them as public ivars, wrap them in #autoreleasepool {}, and set to nil in viewWillDisappear: or other method, or via delegate or notification pattern. It's relative to what you are doing and your conditions.

Is it possible that a weak reference might be garbage collected while I am using its parent in IOS?

Say I have a parent UIView. This UIView has a weak pointer to a subview UIImageView. If UIView is currently displayed on the screen, is it possible for the image view to be garbage collected since the parent UIview only has a weak reference to the UIImageView?
FYI UIview and UIImageView would both be on the screen
This UIView has a weak pointer to a subview UIImageView
Stop. If the UIImageView is a subview of the UIView, then the UIView has a strong pointer to the UIImageView. End of story.
In other words, a view retains its subviews. As long as the subview is a subview, it cannot vanish in a puff of smoke.
Now, on the other hand, if you remove that subview, then you have to worry about its memory management or it might vanish in a puff of smoke.
You use 'weak' property on subviews when they're expected to be created and directly added to a view subviews hierarchy : UIView addSubview: already keeps a strong reference to the view.
if your view is a weak property of a UIViewController, you typically create if from NIB, or in -(void)viewDidLoad. If the controller's view is discarded because not needed anymore, your subview will be too.
When you add a subview to your view, it will, by definition, maintain a strong reference to that subview. That's just part of the addSubview internal process of maintaining view hierarchies. The view will keep this strong reference to its subviews until that subview is manually removed (e.g., via removeFromSuperview) or if the superview, itself, is removed (e.g. you dismissed its view controller).
These strong references that views internally maintain on their subviews should not be confused with the weak references that you (or IB) might add to your view or view controller subclass .h file. Those weak references are just providing you a convenient way of referencing the subview or control. The fact that your .h file has a weak reference to the the subview, such as an IBOutlet for your benefit, doesn't alter the fact that views automatically already have a strong reference to their subviews behind the scenes as part of the overall view hierarchy.
So, a subview, such as an image view will only get deallocated when its last strong reference is removed (or in non-ARC language, when the retain count falls to zero). If you've added the image view as a subview, it won't get deallocated until that strong reference is eliminated (i.e. the image view is removed from it's superview, or the superview, itself is removed). Obviously, if you're maintaining other strong references to the control, those would have to be removed, as well, for the subview to be released.
A caveat: If you're not using ARC, i.e., you're doing manual reference counting (e.g. manually calling release and autorelease), it's certainly possible for you to make a programming mistake and "over release" the image view, thereby letting the retain count fall to zero, and thus allowing it to be deallocated prematurely. But given that you're referencing weak properties in your question, you must be using ARC, so this observation is moot.
There are other situations in which sloppy use of weak variables can cause problems, but I hesitate to elaborate unless you tell us that the subview is not showing up at all.
(By the way, you mention garbage collection (GC) in your question, but I assume the real question was "is it possible that my subview might be deallocated while ...". Obviously, iOS doesn't have GC. But I assume the real question is whether your subview might be deallocated while it's still present on its superview.)
If the UIVIew has the UIImageView added to it the reference will be incremented by that action wouldn't be released until it was removed from the view.
Without knowing why you asked this I would also say that I don't think there would be any harm in having a string reference to it because at the point where the UIView is cleaned up it would also dereference the the uiimageview and it would be released then.
Also I know you said garbage collected but iOS doesn't have garbage collection. I know what you mean though

How to instantiate a particular view controller with storyboard in iOS at early stage of loading?

When using tabs with storyboard in iOS 5, some of them may take quite a long time to initialize when switching to it (for example, a tab containing GLKViewController).
This happens because an amount of work in viewDidLoad method in this controller could be very big.
Is there a way to initialize particular view controller (and call it's viewDidLoad method) defined in the storyboard at early stage - when an application starts? Having done this, the delay should be eliminated.
Are you sure it's the view controller's instantiation and not the viewDidLoad method? The view controllers are probably all created when the storyboard is unpacked, but a view controller tries to delay loading its actual view object as long as possible; viewDidLoad isn't called until the view property of your UIViewController subclass is accessed.
So a way around this could be to manually access the view property:
__unused CGRect frame = [[tabBarController.viewControllers objectAtIndex:index] view].frame;
If the slowdown is, in fact, in the instantiation and the view controller isn't being created until you switch to that tab, then you'll have do force the view controller to be instantiated by accessing it programmatically, like in the above example.
Calling the frame of the vewcontroller or the .view property will most likely work,
but i dont advice you to mess up with the viewcontroller initializations and view settings
For the following reasons
changes you make will not be standard, they will be tricks and hacks that will later on get out of hand
changes that you make will not be carried with you easily to other projects you create
If i faced a problem like this i would create the GLKViewController separately for example in the app delegate and held it there, untill the viewDidLoad gets called in the viewController, then i would move this initilized GLKViewController to the viewController

Memory management in a custom UIViewController

I'm new with iOS development, but I'm familiar with the memory management basics in Obj-C. However, Apple's docs about custom UIViewControllers confused me a bit.
So, I have a PagingController that stores an array of EntryViewController objects. (They're all UIViewControllers.) These objects are loaded dynamically and, of course, released when appropriate. The view in PagingController is created in -loadView and stored in self.view, just as the documentation said.
Whenever I load an EntryViewController (as ctrl), I call [self.view addSubview:ctrl.view];. I also need to call ctrl.parent = self; since the target OS is 3.0 and I don't want to modify a private variable (_parentViewController). (parent is defined as #property(assign) PagingController *parent;)
Here are my questions:
Do I have to release self.view myself, or is UIViewController taking care of that?
Do I have to retain parent (the property in EntryViewController)? I assume it's pointless, since all the child view controllers are being released when the parent is unloaded.
Do I have to call [self.view removeFromSuperview] in the -dealloc method of EntryViewController? The docs said, I have to manage all of the subviews, so I'm not sure if this gets called automatically.
Or am I just confused about how to create a custom view controller in the first place?
UIViewController will take care of that
You shouldn't retain parent, set the property to assign, otherwise you're gonna have a retain cycle
The view controller will take care its view, you only need to release the other subviews you are retaining (removeFromSuperview isn't necessary)

Resources