Some Deprecated UI Objects Causes Memory Leak On iOS8 - ios

I tried UIAlertView and UIActionSheet objects that causes memory leak in iOS8.4 SDK. New objects that coming from iOS8 (such as UIAlertController) that supports minimum iOS8 OS. How can handle this leak with iOS8 and before releases?
Example code piece that causes leak;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#""
message:#""
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];

I would suggest to check the class availability. For example, if you want to check whether to use UIAlertController or UIAlertView then:
if ([UIAlertController class]) {
// use UIAlertController
} else {
// use UIAlertView
}

Related

UIAlertView crashs in iOS 8.3

recently i start receiving crash reports for UIAlertView only by users that use iOS 8.3
Crashlytics reports:
Fatal Exception: UIApplicationInvalidInterfaceOrientation
Supported orientations has no common orientation with the application, and [_UIAlertShimPresentingViewController shouldAutorotate] is returning YES
The line where that crash happens is [alertView show] :
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:nil
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:nil];
[alertView show];
that code is in the app for a long time and now it starts crashing. Did anyone experience a similar behaviour and has fixed the problem?
The main thing is :
UIApplicationInvalidInterfaceOrientation Supported orientations has no common orientation with the application
It means you have somewhere implemented
- (NSUInteger)supportedInterfaceOrientations {
return UIDeviceOrientationPortrait; // or UIInterfaceOrientationPortrait
}
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait = 0
In that function MUST be returned Mask like:
UIInterfaceOrientationMaskPortrait which is 1
try by implementing this
- (BOOL)shouldAutorotate {
return NO;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
check this also : Orientation issue in Lanscape mode while opening camera in iOS 7 in iPhone
Better than this you should start using UIAlertController. It has much better functionality and also for UIAlertAction you don't have to include delegate methods.
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Info"
message:#"You are using UIAlertController"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction
actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction* cancel = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:ok];
[alert addAction:cancel];
[self presentViewController:alert animated:YES completion:nil];
Important: UIAlertView is deprecated in iOS 8. (Note that UIAlertViewDelegate is also deprecated.) To create and manage alerts in iOS 8 and later, instead use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert.
https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIAlertView_Class/index.html
After trying the solutions here, none of them worked for me. I'm supporting iOS 6-8 in an app, and, more than that, use some libraries that use UIAlertView internally, so simply conditionally compiling to use UIAlertController when available was not an option.
I came up with a solution that solved the problem for me. Your mileage may vary. I include the header file in the Header Prefix file so that it's sure to be included anywhere a UIAlertView is shown.
I'm posting this here for anyone who's stumbling on this problem and the solutions found around the net don't work. Hopefully it's helpful.
https://gist.github.com/joshhudnall/cdc89b61d0a545c85d1d
I created a helper for displaying UIAlertView when before iOS8 and UIAlertController after iOS8, this solves the rotation crash and also displays nicely in all versions.
https://github.com/dannyshmueli/DSAlertDisplayer

How to dismiss UIAlertView in both iOS 7 & iOS 6?

How to dismiss uialertview(default) when click on out side. Here I have set the uialert with only one button (OK). Intend for implement this alert, if user seen free offer pack from this uialertview and he want to access his free pack offer by clicking the OK button in uialertview. Otherwise if he doesn't want to access his free offer pack at this time the user can tap the outside of uialert view and the alertview dismissed it.
Kindly give suggestion for how dismiss uialertview from out side clicking.
offeredAlert = [[UIAlertView alloc] initWithTitle:nil
message:strMessage
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil,nil];
[offeredAlert setTag:10002];
[offeredAlert show];
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *tempStr;
if(alertView.tag == 10001)
{
if(buttonIndex == 1)
{
tempStr = #"payable";
[self dietPackPurchaseAPI:id_Pack type:tempStr];
}
}
}

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 #>
});

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.)

Showing Waiting Alert View At Load

I would like when my app starts for it to show an Alert view for about 5 seconds, then depending on the outcome of a background process, it will show another Alert view.
The problem I am experiencing is that when I try to use Sleep to wait for a background process to occur. The first Alert does not show and wait the 5 seconds. The app shows the first view of the app, and then after 5 seconds the first Alert shows briefly.
What do I need to do to perform what I wish.
Here is my code.
- (void)viewDidAppear:(BOOL)animated
{
SSGlobalSettings *connSettings = [SSGlobalSettings sharedManager];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Connecting" message:#"Please wait, while your device connects" delegate:Nil cancelButtonTitle:nil otherButtonTitles: nil];
[alertView show];
[NSThread sleepForTimeInterval:5.0f];
[alertView dismissWithClickedButtonIndex: alertView.cancelButtonIndex animated: YES];
if ([connSettings.connectionStatus isEqual: #"Not Found"])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Connection Failed" message:#"Cannot find your device on the network" delegate:Nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alertView show];
}
else
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Connection Success" message:#"WYour device has been found on the network" delegate:#"OK" cancelButtonTitle:nil otherButtonTitles: nil];
[alertView show];
}
}
Don't use sleep on the main thread. Ever. Also don't update UI from a background thread.
What you want to do is to display your alert on the main thread and return.
Then, when your networking code completes, have it send a message to the main thread. In the main thread, when you receive a notice that it's done, remove the alert.
It's not working right because you are trying to tell the main thread of the app to sleep. If you are telling that thread to sleep, then you're most likely not going to allow any UI updating to occur during that time, because all UI updating happens on the main thread.
What you need to do is move the code for showing the second UIAlertView to a second method, and then call the method - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay, passing it that second method for the selector, and giving it a delay of 5 seconds. Make sure you remove the call to sleep the main thread.
However, this still seems like a bad practice, because this action should be occurring as a result of your background task completing. So if you can, you should be running the code to show the second alert view upon completion of that task, which most likely could finish in varying amounts of time.
you block the main thread in you way.
i think it seems that you just want the user not to do anything before the first 5 sec(to let you connection connect successfully?), if so, lots ways could do that, e.g. just show a view on the top of the window, until you want the user can do something, you can show the disappear button on that view or just disappear it immediately.
You can use performSelector:withObject:afterDelay: method instead.

Resources