Animations stopped working - ios

I know it sounds a bit general, but this is exactly the issue. After roaming a bit in my app, something I do (don't know what) causes the app to lose all its animations.
Animations like: keyboard popping up/down, view controllers push animations... Or even my coded animations. Nothing works. Everything just pops in/out instantly.
I'm not even sure which code of mine causes this...
Could it be a bug in my code? or a bug in my device? or a bug in iOS8?
Thanks

Animations will stop working when performing them in a background queue. Ideally, you would find and fix such instances in your code. Here is a library that helps track them down:
https://github.com/Cocoanetics/DTFoundation/blob/develop/Core/Source/iOS/Debug/UIView%2BDTDebug.m
This is a good workaround (from the App developer forums) to get animations to work again:
[UIView setAnimationsEnabled:YES]

OK... Found it.
I was loading a new view controller. In the viewDidLoad I have put a block to see if the app has permissions to create a reminder. The loading of the page was postponed after the completion of the block and that's what caused the bug.
This is my BAD code:
- (void)viewDidLoad {
[super viewDidLoad];
self.shouldAlert = YES;
[[EventStoreManager sharedManager] connectRemindersPermissionWithCompletion:^(BOOL granted) {
if (granted) {
[self initData];
[self initGraphics];
[self pageLoaded];
} else {
dispatch_async(dispatch_get_main_queue(), ^(void) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"\"APP_NAME\" Would Like to Access Your Reminders" message:#"Settings -> Privacy -> Reminders" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert showWithCompletion:^(UIAlertView *alertView, NSInteger buttonIndex) {
[self closeAddTaskButtonPressed:nil];
}];
});
}
}];
}
This is my correction:
- (void)viewDidLoad {
[super viewDidLoad];
self.shouldAlert = YES;
[self initData];
[self initGraphics];
[self pageLoaded];
[[EventStoreManager sharedManager] connectRemindersPermissionWithCompletion:^(BOOL granted) {
if (granted) {
} else {
dispatch_async(dispatch_get_main_queue(), ^(void) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"\"APP_NAME\" Would Like to Access Your Reminders" message:#"Settings -> Privacy -> Reminders" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert showWithCompletion:^(UIAlertView *alertView, NSInteger buttonIndex) {
[self closeAddTaskButtonPressed:nil];
}];
});
}
}];
}
Bug solved... :)

Unlikely but: try searching for "speed" in your code base. In case you
[UIApplication sharedApplication].keyWindow.layer.speed = 99.0;
or something similar.

Related

iOS: Decrease delay in UIAlertView show when app enters foreground

