iPhone SDK Managing Memory for Multiview app - iphone

I have an app that programmatically creates labels and text fields based on the contents of a text file. Whenever the view controller is loaded, it creates text fields and labels that are different each time. My problem is I need to clear out the labels and text fields without releasing the view controller since I need to keep track of the view controller. I tried self.viewController = nil, but I'm pretty sure this results in a memory leak. Is there a way to delete all the subviews of a view?

What Greg meant to say is this:
for (UIView *subview in self.view.subviews) {
[subview removeFromSuperview];
}
This may not work as you would expect though, as Objective C doesn't like it when you modify an array while you're iterating through it in a for loop. A safer choice would be this:
while ([self.view.subviews count] > 0) {
[[self.view.subviews lastObject] removeFromSuperview];
}

If you have a view named view, you should be able to remove all of the subviews from the view using this code:
for (UIView *subview in view) {
[subview removeFromSuperview];
}

Related

Adding views lazily in UIScrollView slowing down App

I am trying to implement a view with a mainScrollView. Inside that mainScrollView I have 10 UIView, each one is having subScrollView.Now, I want to add many (around 150 to 200) views(imageview,label,textview,uiview,webview,etc) inside each subScrollView.
something like this:
Timeline ww2 and
History of Jazz
I have tried following:
Method 1:
Lazy loading for each subScrollView to add views.
code for this:
-(void)loadInnerScrollViewLazily:(int)tag pageNo:(int)pageNo{
/// this array will contain all the views for subScrollView
NSMutableArray *array=[NSMutableArray array];
array=[self.tlScrollContentArray objectAtIndex:tag];
if (pageNo < 0)
return;
if (pageNo >= [array count])
return;
UIView *controller = [array objectAtIndex:pageNo];
CGRect frame = [[array objectAtIndex:0] frame];
frame.origin.x = 350;
frame.origin.y = 0;
controller.frame = frame;
for (UIView* view in [mainScrollView subviews]) {
for (UIScrollView* scroll in [view subviews]) {
if ([scroll isKindOfClass:[UIScrollView class]]) {
if (scroll.tag == tag+11) {
[scroll addSubview:controller]; /// adds view in particular subScrollView
}
}
}
}
}
This method is called in scrollViewDidScroll method, which checks perticular scrollView and removes view which is out of screen and then it will add views depending upon the condition.
This code is slowing down app as scrolling rate increases.
Method 2:
With the reference of this tutorial:
Add three UIView(each with subScrollView) in to mainScrollView. Updating content of subScrollView depending upon the condition.
But this solution is also slowing down my app as it is updating subScrollView every time it appears.
Is there any library or code available to manage this.
Any help will be appreciated.
Thanks in Advance!
I think your code has many, many errors, and you would need to post your complete source to be helped. It's unclear if you are ever removing images from your scrollview. If not, that is your problem.
Look at Apple's sample PhotoScroller code: http://developer.apple.com/library/ios/#samplecode/PhotoScroller/Introduction/Intro.html
This dequeues and manages the ImageViews on the scrollview... I implemented something similar based on this.

How can I have a UISegmentedControl swap views in and out, AND still have the ability to rotate orientation?

