iphone/ipad adding adding and removing a subview doesnt work - iphone

Im have a slight amount of trouble adding a new view to my scene, I have the code like this:
- (void) showMyDayView {
NSLog(#"My Day View was touched");
MyDayViewController *temp = [[MyDayViewController alloc] initWithNibName: #"MyDayView" bundle:nil];
self.myDayViewController = temp;
NSLog(#"superview: %#", [[self mainNavView] superview]);
[[self mainNavView] removeFromSuperview];
NSLog(#"after removal main: %#", [self mainNavView]);
NSLog(#"after removal view: %#", [self view]);
NSLog(#"after removal superview: %#", [[self view] superview]);
[[[self view] superview] addSubview: [self.myDayViewController view]];
[temp release];
}
And when I run this code, the console says "after removal superview: (null)"
so when I add the subView to the superview, nothing happens because the superview is null.
Any ideas?
Thanks
Mark

If you want to reuse a view that you are going to removeFromSuperview, you must retain it first. removeFromSuperview releases any view it is invoked on.
So...
[[self mainNavView] retain]
[[self mainNavView] removeFromSuperview];
And [self mainNavView] remains safe to use.

Related

How can create pop up table that is compatible with ios4?

I'm doing a testing stuff. I'm making a pop up table (PopUpViewController, UIViewController) that trigger by UI button through below code. It work fine.
ThirdViewController.m
-(IBAction)onClickPopUpView:(id)sender{
popUpViewController=[[PopUpViewController alloc]initWithNibName:#"PopUpViewController" bundle:nil];
[self.view addSubview:controller.view];
[self addChildViewController:controller];
[controller didMoveToParentViewController:self];
}
PopUpViewController.m
- (IBAction)close:(id)sender
{
[self willMoveToParentViewController:nil];
[self.view removeFromSuperview];
[self removeFromParentViewController];
}
That code work for ios5 or later. I wonder how can do some effect that is compatible with ios4. Does anyone give me hint?

memory leak on dealloc

I am new to iPhone Development.
I have taken UIView,UIImageView,UIScrollView etc in my NIB File.
My question is that can i remove all that views from SuperView ?
For Example:`
-(void)dealloc
{
[super dealloc];
[imageView removeFromSuperview];
[View1 removeFromSuperview];
[View2 removeFromSuperview];
[ScrollView removeFromSuperview];
[imageView release];
[View1 release];
[View2 release];
[ScrollView release];
imageView = nil;
View1 = nil;
View2 = nil;
ScrollView = nil;
}
please help me.Thanking you...
You need to call [super dealloc]; as the very last thing, not first. That's because [super dealloc] cleans up your object, and accessing instance variables afterwards is undefined behavior: anything can happen. For example, [super dealloc] could set all instance variables to nil, in which case the following release calls simply have no effect (and thus cause leaks). Also, there's no need to set the instance variables to nil since you're not going to use them anyway. So all you need is:
-(void)dealloc
{
[imageView release];
[View1 release];
[View2 release];
[ScrollView release];
[super dealloc];
}
A few more notes: the removeFromSuperview calls are harmless but unnecessary, this is implicitly done by [super dealloc]. And you should stick to Apples naming conventions which in your case means you shouldn't start variable names with uppercase letters. So it should be scrollView instead of ScrollView.
No need to remove those subviews from superview, since anyhow you are going to release the superview itself.
You can make the dealloc as follows.
-(void)dealloc{
[imageView release];
[View1 release];
[View2 release];
[ScrollView release];
imageView = nil;
View1 = nil;
View2 = nil;
ScrollView = nil;
[super dealloc];
}
Note that [super dealloc] is at the end (More info).
You might want to enable ARC in your projects. You won't need to release these objects anymore; the system will take care of (most of) your memory-management.
You can read more about ARC here: http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html

UIActivityIndicatorView not working when added to UITableView

I'm trying to add a UIActivityIndicatorView to the center of my UITableView while it waits for the UITableViews data to load. I am doing this as follows:
UIActivityIndicatorView *activityIndicatorTemp = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhiteLarge];
[activityIndicatorTemp setCenter:[[self tableView] center]];
[self setActivityIndicator: activityIndicatorTemp];
[activityIndicatorTemp release];
[[self tableView] addSubview:activityIndicator];
[activityIndicator startAnimating];
However the activity indicator is not showing up at all when I launch the code. I'd like to do it programmatically, any suggestions on how to fix this or why it isn't working?
please move
[activityIndicatorTemp release];
after addSubview:
[[self tableView] addSubview:activityIndicator];
The problem here is when I was setting the location of the activityindicator. I did this before the tableview had been initialized.
[activityIndicatorTemp setCenter:[[self tableView] center]];
I removed the above and it worked.

how to know which viewController when subview is removed

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
[[self model] setTransitioning:NO];
[[[[self view]subviews] objectAtIndex:0] removeFromSuperview];
}
How can I tell what kind of viewController controls the subview at index 0?
If it's a QuizViewController I need to call a function on it.
Thanks in advance.
Good answers. I don't believe I explained enough. This is a all in a view controller that is a view stack. The view controller adds and deletes views manually with an animated transition. I am not using a navigationController and cannot in this particular instance for other reasons.
Sometimes the views I add are simple UIImageViews. Sometimes they are QuizViews. The QuizViews have a QuizViewController because they need internal functionality. Here are the two functions I use to add the views.
- (void)loadQuiz:(NSInteger )quizNum
{
if([self quizViewController] != nil)
{
[self setQuizViewController:nil];
}
QuizViewController *quiz = [[QuizViewController alloc] initWithNibName:#"QuizViewController" bundle:nil];
[quiz setUp:quizNum];
[self setQuizViewController:quiz];
[quiz release];
[[self view] addSubview:[[self quizViewController]view]];
[self setSlide1:[[[self view] subviews] objectAtIndex:0]];
[self setSlide2:[[[self view] subviews] objectAtIndex:1]];
[[self slide1] setHidden:NO];
[[self slide2] setHidden:YES];
[self performTransition];
}
- (void)loadImage:(NSString *)slideImage
{
UIImage *tempImg = [UIImage imageWithContentsOfFile:[Utilities localPathForFileName:slideImage]];
UIImageView *temp = [[UIImageView alloc] initWithImage:tempImg];
[[self view] addSubview:temp];
[temp release];
//[topView release];
if ([[[self view]subviews] count] > 2) {
//add the 2nd subview
//[[[[self view]subviews] objectAtIndex:0] removeFromSuperview];
}
[self setSlide1:[[[self view] subviews] objectAtIndex:0]];
[self setSlide2:[[[self view] subviews] objectAtIndex:1]];
[[self slide1] setHidden:NO];
[[self slide2] setHidden:YES];
NSLog(#"%s %d",__FUNCTION__,[[[self view]subviews] count]);
[self performTransition];
}
So my question is still, in the animationDidStop function how do I detect if it's a quiz?
if ([[self view]subviews] objectAtIndex:0] isKindOfClass:CLASS(class))
...
or isMemberofClass
From memory so you'll have to test it out...
You can also set a tag on the view when you create it, then look for the view when you retrieve it.
someUIView.tag=99;
then
if ( [[self view]subviews] objectAtIndex:0].tag == 99 )
...
Cheers
You maintain one UIViewController (for e.g. UIViewController *currentViewController) object for keeping the track of current view controller.
Now before pushing to the viewcontroller which according to my understanding gets pushed by more than one view controller,you set the currentViewController with the viewController from which you are pushing.
So if you are in QuizViewController and pushing to viewController which controlls subviews,you first set currentController of it and then push it.
subViewController.currentController = self;
[self.navigationController pushViewController:subViewController animated:YES];
Views don't inherently have view controllers attached to them, so the way your question is worded doesn't quite make sense. If what you're doing is having a UIView subclass, say QuizView, as a subview and need to know when that is being removed and act on it, then the code would look like this;
-(void) animationDidStop:(CAAnimation*)theAnimation finished:(BOOL)flag
{
[[self model] setTransitioning:NO];
UIView *subview = [self.view.subviews objectAtIndex:0];
if([subview isKindOfClass:[QuizView class]])
{
[(QuizView*)subview yourFunction];
}
[subview removeFromSuperview];
}
If you mean something different and you can provide some code I might be able to help more, but like I said your original question isn't quite clear to me if this isn't what you mean ;)

Memory management, release needed?

I wonder if someone could quickly help me with the following, do I need to add a [myTableView release]; after I call [view addSubview:[self myTableView]]; ? Initially I was thinking no, and running it through CLANG produced to memory warnings
Here is my thinking:
[self setMyTableView:tempTableView]; retainCount = (+1)
[view addSubview:[self myTableView]]; retainCount = (+2)
//[myTableView release]; << HERE retainCount = (+1)
-dealloc [myTableView release]; retainCount = ( 0)
.
#property (nonatomic, retain) UITableView *myTableView;
.
- (void)loadView {
NSLog(#"%s", __PRETTY_FUNCTION__);
[self setTitle:#"Location Data"];
CGRect viewFrame = CGRectMake(0, 20, 320, 460);
UIView *view = [[UIView alloc] initWithFrame:viewFrame];
CGRect tableFrame = CGRectMake(0, 0, 320, 416);
UITableView *tempTableView = [[UITableView alloc] initWithFrame:tableFrame];
[self setMyTableView:tempTableView];
[tempTableView release];
[view addSubview:[self myTableView]];
//[myTableView release]; << HERE
[[self myTableView] setDelegate:self];
[[self myTableView] setDataSource:self];
[self setView:view];
[view release];
}
.
- (void)dealloc {
[myTableView release];
[dataModel release];
[super dealloc];
}
EDIT: hmm maybe I don't as [view addSubview:[self myTableView]]; retains it and will release when done. Your right Carl, my bad. I was getting confused with: alloc, set, release, when this is simply the view taking ownership (and the responsibility to release that later)
You're right when you say that [view addSubview:[self myTableView]]; will retain your table view, but since it's the view who is retaining it, it's the view that is supposed to release it. And it will, when the view gets dealloc'ed. You only have to release what you retained yourself, i.e., you only have to release the table view once in your dealloc method.
Your method doesn't retain myTableView, so it shouldn't release it.