Reputation: 2057
I am creating a UIActionSheet
on actionSheet:clickedButtonAtIndex delegate method.
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
if(buttonIndex == 1){
[self.myFirstView removeFromSuperview];
if (!self.mySecondView) {
[[NSBundle mainBundle] loadNibNamed:@"MySecondView" owner:self options:nil];
}
[self.mySecondView setFrame:CGRectMake(0, 0, 320, 480)];
[[UIApplication sharedApplication].keyWindow addSubview: self.mySecondView];
UIActionSheet * action = [[UIActionSheet alloc]initWithTitle:@""
delegate:self
cancelButtonTitle: nil
destructiveButtonTitle: deleteContacts
otherButtonTitles: cancel, nil];
action.tag = 102;
[action showInView:self.view];
[action release];
}
I handle the click event of this UIActionSheet
in the exact same method as above.
if(actionSheet.tag == 102){
if(buttonIndex == 0){
if([[NSBundle mainBundle] loadNibNamed:@"MyThirdView" owner:self options:nil]) {
[self.myThirdView setFrame:CGRectMake(0, 0, 320, 480)];
[[UIApplication sharedApplication].keyWindow addSubview:self.myThirdView];
}
[self.mySecondView removeFromSuperview];
[self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton.target];
[self performSelector:@selector(RemoveView) withObject:self afterDelay:3.0];
}
}
The problem I am facing is that, the UIActionSheet
takes too much time to respond. When I click on the UIActionSheet
button, its in a frozen state for 2 or 3 seconds, before myThirdView
loads. I am not able to understand, whats the response delay in this case as the first thing I do in the UIActionSheet
button click event method is to load myThirdView
. The rest of the code is executed only after the code to load the myThirdView. But even the first line of code seems to execute after a delay.
Any suggestions?
Upvotes: 6
Views: 2032
Reputation: 593
in Swift 4: I wrapped the code with this block
DispatchQueue.main.async {
// your code to show action sheet.
}
for example
DispatchQueue.main.async {
let alert = UIAlertController(title: "Options", message: String("What do want to do?"), preferredStyle: UIAlertController.Style.actionSheet)
alert.addAction(UIAlertAction(title: "Open", style: UIAlertAction.Style.default, handler: {(action:UIAlertAction!) in
self.myOpen(code: self.codes[indexPath.row])
}))
alert.addAction(UIAlertAction(title: "Delete", style: UIAlertAction.Style.default, handler: {(action:UIAlertAction!) in
self.myDelete(indexPath: indexPath)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.default, handler: {(action:UIAlertAction!) in
print("Cancel")
}))
self.present(alert, animated: true, completion: nil)
}
Upvotes: 0
Reputation: 11818
How big is your third view. if the nib file needs to load too much, you may be waiting for a lot to happen, also if you have to change some UI elements and your blocking the UI thread, you will hault your app until a timeout occurs and the app will shift some things to compensate..
the route I take with this is dispatch_async and dispatch_sync
// This will release the UI thread which may be blocking your calls.
// You can use any of the DISPATCH_QUEUE_PRIORITY_.... values to set how important this block is.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// this command will get added to the stack and return without a hitch.
// the block will be run the next time the main runloop ends.
dispatch_async(dispatch_get_main_queue(), ^{
// do some UI work that can happen without a hitch, and does not impact the calling block
});
// this command will act much the same. but will pause the background execution
// of this block until the runloop has executed this and returned.
dispatch_sync(dispatch_get_main_queue(), ^{
// do some UI work that must be completed to continue.
});
});
doing too much in the UI thread will pause the execution of things that get stacked on the queue. Shipping all code to the background thread and only skipping to the UI thread when you need to alter the UI is a better and more responsive way to code your iphone app.
I hope this helps :)
Upvotes: 1
Reputation: 3359
User interface actions run in the main thread and only occur when your method ends. So, MyThirdView
will not appear until the other instructions have finished. The only thing I can figure is delaying that is:
[self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton.target];
If you are doing any heavy calculation or net conection, for sure that is the reason.
OTOH, I think you'd better modify that line:
[self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton];
if you want to simulate a button touch action.
Upvotes: 3
Reputation: 3191
Question. Does the UIActionSheet freeze, or does it disappear and the 3rd view isn't visible for 2-3 seconds?
This could be due to 1 of 2 problems.
If the entire action sheet freezes, then you are doing some heavy lifting when you init that 3rd view, you are loading some core data, or a lot of assets, or something that is taking a long time. If this is the case, you'll need to reformat HOW you load that 3rd view. I'd suggest pushing any heavy loading to the background (this means if you have a lot of images in your xib, you may need to load them in code).
The other possibility, is you are adding the 3rd view BELOW the 2nd view, and then not hiding the 2nd view for 3 seconds (done by performing the selector with a delay). If this is the case, simply remove the delay.
I made a couple of classes to help me time executions and find the bottlenecks in my code, it seems like they might help you now. http://forrst.com/posts/Code_Execution_Timer_for_iOS_Development-dSJ
Upvotes: 2
Reputation: 8947
this is perhaps due to this
[self performSelector:@selector(RemoveView) withObject:self afterDelay:3.0];
make an other methods and do this in that method. like this
[self viewRemover];
and in viewRemover
-(void) viewRemover
{
[self performSelector:@selector(RemoveView) withObject:self afterDelay:3.0];
}
so your code will be like this now
if(actionSheet.tag == 102){
if(buttonIndex == 0){
if([[NSBundle mainBundle] loadNibNamed:@"MyThirdView" owner:self options:nil]) {
[self.myThirdView setFrame:CGRectMake(0, 0, 320, 480)];
[[UIApplication sharedApplication].keyWindow addSubview:self.myThirdView];
}
[self.mySecondView removeFromSuperview];
[self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton.target];
[self performSelectorInBackground:@selector(viewRemover) withObject:nil];
}
}
Upvotes: 3