IPHONE: Test to see if a view is on the superview - iphone

I am about to do a
[vistaX removeFromSuperview];
How do I test to see if vistaX is present on the super view before removing it? Removing a view that isn't there would lead to a crash on the application...
thanks for any help.

You can guard it with:
if(vistaX.superview)
[vistaX removeFromSuperview];
Although, I wasn't aware that removeFromSuperview would fail if there wasn't a superview. Are you sure that this is the issue and it isn't maybe related to the fact that removeFromSuperview releases the view?
EDIT:
Based on your comment below, it sounds like vistaX's retain count is going to 0 the first time around and it's being freed. If you don't want this to happen, add a property to your class that retains vistaX (i.e. "#property (retain)") so you can be sure that it'll always be around.
EDIT EDIT:
Do you have a handle on the superView or one of its ancestors? If so, I would recommend setting a unique tag on the vistaX view. This can be done programmatically or through IB. Then, use the viewWithTag selector on one of the ancestors to search for the vistaX view by its unique tag.

You Can Check it By applying one condition like
if(vistaX.superview!=nil)
[vistaX removeFromSuperview];
then if superview exists, it will remove from super view, otherwise not.

Related

three20 - TTTableViewController Memory warning gives blank screen, how to fix?

This is driving me nuts. I am using three20's TTTableViewController and when I get a memory warning, the screen goes white. Now, after reading on the three20 google group is seems that the tableView got released. But, I cannot for the life of me figure out a check to see if that is the case, then create it again.
I was using the following because I thought it would fix the issue, but it seems that it doesn't satisfy the if statement:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// If we don't have a datasource we need to reset it
if (!self.dataSource) {
// Create datasource again
}
}//end
Does anyone know what to do when this happens? The google group has been no help.
Are you subclassing TTTableViewController? I haven't used it before, but assuming it's just like UITableViewController...
How does your "viewDidUnload" look like? Are you releasing the tableview here? If so, you need to create tableview in viewDidLoad to match it.
No need to check if dataSource is available in viewDidAppear, because if you read View programming guide, it explains that memory warning will call "viewDidUnload" to give you a chance to clean up data that are created in "viewDidLoad".
i had the same issue and it drove me crazy as well.
Nobody mentions it in the three20 docs, but you shouldn't use UIViewController's initWithNibName function to add subviews. If you do, a memory warning will release these subviews.
Try to move your code from initWithNibName function to viewDidLoad function. I have noticed that some code need to be kept in the initWithNibName, such as navigation styles. However, any subviews added to the controller's view should be in the viewDidLoad function.
In general you should be careful to set up views in viewDidLoad rather than the class constructor. For instance, you should set up your launcher view in viewDidLoad rather than the constructor of your launcher view controller, otherwise your launcher will become empty after a memory warning.
In the case of TTTableViewController however this does not (usually) apply because you don't set up the table view manually. I had the same problem you had, and eventually tracked it down: I had redefined viewWillDisappear: and forgot to call [super viewWillDisappear:animated]. This meant that some of the flags that the Three20 controller maintains about the state of the view were not updated correctly.
I also found that it was beneficial to redefine didReceiveMemoryWarning to call [self setEditing:NO] before calling super; I found that the state of the table view got confused otherwise (this is not relevant if you don't use edit mode for your table).
Finally, there is a bug in Three20 which means that tables in loading/empty/error mode will not be restored properly; see a discussion in the blog post by TwoCentStudios and a proposed fix on github.

cocoa - quickly release all IBOUtlets

I have a view with many retained IBOutlets, loaded from a XIB.
I have read that they have to be released when the controller's dealloc method is called.
May I use a cycle to do this(also to avoid releasing each outlet separately)?
something like
for(UIView *v in self.view.subviews){
[v release];
v=nil;
}
?
also, after that, should I release the view as well?
That would only make sense if you've actually retained every single subview, and even then it seems like asking for trouble -- if you ever wanted to change your .xib, you'd have to remember to update you code as well. And there may also be non-view objects in a nib that can be connected to outlets, like view controllers.
There are only so many views you can fit on an iPhone- or iPad-sized screen, so it's hard to imagine that you have more than a few dozen outlets. I think the prudent thing to do here is to simply release each one separately. This is what and iOS developer would expect to see, and it won't be any slower than using a loop. It'll be more code, yes, but the code will be easy to understand.
self.view is automatically released on UIViewController deallocation, and subviews also, if not retained by your code.
You should re-read the chapter on memory management in Apple Documentation... ;)
I wrote like a releaseVars function, which takes address of variables, release them and set to nil. This save some lines of code, but still you have to manually take care of them.

Adding subview then releasing it: "modifying view that is being finalized"

I've got a UIButton called tagButton and a UIScrollView called tagsView.
Inside my -(void)renderTags method, I do
[[self.tagsView subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
...to clear the decks, then I walk through a pair of arrays called allTags and activeTags, alternately creating "lit" and "unlit" buttons for each tag the user has ever used in the app. So far so good. But when I add the newly created UIButton to my view, thusly:
[self.tagsView addSubview:tagButton];
[tagButton release];
...the first time, nothing happens on the view, the tag button doesn't show up. The second time I put that same string in (which fires -toggleTag rather than -createTag, but ends up in the same rendering method), I get the console message modifying layer that is being finalized = 0x82b3ec0.
If I comment out [tagButton release], though, everything works. So, what gives? I thought adding a subview to a superview made the superview retain it. I'm not going to deal with this button again except to tell it to remove itself next time I render my tag list, so it seems like the view controller ought to release it.
Your problem is probably that you arent retaining tagButton to begin with, therefore there is no need to release it...hope that helps

iphone basic release question

When i add a new subview, i cant immediately release the controller after displaying. How should i release this viewController?
I was thinking about using a property for the viewController, and use delegation to notify for removing the view and releasing it?
Is this the best way to do it? or should i do something with autorelease?
Ton.
I'm going to have a shot at answering this rather vague question. I think what you are doing is creating a new subview and then releasing it. What you need to do is add it to your main view. Something like:
[myView addSubview.newSubview];
Once you have done this myView owns the subview and you can release it without hassles.

How to detect when a UIView has changed size?

I have a UIViewController that is initialised with a correct frame, however somewhere in my code the frame gets mangled and I'm having difficulty finding out where.
In situations like this it is usually handy to watch a variable in the debugger, however I have no way of accessing the controller->view->frame property in my variable view, since it isn't a variable, it's a property (surprisingly enough)
Drilling into the UIView in the variables display shows a few things but nothing I can relate to the frame, I thought perhaps that would be in layer but it isn't.
Is there any way to watch for changes in a private API? I guess not, since the variables are essentially 'hidden' and so you can't specify exactly what to watch.
Alternatively, what other approach could I use? I already tried subclassing UIView, setting my UIViewController's view to point to this subclass and breaking on the setFrame method but it didn't seem to work.
EDIT: the subclassing UIView method DID work, I just had to set the view to point to my test subclass in viewDidLoad and not the init method. Leaving this question open as I'm not sure if this is the best way of approaching this kind of problem...
Subclass your the view you want to track and rewrite the setFrame method:
#implementation MyTableView
- (void)setFrame:(CGRect)frame;
{
NSLog(#"%#", frame);
[super setFrame:frame];
}
#end
Then use the debugger to add a breakpoint to it and check when it gets called. Eventually, you'll see when the frame gets changed and where does the change comes from.
I discovered this can be done using key value observers.
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html
You could create an ivar, view2, and just assigned it to your view in your loadView method. That should enable you to watch it like a normal variable.