I have a UILabel and a checkbox button. When checkbox button is checked, display the uilabel,else display the label for 5 seconds and hide the label.When I go to other view and come back to this view,my app gets crashed saying "[_UILabelLayer isHidden]: message sent to deallocated instance "
NSString *display = [NSString stringWithFormat:#"Scanned!\n\nFormat: %#\n\nContents:\n%#", formatString, result.text];
if(checkbox==NO){
[self hideLabel:display];
}
//method to hide the label for 5 seconds
- (void)hideLabel:(NSString*)text{
self.decodedLabel.hidden=NO;
[self performSelector:#selector(hideLabel) withObject:nil afterDelay:5];//3sec
}
-(void)hideLabel{
self.decodedLabel.hidden= YES; //app crashed at this point
}
Could anyone tell me why this is crashing?
[self performSelector:#selector(hideLabel) withObject:nil afterDelay:5];
is causing issues. According to my understanding, you are popping the view controller and then coming back to it. when the controller is popped, all of the associated view are cleared and deallocated. Now in your case, this happens within the span of 5 sec. So when the timer hits, it cannot find that label(which is already deallocated).
So either you can use nstimer and invalidate it as soon as the screen goes away and hide/unhide the label when the next time screen appears depending upon the check mark state.
Please let me know if this helps.
Related
I have an NSTimer displaying text over time. If a popOver shows up at the same time, the timer seems to just die. The method it's calling stops printing log statements, and my code is definitely never invalidating it.
Is this expected behavior? Should I never have a popOver when I'm running a timer?
Edit: By "at the same time" I mean, before the NSTimer has been invalidated by me (it's still displaying text), a user triggers a popOver, which prevents the NSTimer from continuing. I have methods surrounding invaliding a NSTimer which print log statements, and am invalidating it nowhere but that method. The log statements aren't displaying when a popOver happens.
Here's how I'm calling the popOver:
if ([self.popOverController isPopoverVisible]) {
[self.popOverController dismissPopoverAnimated:YES];
} else {
SubMenuViewController *popup = [[SubMenuViewController alloc] initWithStorySections:tmp_menu];
self.popOverController = [[UIPopoverController alloc] initWithContentViewController:popup];
popup.delegate = self;
[self.popOverController presentPopoverFromRect:self.textView.frame inView: self.backgroundView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
I don't THINK I'm doing any weird threading things with it, but it still interferes with my timer. I do notice that that the timer is already called before the popup is triggered, could that be doing anything?
A timer shouldn't be killed by a popover, but it does depend on the popover. If you have a custom made one that's not calling the main runloop, that might be your problem. You want to make sure the system gets time so it can call your timer call. Otherwise, put breakpoints on all your calls to invalidate the timer and see if one is getting called on you.
My app has a monthly view and for each day in the month, on a long press, a popover is displayed.
I have used self.view setExclusiveTouch:YES to prevent more than one popover occurring at once but that still occasionally allows multiple popovers.
How can I prevent more than one UIPopover from being displayed at a time?
Thanks
First of all declare a property of type UIPopoverController (lets say activePopover).
In the method that is called on long press do this:
if (self.activePopover != nil)
{
if (self.activePopover.popoverVisible)
[ self.activePopover dismissPopoverAnimated:YES];
self.activePopover = nil;
}
And then when you allocate the UIPopoverController on long press assign it to activePopover.
This way you always dismiss a visible popover and only then present a new one.
You can disable any interactions outside popover by setting its passthroughViews property to empty array after its presentation.
What about a global boolean flag?
Create it as a property in a global class or in your viewcontroller and check it before opening any popup
Init it with FALSE value and when you are going to open a popup just check its value:
//In the method that handle the long press to open the popup
if(!self.popUpPresent)
{
//open the pop up
[self openNewPopUp];
//put the flag
self.popUpPresent = TRUE;
}
else
//There is a popup opened, do another stuff or nothing.
Dont forget to reset it value again to FALSE every time you close a popUp.
Hope it helps
Im setting an MaxIdleTime in my app once if no userInteraction happened within this specified time i'm just removing the existing view from my window and adding my login (Home) view as subview to my apps UIWindow through a method called logout.
In this logout i'm just removing all the references which are alive but if any of the UIPopOverController is visible on any view during this logout call i'm getting exception
-[UIPopoverController dealloc] reached while popover is still visible.
Im making popover instance to nil in viewDidUnload even though i'm getting this exception and app is crashing and my project is ARC enabled.
How to overcome this exception, any help is appreciated in advance.
To remove all the subviews in your main view when the timer fires, use the following code:
for (UIView *sub in [[_view subviews] copy]) {
[sub removeFromSuperView];
sub = nil;
}
As for the popovers, simply remove the one currently onscreen with:
[pop dismissPopoverAnimated:NO];
pop = nil;
I have a modal view controller that appears, checks a service on the Internet and then dismisses itself when done. The nib contains an activity indicator and a label to inform the user what is going on.
When the update is complete, the label changes to "Update Complete" and then dismisses the view controller. However, I want it to delay the dismiss for a couple of seconds to give the user a chance to see the text before it disappears. So I've done this:
#pragma mark - AssetLoaderServiceDelegate
- (void)assetLoaderServiceDidFinishLoading:(AssetLoaderService *)service
{
[self.spinner stopAnimating];
self.infoLabel.text = #"Update complete";
[self performSelector:#selector(dismissUpdater) withObject:nil afterDelay:2.0];
}
- (void)dismissUpdater
{
[self dismissModalViewControllerAnimated:YES];
}
But for some reason, the selector is never being called. I've tried running it in mode NSRunLoopCommonModes too, but that doesn't work either.
I must be doing something wrong, but I can't see what...
EDIT: The delegate callback is actually happening within an NSOperationQueue, which might mean it's not on the same thread when it sends the message back to the view controller? So I tried
[self performSelector:#selector(downloadQueueComplete) withObject:nil afterDelay:0.0 inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
followed by
- (void)downloadQueueComplete
{
[delegate assetLoaderServiceDidFinishLoading:self];
}
But the performSelector doesn't seem to be working here either.
Following up your suggestion about the thread issue, would you try with:
[self performSelectorOnMainThread:#selector(downloadQueueComplete) withObject:nil waitUntilDone:YES]];
Sorted! In the AssetLoaderService, I had to perform selector on main thread:
[self performSelectorOnMainThread:#selector(downloadQueueComplete) withObject:nil waitUntilDone:YES];
After that, all the following calls were on the correct thread. :)
I'm displaying a modal view called "rule" from a round rect button. In that "rule" modal view i'm displaying another modal view called "newRule" when user clicks the Create Rule button.
When i'm quitting from the "newRule" modal view the app crashes. Here's the code i had written for quitting the "newRule" modal view.
[self dismissModalViewControllerAnimated:YES];
Nothing is displayed in the console. When i tried to debug the code, it displayed a EXC_BAD_ACCESS after the dealloc method. My dealloc method looks like this:
[label release];
label = nil;
[imageArray release];
imageArray = nil;
[languageElementsArray release];
languageElementsArray = nil;
[super dealloc];
Please help me.
Is the label a UILabel object? Also what are in the arrays? Views are automatically released once their superview is released, so releasing a subview after its superview has been released (or releasing the subview then the superview) will cause an crash similar to the one you describe
I'm experiencing something similar. When I comment out the last line ( [super dealloc] ), it then works. Does this make a difference for you?
If you happen to be using Automatic Reference Counting in Xcode 4.2, then you should not have a [super dealloc] at all—which would result in this error.
Of course, in that context you likely should not be releasing these other objects either.