I have created a password protected app. The app is allowed to run in background.
When it returns to foreground, I display an alert to prompt the user for password, by overriding the applicationWillEnterForeground: method in appdelegate like so-
- (void)applicationWillEnterForeground:(UIApplication *)application
{
if (/*password is enabled*/) {
alertview = [[UIAlertView alloc] initWithTitle:#"LOGIN"
message:#"Enter app password"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
alertview.alertViewStyle = UIAlertViewStyleSecureTextInput;
pwdTF = [alertview textFieldAtIndex:0];
[pwdTF setDelegate:self];
[alertview show];
}
}
However, the alert takes a little time to appear. During this time, the view remains vulnerable.
Is there a way to make uialertview show instantly?
dispatch_async(dispatch_get_main_queue(), ^{
<# Write UI related code to be executed on main queue #>
});

Show UIAlertView in delegate fails

I am calling a UIAlertView within it's own delegate and it is failing. The code is simple:
#interface ViewController () <UIAlertViewDelegate>
#property (nonatomic, strong) UIAlertView *alertView;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.alertView = [[UIAlertView alloc] initWithTitle:#"Howdy"
message:#"Here's the alert"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
[self.alertView show]; // this shows the
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1) {
[self.alertView show]; // this does not show the alert again!
}
}
#end
However, when I remove:
[self.alertView show]
and replace it with:
[self.alertView performSelector:#selector(show) withObject:nil afterDelay:0.01]
it works.
This seems to indicate that the original UIAlertVIew is not completely dismissed even though I am inside the delegate method alertView:didDismissWithButtonIndex:.
While this is working, it does not seem right. Can anyone tell me what I am doing wrong?
You are probably right, but I don't see why would you show the same alert again. Since you usually do not require to keep a reference to an alert, you could just write a method like:
- (void)showAlert {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Howdy"
message:#"Here's the alert"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
[alert show];
}
It would also be better if you would call this from viewDidAppear instead of viewDidLoad.

Quit iOS Application Programmatically with UIAlertView

I'm aborting my iOS Application by below methods
-(void)cancelSelected
{
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:nil message:#"Are you sure you want to exit?" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes", nil];
[alert show];
alert = nil;
}
Method 1 :
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex)
abort();
}
Method 2 :
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex)
[NSException raise:#"Disagree terms and conditions." format:#"Quit, Cancel"];
}
Shall I do this to quit my iOS Application programmatically?
Will this abort() method leads to reject my app?
Thanks!
See QA1561:
Q: How do I programmatically quit my iOS application?
A: There is no API provided for gracefully terminating an iOS
application.
In iOS, the user presses the Home button to close applications. Should
your application have conditions in which it cannot provide its
intended function, the recommended approach is to display an alert for
the user that indicates the nature of the problem and possible actions
the user could take — turning on WiFi, enabling Location Services,
etc. Allow the user to terminate the application at their own
discretion.
Yes the codes above will result in a reject. Use this code instead in your OK button of alert:
UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil)
Yes, generally you will get rejected for that.
Just present an alert to the user with a singe option, so they must approve to dismiss the alert. Then, if they dismiss (approve) they can use the app and if they don't they can't and must quit the app manually.
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"Game Over" message:#"Your time is up" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *close = [UIAlertAction actionWithTitle:#"close" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
**exit(0);**
}];
UIAlertAction *playagain = [UIAlertAction actionWithTitle:#"Play again" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
[self viewDidLoad];
}];
[alert addAction:close];
[alert addAction:playagain];
[self presentViewController:alert animated:YES completion:nil];
Use exit(0) for close current application
You can use below code to Quit iOS Application Programmatically with UIAlertView :-
Step 1:
Delegate "UIAlertViewDelegate" to your viewcontroller.h
for example:
#interface User_mail_List : UIViewController< UIAlertViewDelegate >
Step 2:
//create your UIAlertView
UIAlertView *exit_alertView= [[UIAlertView alloc] initWithTitle:#"Bizbilla !" message:#"\nAre you sure you want to Exit ?" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes",nil];
[exit_alertView show];
Step 3:
-(void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex{
if(alertView==exit_alertView){//exit Alert Fns Start,,,,,
if(buttonIndex==1){
exit(0);
}
}//exit Alert Fns End,,,,,
}
thanks,
On your alertview button click
You can use: exit(0)?
Or,
[[NSThread mainThread] exit], using this you can quit ios app.
How about calling fatalError()
function? I've just used it, everything works as expected. (Hope this will not cause a rejection though.)

Objective-C view pop-up after random time

Let's say John has been using my app for 3-6 minutes.
Then I'd like a view to pop up that would in my case, include an advertisement.
Something like this,
AdViewController *adViewController = [[AdViewController alloc] init];
[self presentViewController:adViewController animated:YES completion:nil];
But how can I let it pop up after some random time? I guess I have to work with the delegate files and use the arc4random function.
After John has viewed the advertisement, he'd then have to close it, but that's not the problem..
Can someone give me a code example?
The simple solution is to
Create a NSTimer and let it fire every 300 secs (5 mins)
NSTimer will fire an action that shows your pop-up.
I don't get it why was this so difficult to understand?
//use arc4random() if you need random time
NSTimer *timer2 = [NSTimer scheduledTimerWithTimeInterval:300.0 target:self selector:#selector(rateThisApp) userInfo:nil repeats:YES];
// *********
// ********* RATE APP ***********
// *********
- (IBAction)rateThisApp
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Rate this App"
message:#"Are you enjoying this app? Please leave a rating at the app store and tell us what you think of this app and its features. We would love to hear from you!"
delegate:self cancelButtonTitle:#"Not Now"
otherButtonTitles:#"Rate Now", nil];
[alert show];
alert.tag = 400;
}
-(void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (actionSheet.tag == 400)
{
if (buttonIndex == 0)
{
//dont do anything, user hit cancel
}
else if (buttonIndex == 1)
{
[[UIApplication sharedApplication]
openURL:[NSURL URLWithString:#"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=1234567"]];
}
}
}

UIAlertViewDelegate didDismissWIthButtonIndex getting called for 1 UIAlertView, but not the other

(iOS7, xCode 5.1) I have an app that accesses the Calendar for various purposes, and I'm trying to get all of my error messaging in place.
I have 2 UIAlertviews. Both UIAlertviews show when I need them to, but I only get a call to didDismissWIthButtonIndex for one of them. The alertview called _iCloudAlert is the one that works.
If I show the _iCloudAlert, I get a call to didDismissWIthButtonIndex when a button is clicked, but when I show _deniedAccessAlert I get no call at all. I can't even see the outermost NSLog/s.
I have <UIAlertviewDelegate> in my .h file.
Code that shows the alerts, depending on Calendar access:
// Check the authorization status of our application for Calendar
-(void)checkEventStoreAccessForCalendar
{
NSLog(#"Check Status");
EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
switch (status)
{
// Update our UI if the user has granted access to their Calendar
case EKAuthorizationStatusAuthorized: [self accessGrantedForCalendar];
NSLog(#"Already granted");
break;
// Prompt the user for access to Calendar if there is no definitive answer
case EKAuthorizationStatusNotDetermined: [self requestCalendarAccess];
break;
// Display a message if the user has denied or restricted access to Calendar
case EKAuthorizationStatusDenied:
case EKAuthorizationStatusRestricted:
{
NSLog(#"already denied");
[self performSelectorOnMainThread:#selector(showDeniedAccessAlert) withObject:nil waitUntilDone:NO];
}
break;
default:
break;
}
}
Both alert view methods:
- (void)informUserAboutCloud {
_iCloudAlert = [[UIAlertView alloc]
initWithTitle: #"Important!"
message: #"If you have an iCloud account.....blah, blah, blah..."
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[_iCloudAlert show];
}
- (void)showDeniedAccessAlert {
NSLog(#"Show Denied Access Alert");
_deniedAccessAlert = [[UIAlertView alloc]
initWithTitle: #"Attention!"
message: #"It looks like you've blocked access to Calendar data... Blah, Blah, Blah..."
delegate: nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[_deniedAccessAlert show];
}
And here is the code used to take action on the button clicks:
- (void)alertView:(UIAlertView *)alert didDismissWithButtonIndex:(NSInteger)buttonIndex {
NSLog(#"button index: %i", buttonIndex); //only logs when _iCloudAlert is shown
NSLog(#"alertview: %#", alert); //only logs when _iCloudAlert is shown
if (_iCloudAlert) {
[self checkEventStoreAccessForCalendar];
NSLog(#"check for calendar access from dismissed icloud alert...");
}
if (_deniedAccessAlert) {
NSLog(#"dismissed denied access..."); //never logged
}
}
The 2nd UIAlertView has its delegate set to nil. Change that, and it will work!

Resources