I have looked around at a number of posts on this topic, but have been unable to fix the issues I am having. I am presenting a modal view that is a UIViewController. I've setup that view to have a UISegmentedControl on the top right that will ideally allow me to switch the view (inside of this modal view).
In order to not cover up my toolbar at the top, I have made a simple UIView in IB, and laid out the dimensions so they don't overlap the toolbar. Now my thinking is that if I add the view I want to add to the UIView when the UISegmentedControl is selected, life will be great:
-(IBAction) indexDidChangeForSegmentedControl:(UISegmentedControl*)seg{
int selectedNum = seg.selectedSegmentIndex;
if([[self.view1 subviews] objectAtIndex:0] != nil){
[[[self.view1 subviews] objectAtIndex:0] removeFromSuperview];
}
if(selectedNum == 0){
[self.view1 addSubview:[(DialogInfo*)[viewsArray objectAtIndex:seg.selectedSegmentIndex] view]];
}else if(selectedNum == 1){
[self.view1 addSubview:[(DialogMetadata*)[viewsArray objectAtIndex:seg.selectedSegmentIndex] view]];
}else if(selectedNum == 2){
[self.view1 addSubview:[(DialogVersions*)[viewsArray objectAtIndex:seg.selectedSegmentIndex] view]];
}else if(selectedNum == 3){
[self.view1 addSubview:[(DialogAssoc*)[viewsArray objectAtIndex:seg.selectedSegmentIndex] view]];
}
}
And that works! But the problem is that when I rotate the device, the view that I really care about, the inner one, won't spin.
I have tried not doing this outer parent UIView approach, and just tried setting the view controller view with a certain frame, but the orientation is still messed up.
I have also tried doing this with a UINavigationController, and just not animating the transition, but I can't get that to work correctly.
So my question is: What do I do?! All I want is to be able to switch between views with a UISegmentedControl and be able to rotate the device to any orientation I need. I've thought through this so much and tried so many different things that I feel like I don't have a clue what is happening anymore.
Thank you for your help
Well it turns out after poking around some more that my resize mask wasn't set properly in IB. DOH!

Positioning A Button

How can I position a button on my view dynamically?
Try this code
for(UIView * view in self.view.subviews)
{
if([view isKindOfClass:[UIButton class]])
{
// view is button
}
}
You can also use tags
Set the tag property of the UIButton (e.g. in interface builder, or programatically). Then you can walk the children of the owning view:
for (UIView *view in myView.subviews) {
if (view.tag == 101 /*or whatever you set it to*/) {
// things...
}
}
Ok, now we understand the question better...
You can place a button/UIComponent at runtime by settings its frame. This will place it at a given coordinate within the view containing the button.
myButton.frame = CGRectMake(newX, newY, myButton.frame.width, myButton.frame.height);
If you wish to do a linear style animation (no curves), look up CATransitions, see iPhone UIView Animation Best Practice. If you need to support pre-iOS4 devices, you can't use CATransitions, and have to do it the old way using UIView animations.
To do more complex animations, you might have to mess around with timers, which can slightly juddery effects if you're trying to do complicated animation paths.
Get a array of all the subviews of a view using:
[myView subviews]
iterate through that array and check for your butotn by some unique characteristic. (You can set the button's tag attribute to some unique value and check for that value)

Properly zooming a UIScrollView that contains many subviews

I created a zoomable UIScrollView and added 100 subviews to it (tiled). The view scrolls perfectly left and right. However, I'd like to allow zooming.
To do so I read that my delegate needs to implement:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return ???;
}
I have seen examples that have only one subview to zoom, so they return that subview in that method. In my case, however, I have a lot more. What is the proper way to do the zooming?
I tried creating another UIView and adding the 100 subviews to that one. And then return that one view on the method above, but I doesn't work (it zooms but once it stops, it's not interactive any more).
Exactly,
This is what Apple also is mentioning in the Scroll View Programming Guide:
Just create a view, add all subviews to this view and add the newly created view as a single subview to the scrollview...
Then in the viewForZoomingInScrollView delegate method return the object at Index 0:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return [self.scrollView.subviews objectAtIndex:0];
}
I created the view where I added everything using:
UIView *zoomableView = [[UIView alloc] init];
without setting its frame.
The problem was solved when, after adding all the subviews to it, I set its frame to something large enough to accommodate all the tiled subviews.
You have to return what your going to add views to scroll view as a subviews.
Ex: If you are adding image view to scroll view then write
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return imageView object;
}

iPhone + clear all UI Controls from View

I have a view in which I have few labels and I want to dynamically clear the view (remove all the labels) at certain condition in my application.
Please help me
Regards,
Pratik
Your most logical option is to use a separate view for the next stage of your interface rather than changing them out, maybe using UIViewControllers.
If you really want to do this, though:
for (UIView *v in myView.subviews) {
// Include the if-statement if you want to remove UIControls only
if ([v isKindOfClass:[UIControl class]]) {
[v removeFromSuperview];
}
}