I noticed that after dismiss a UIAlertView, there is a short amount of time that apps do not recognize any touches.
So, I made a very simple project, which only contains 2 UIButtons (one to change a label to a random number and one to show a UIAlertView).
Tested it both on device (an iPhone4) and simulator (iOS 6 and iOS 7).
The result is this lag only happens on iOS 7. On iOS 6.x, it works just fine.
The delay duration depends on how large the app is. In the test project, which I described above, the delay is about 0.3s. However, in an another project of mine, it maybe up to 1 second.
I also used GCD, follow this:
- (void) startSomeLongOperation {
//display alertView
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_NORMAL, 0), ^{
// …do something that takes long…
dispatch_async(dispatch_get_main_queue(), ^{
//dismiss alertView
});
});
}
another one I have tried:
dispatch_async(dispatch_get_main_queue(), ^{
//show and dismiss alertView
});
neither of them work.
So, I jumped in to conclusion that this delay was caused by iOS 7.
Have anyone experienced this before ?
Related
I'm trying to extend what apple watch can do by rendering UIImage 'frames' and then setting them on my WKInterfaceImage every 500 milliseconds (2 frames per second).
My plan is to try render 8bit style games that don't need high detail or frame rates and then get arrow buttons on the watch app to direct how the game state changes.
So I have a Game class that has a 'tick' method which returns a UIImage. Each call to 'tick' will proceed the game by a single point. Think Tetris where each 'tick' of the game moves the falling blocks by one block space downwards. The game proceeds by 'ticks' until there is interaction from the user. Upon call to rotate the block, I am telling the Game class to rotate left or right when the next 'tick' happens. Here are the relevant parts of my WKInterfaceController class below.
- (void)willActivate
{
// This method is called when watch view controller is about to be visible to user
NSLog(#"%# will activate", self);
// wait 2 seconds until game 'starts'
[self performSelector:#selector(timerFired) withObject:nil afterDelay:2.];
}
- (void)timerFired
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.theImage setImage:[self.game tick]];
[self performSelector:#selector(timerFired) withObject:nil afterDelay:.5];
});
}
- (IBAction)leftButtonPressed
{
self.game.futureMove = FutureMoveAntiClockWise;
}
- (IBAction)rightButtonPressed
{
self.game.futureMove = FutureMoveClockWise;
}
Now, amazingly all that code works great - for a few seconds. Then it all gets slower and slower and more and more behind (in terms of frames). After 10 seconds or so pressing the rotate left or right buttons only shows up on the rendered UIImage a few seconds later.
The watch app starts off rendering maybe 30 frames a second (if I wanted it to), and then crawls slower and slower and ultimately stops. Is there a better way to reliably setImage on a WKInterfaceImage repeatedly without it slowing down?
I'm so close!!
Thanks for you comments. After updating to Xcode 6.3 it works fine and doesn't lag but I will heed #MikeSwanson and expect Apple to reject my app :(.
I'm using SKStoreProductViewController on iPad with iOS 8. Pressing a button opens an instance of it:
[self.storeProductViewController loadProductWithParameters:#{SKStoreProductParameterITunesItemIdentifier:appStoreIdNumber}
completionBlock:^(BOOL result, NSError *error) {...}];
[[self getPresentingViewController] presentViewController:self.storeProductViewController animated:YES completion:^{...}];
It pops up the first time fine. But after it is dismissed, pressing the button again to reopen it throws an exception and the pop up never appears.
<SKRemoteProductViewController: 0x15c1ec00> timed out waiting for fence barrier from com.apple.ios.StoreKitUIService
Anyone know what's going on or how to work around it?
I've also had some other problems with UIAppearance and StoreKit not working together (see StoreKit's SKStoreProductViewController leaving space between the nav bar and the view?)
I was having the same problem that you now have and removing all UIAppearance code fixed it, but I noticed that the SKStoreProductViewController won't load any iPad apps on an iPhone on iOS 8 and it will fail silently. Let me know if you have the same problem.
I had the same problem, where the first time I present the SKRemoteProductViewController it works fine, but subsequent presentations give the error as the OP described. Apparently the problem is related to presenting the same SKRemoteProductViewController more than once. If I dispose of the SKRemoteProductViewController after presenting it and then re-load another one each time I want it to present again then things work without issue.
Had this problem as well. Make sure that identifier is actually an NSString
#{ SKStoreProductParameterITunesItemIdentifier : identifier }
I was inadvertently passing an NSURL object, which resulted in the same error -- "timed out waiting for fence barrier from com.apple.ios.StoreKitUIService"
you should present SKStoreProductViewController before loading it
The Problem - Preparing and showing an MFMessageComposeViewController is trivial as per the Apple docs. What I need to know is when this has been fully presented.
Explanation - Showing the MFMessageViewComposeController with a completion block is easy, but doesn't solve my problem:
[self presentViewController:messageController animated:YES completion:^(void){
//Controller has been shown. But not really....
}];
The problem is more obvious for messages to larger groups of recipients (say 50 people). The completion block gets called, but the phone's screen remains black. Several seconds later, the messaging window appears. Several seconds later, the recipient list becomes active with a flashing cursor. Basically, there's a lot of loading and processing that goes on after the controller has supposedly been presented.
What I'd like - To figure out when the interface has been fully loaded. I don't expect a simple answer, and I've already spent quite a bit of time on it - definitely bounty worthy. If you can post a working answer with code I'll award maximum bounty for it.
Just check MFMailComposeViewController view's frame. Once it achieves top of the screen handle the appearance.
[self presentViewController:messageController animated:YES completion:^
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^
{
while(messageController.view.frame.origin.y > 0)
{
}
dispatch_async(dispatch_get_main_queue(), ^
{
// Handle appearance of MFMailComposeViewController
});
});
}];
The other way is to wait 0.3 seconds using dispatch_after() method. But this time interval could be changed next versions of iOS.
I am facing error App Terminated due to Memory Pressure when I capture some images using UIImagePickerController Camera.
I receive memory warnings first and then suddenly app crashes. This issue is in iOS 7 specifically as in iOS 6 it is working fine.
Does someone know why is this memory issue occuring in iOS 7 on using camera.
Note: I tried to minimize RAM usage because it may also be the reason for this memory pressure. But still getting warning.
I just posted this answer on a similar post (iOS 7 UIImagePicker preview black screen). Here's what I said:
About 5 months ago my team discovered a memory leak with UIImagePickerController. Each instantiation slowed down the app exponentially (i.e. first alloc-init had a 1 second delay, second had a 2 second delay, third had a 5 second delay). Eventually, we were having 30-60 delays (similar to what you're experiencing).
We resolved the issue by subclassing UIImagePickerController and making it a Singleton. That way it was only ever initialized once. Now our delay is minimal and we avoid the leak. If subclassing isn't an option, try a class property in your viewController and just lazy load it like so.
-(UIImagePickerController *)imagePicker{
if(!_imagePicker){
_imagePicker = [[UIImagePickerController alloc]init];
_imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
return _imagePicker;
}
Then you can just call it later like:
[self presentViewController:self.imagePicker animated:YES completion:nil];
From what I could tell, this is just an issue with the UIImagePickerController in iOS 7. Previous versions seems to be fine.
I tried my app on my iPhone with iOS 7 and everything works perfectly except one thing. On iOS 6 versions, when I executed the following code, the loading view (with the activityindicator) appeared and disappeared at the end of the loading. On iOS 7, the view does not appear at all during the loading.
self.loadingView.alpha = 1.0;
[self performSelector:#selector(accessServices) withObject:nil afterDelay:0.0f];
AccessServices method :
- (void)accessServices {
// Getting JSON stuff
// The code is OK, I just don't copy/paste it here
self.loadingView.alpha = 0.0;
}
What happens ? Is it an iOS 7 bug ?
I wouldn't have expected the behavior of the above code to change, though I'm not surprised that it might not work the way you expect. If you do the JSON stuff on the main queue, your code will be dependent on idiosyncrasies of when the UI update takes place, rather than making it explicit.
You probably want to explicitly dispatch the JSON code to a background queue, and then dispatch the final UI update back to the main queue. The standard pattern for something like this is:
self.loadingView.alpha = 1.0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Getting JSON stuff
// The code is OK, I just don't copy/paste it here
dispatch_async(dispatch_get_main_queue(), ^{
self.loadingView.alpha = 0.0;
});
});
You can use GCD (like above) or operation queues, or whatever. But the idea is the same, that UI updates should happen on the main queue but that anything remotely computationally expensive or slow else should happen on a background queue.
This pattern should work regardless of iOS version.