Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Is it possible that you are getting <code>EXC_BAD_ACCESS</code>? Is it possible that the app is crashing because <code>tabsView</code> is deallocated when you send <code>isDescendantOfView:</code> to it. If you run with breakpoints enabled it should tell you the reason for the crash. If it is an <code>EXC_BAD_ACCESS</code> problem you should try <code>NSZombie</code>.</p> <p>To activate NSZombie do the following:</p> <ol> <li>Get info of the executable.</li> <li>Go to the arguments tab.</li> <li>In the "Variables to be set in the environment:" section add:</li> </ol> <p>Name: NSZombieEnabled Value: YES</p> <p>Then run your app as usual and when it crashes it should tell you which deallocated object received what message.</p> <p><strong>EDIT:</strong> Just saw your edit. I think I nailed it. You're autoreleasing the views when you create them, so when they are removed from their superviews they are no longer retained and thus deallocated. You're app crashes because you're trying to run methods on deallocated views.</p> <p><strong>EDIT 2:</strong> Thought I should tell you that there is a better solution than the one posted by Praveen S.</p> <p>Change your code as follows:</p> <pre><code>[tabsClippedView release]; tabsClippedView = [[UIView alloc] initWithFrame:tabsClippedFrame]; </code></pre> <p>and</p> <pre><code>[tabsView release]; tabsView = [[UIView alloc] initWithFrame:tabsFrame]; </code></pre> <p>The above code does the same thing as the code posted by Praveen S, but without the autorelease. An autorelease is more expensive than a regular release and should only be used when needed and in this case it isn't.</p> <p>Rather than releasing before you allocate a new view you probably want to release the view when you're done with it:</p> <pre><code>[tabsView removeFromSuperview]; [tabsView release]; tabsView = nil; </code></pre> <p>or simply</p> <pre><code>[tabsView removeFromSuperview]; self.tabsView = nil; </code></pre> <p>and then instead of:</p> <pre><code>if ([tabsView isDescendantOfView:tabsClippedView]) ... </code></pre> <p>you can use:</p> <pre><code>if (tabsView) ... </code></pre> <p>As you might have noticed, there really is no need for you to retain the view. You could just as well do the following:</p> <pre><code>tabsView = [[UIView alloc] initWithFrame:tabsFrame]; [tabsClippedView addSubview:tabsView]; // This retains tabsView [tabsView release]; </code></pre> <p>and then to remove the view you would use:</p> <pre><code>[tabsView removeFromSuperview]; // This will release the tabsView tabsView = nil; </code></pre> <p>Also remember to set the views to nil in <code>viewDidUnload</code>.</p> <p><strong>EDIT 3:</strong> Why self made such a difference:</p> <p>What you need to understand is how properties and reference counting works. There are books and such you could read about it. I'm sure Google can provide you with some good references as well.</p> <p>The difference between</p> <pre><code>self.tabsView = [[UIView alloc] initWithFrame:frame]; </code></pre> <p>and</p> <pre><code>tabsView = [[UIView alloc] initWithFrame:frame]; </code></pre> <p>is that <code>self.tabsView</code> is accessing the properties setter, while <code>tabsView</code> is accessing the instance variable directly.</p> <p>A nonatomic, retain property's implementation looks something like the following:</p> <pre><code>- (void)setTabsView:(UIView *)view { if (view != tabsView) { [tabsView release]; tabsView = [view retain]; } } </code></pre> <p>So the property is taking care of the memory management for you. In my solution I take care of the memory management myself and thus I don't need the property to do it for me, so I don't use it.</p> <p>I hope this explains why self made such a difference.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload