when the following event gets executed, i initialize and call a UIImageView.
Later on i will remove this view. My code is as follows;
self.myView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 320, 460)];
[myView setBackgroundColor:[UIColor whiteColor]];
self.myView.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"someImage.png"]];
[self.tableView addSubview:self.myView];
At a later instance i will remove the view, and my code for removing is as follows;
[self.tableView bringSubviewToFront:self.myView];
[self.myView setHidden:YES];
[self.myView removeFromSuperview];
The problem i am having is that, the view that i added to the tableview, is not getting removed. I need to know why this is hapenning, and a programatic solution to solve it.
note: i have debugged, and the remove part of the code gets executed but nothing gets removed. Help
A common issue that can cause behavior like this is modifying UIKit objects (like UIViews) from a background thread. UIKit is not generally threadsafe and calls from background threads will often not change the visible state of your app for a long time, if at all.
What is the method that executes your second block of code and how does it get called?
FWIW, bringSubviewToFront: and setHidden: should be unnecessary; removeFromSuperview should be all that is required to remove your view.
Was wondering if there is another controller on top of your tableview like a navigationcontroller. Would removeFromSuperview actually refer to it giving an unwanted result?
you should try only [self.myView removeFromSuperview];
Related
I am currently working on an application that has some ViewController with a button on it that pushes to a UITableViewController with Search Bar and Search Display controller. I have some data in the cells and that gets populated. I have added the following code to hide the search bar and also make it clearcolor when you do see it:
[[self.searchBar.subviews objectAtIndex:0] removeFromSuperView];
[self.searchBar setBackgroundColor:[UIColor clearColor]];
CGRect newBounds = [[self tableView]bounds];
newBounds.origin.y = newBounds.origin.y + searchBar.bounds.size.height;
[[self tableView] setBounds:newBounds];
Now this works when I am using the iOS simulator, but when I run it on my device and begin to scroll, either up or down, it crashes and gives me the following error:
EXC_BREAKPOINT (code = EXC_ARM_BREAKPOINT, subcode = 0xdefe)
I then enabled Zombie Objects to further debug and got this:
-[UIView frame]: message sent to deallocated instance 0x156b1430
When I take off:
[[self.searchBar.subviews objectAtIndex:0] removeFromSuperView];
[self.searchBar setBackgroundColor:[UIColor clearColor]];
and run my application on my device again, it does not crash and works fine.
Anyone have any ideas whats going on and how this is happening? Thanks in advance!
[[self.searchBar.subviews objectAtIndex:0] removeFromSuperView];
//This Line remove search bar from view ,which means it is deallocated at that moment so when you again try to remove it ,,the app crash ..
// So,instead of this try to hide searchbar ,,
Self. searchBar.hidden =YES;
I think UISearchBar has unsafeunretained reference of [self.searchBar.subviews objectAtIndex:0];
And You set the Bounds of UITableView then change frame of UITableView.
It would fire auto resizing and layoutSubviews.
So, UISearchBar's layoutSubviews method access [self.searchBar.subviews objectAtIndex:0].frame
for layout or auto resizing.
It's not recommended that change view in UIControls from SDK.
There is an idea that Setting hidden=YES instead removeFromSuperview.
I was having this same problem. Got to this page, read the words 'zombie objects' in the question and remembered that I'd left zombie objects enabled. After disabling them, the problem went away. Now when I scroll my tableView, there's no crash.
This may be weird, but perhaps it will help someone...
I'm doing a cool CA3DTransform while a UIScrollview is scrolling in the scrollViewDidScroll delegate method. It works perfectly when you use your finger to scroll, so when scrolling manually everything is perfect.
But, when I set scrollview contentoffset programmatically like:
[scrollView setContentOffSet:CGPointMake(0,460) animated:YES];
It still calls the delegate method scrollviewdidscroll, so the same animation methods are called, so I still see the correct animation, BUT, somehow parts of the view are missing during and after the animation! I've tried to set the layer.zPosition on all things and it doesn't seem to help. It should be fine since manually scrolling does work without parts of views going missing... Somehow calling this method programmatically differs and I have no idea why!
Post your question in this way is not very clear, considering that with the delegate scrollViewDidScroll, I can print me the code, either manually or programmatically.
...
UIScrollView *sv = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 10, 320, 200)];
[sv setContentSize:CGSizeMake(640, 200)];
sv.delegate = self;
[sv setContentOffset:CGPointMake(320, 0) animated:YES];
[self.view addSubview:sv];
...
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(#"---%#---", NSStringFromCGPoint(scrollView.contentOffset));
}
In this simple example, you can see that the delegate actually works.
Excuse the simplicity of the answer, but the only question you ask is hard to give you help.
I had a similar problem (in the context of using a scrollview for a slideshow) but solved it by using scrollRectToVisible:NO (NO for no animations), and wrapped that inside a UIView animation block where I also put my animation code.
I have a problem with the animation. At start, everything is smooth. However, when the application runs for a certain period of time (around 10 min) then the animation lags.
Here is the code in viewDidLoad:
[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:#selector(updateImage) userInfo:nil repeats:YES];
And in -(void)updateImage: //image fade in
[aSubview release];
[aSubview removeFromSuperview];
aSubview = [[UIImageView alloc] initWithFrame:CGRectMake(28, 64, 265, 284)];
aSubview.image = [slideShowArray objectAtIndex:randNum];
[aSubview setAlpha:0.0];
[UIImageView beginAnimations:NULL context:nil];
[UIImageView setAnimationDuration:2.0];
[aSubview setAlpha:1.0];
[UIImageView commitAnimations];
[self.view addSubview:aSubview];
UIImageView *film = [[UIImageView alloc] initWithFrame:CGRectMake(20, 34, 280, 344)];
film.image = [UIImage imageNamed:#"film5.png"];
[film setAlpha:1.0];
[self.view addSubview:film];
[film release];
Can anyone explain this? Is it due to memory issue or something else? Thanks in advance.
[self.view addSubview:aSubview];
You are adding a subview in every 3 seconds. So after 10 mins there are 200 subviews which requires too much memory and thus slowing the app. Before adding a new subview, remove the previous ones if they are not needed. And if you need 200 subviews simultaneously then you should reconsider your design.
EDIT: After the edit of the question, why do you need to add a film every time? You are adding a new film object every time the method is called. Note that, super view retains subviews. So if the method is called 20 times then you have 20 film objects in memory.
Yes, your problem is with memory aggregating over time. To solve this problem use Instruments to check memory usage and find out what causes it. You might not release some object. In XCode go to Product -> Profile or press "cmd+i" choose "Allocations" and add "Leaks" manualy. Run Instruments and try to debug your problem.
[self.view addSubview:aSubview];
The above is not the issue at all, from the apple documentation for addSubView .
Views can have only one superview. If
view already has a superview and that
view is not the receiver, this method
removes the previous superview before
making the receiver its new superview.
Animation is always a heavy operation in term of memory that need to store many thing before and after animation, which are not visualable to as application developer. And in your case you are doing it more than 10 min.. in a loop that lead to reduce the availability of memory for next animation operation.
For example:
UILabel *lblEmail = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 70, 30)];
[lblEmail setBackgroundColor:[UIColor clearColor]];
[lblEmail setText:#"Email"];
[lblEmail setTag:1];
[contentView addSubview:lblEmail];
[lblEmail release];
In the above code, we create one UILabel and release it and hence has no memory reference anymore, but still it's works while I am running the application. and we can change it's value using viewWithTag also. Other example would be I create one button and release it but still in the when user clicks on the buttons it works.
Content view retained the label / button, so it is still around. You create it with a retain count of 1, adding it to the contentView gives it a retain count of 2, and releasing it gives it a retain count of 1. So it is still around.
It's not released from memory. You are just releasing your retention of it. When you add it as a subview of contentView it is retained internally there.
Apple Docs states - (void)addSubview:(UIView *)view retains view and sets the view’s next responder to the receiver, which is its new superview.
lblEmail will only be deallocated once it's reference count is 0. It is retained by contentView.
Read the Apple Documentation for addSubview.
- (void)addSubview:(UIView *)view
The view to be added. This view is retained by the receiver
Apple Documentation for UIView
A Default.png in your application directory looks like a good way to get a zoom-in splash screen "for free". Zero LOC and everything happens before your applicationDidFinishLaunching gets called so your app launch feels snappy.
Unfortunately it erases itself a bit earlier than I would like: sometime after applicationDidFinishLaunching, but before I start drawing.
Does anyone know when it happens and I how can convince it to stay longer?
How do you start drawing? I think it goes away the first time the screen is drawn, which seems to be at the end of the first run loop.
You can create the effect of having it stay longer by showing an image view of Default.png. Something like (untested):
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0)];
imageView.image = [UIImage imageNamed:#"Default.png"];
imageView.tag = 1234; // Must be a unique tag (int)
[window addSubview:imageView];
[imageView release];
//...
// When you want to hide/remove it:
UIView *defaultPng = [window viewWithTag:1234];
[defaultPng removeFromSuperview];
If you want it to be shown for some specific period of time, I imagine you'd use the second part of the code either in an NSTimer action method, or a method called using performSelector:withObject:afterDelay:. If the delay is unknown, you can use that code wherever you like.
Caveat: If your app is multithreaded, make sure it's called from the main thread. You can use performSelectorOnMainThread:withObject:waitUntilDone:.
Hope this helps.