UIAlertController not working Xibs? - objective-c

In my project i am using xib's in that i want to show UIAlertController and perform some actions.but i am getting error.
Here is my code.
What is the mistake in my code.

when add xibView in UIVieController assign self in ParentViewController.
i.e
_xibView *objxibView = [[xibView alloc]init];
objxibView.parentViewController = self;
in Xib's xibView.h file create 1 property
#property (weak, nonatomic) UIViewController *parentViewController;
and in xibView.m File use below code
for UIAlertController in xib
{
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:nil
message:nil
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *actionOK = [UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:actionOK];
[self.parentViewController presentViewController:alert
animated:YES
completion:nil];
}

Related

after calling an func for init the UIAlertController remains nil

I have 2 alerts I want to present in different cases, I wrote a general function to init the alerts in the beginning and change the messages later, but when I am trying to present the alert I get a crash. When I inspect the notesAlert in runtime it is still nil.
Can someone explain what I did wrong?
#interface viewController (){
UIAlertController *tableAlert;
UIAlertController *notesAlert;
}
#end
#implementation viewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initAlert:tableAlert];
[self initAlert:notesAlert];
}
// func to init the alerts
-(void)initAlert:(UIAlertController*)alert{
alert = [UIAlertController alertControllerWithTitle: #"" message: #"" preferredStyle:UIAlertControllerStyleActionSheet];
[alert setModalPresentationStyle:UIModalPresentationPopover];
[alert.popoverPresentationController setSourceView:self.view];
UIPopoverPresentationController *popover = [alert popoverPresentationController];
CGRect popoverFrame = CGRectMake(0,0, self.view.frame.size.width/2, self.view.frame.size.width/2);
popover.sourceRect = popoverFrame;
UIAlertAction *dismiss = [UIAlertAction actionWithTitle:#"Ok" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:dismiss];
}
- (IBAction)showNotes:(id)sender {
// here the notesAlert is still nil
[notesAlert setTitle:#"oops"];
[notesAlert setMessage:#"you pressed the wrong one"];
[self presentViewController:notesAlert animated:YES completion:nil];
}
#end
[self initAlert: notesAlert]; doesn't create notesAlert. Instead, you could use notesAlert = [self initAlert];
Maybe something like this:
#interface ViewController () {
UIAlertController *tableAlert;
UIAlertController *notesAlert;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableAlert = [self initAlert];
self.notesAlert = [self initAlert];
}
// func to init the alerts
- (UIAlertController *) initAlert {
UIAlertController *alert = [UIAlertController alertControllerWithTitle: #"" message: #"" preferredStyle: UIAlertControllerStyleActionSheet];
[alert setModalPresentationStyle:UIModalPresentationPopover];
[alert.popoverPresentationController setSourceView: self.view];
UIPopoverPresentationController *popover = [alert popoverPresentationController];
CGRect popoverFrame = CGRectMake(0,0, self.view.frame.size.width/2, self.view.frame.size.width/2);
popover.sourceRect = popoverFrame;
UIAlertAction *dismiss = [UIAlertAction actionWithTitle: #"Ok" style: UIAlertActionStyleDefault handler:nil];
[alert addAction: dismiss];
return alert;
}

UIAlertController disappearing since iOS 13

I have the following function that pops up a UIAlert which allows the user to update their Haptic Feedback setting:
- (void)requestHapticSetting{
UIWindow *alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
alertWindow.rootViewController = [[UIViewController alloc] init];
alertWindow.windowLevel = UIWindowLevelAlert + 1;
[alertWindow makeKeyAndVisible];
if(isHapticOn){
hapticMessage = #"Haptic feedback is currently\nturned ON.\nPlease update preference.";
}
else {
hapticMessage = #"Haptic feedback is currently\nturned OFF.\nPlease update preference.";
}
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"Haptic Setting"
message:hapticMessage
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* onAction = [UIAlertAction actionWithTitle:#"TURN ON" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[self saveHapticSettingOn];
}];
UIAlertAction* offAction = [UIAlertAction actionWithTitle:#"TURN OFF" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[self saveHapticSettingOff];
}];
[alert addAction:offAction];
[alert addAction:onAction];
[alertWindow.rootViewController presentViewController:alert animated:YES completion:nil];
}
I have used this for a couple of years and it works great.
However, since updating to iOS 13 and updating to the latest Xcode, my alert pops up for less than a second before closing.
What has changed that could be making this happen? Thanks in advance.
What seems to have changed is that on iOS 12 and previous versions your app would hold a strong reference to the window just by calling [alertWindow makeKeyAndVisible];, in iOS 13 it doesn't anymore.
What's happening is that the only strong reference to your alertWindow is in your requestHapticSetting func, and as soon as this func returns, the window is destroyed, thus removing your alert from the view.
This might be fixed just by adopting iOS 13 scenes, but I haven't tested that. What I can suggest, which won't properly work if you are using scenes, is holding your alert window in a strong variable somewhere in your code, and then using it to present the alert. I'd suggest doing so in a singleton or AppDelegate itself.
//AppDelegate.h
...
#property (strong) UIWindow *alertWindow;
....
//AppDelegate.m
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
self.alertWindow = [[UIWindow alloc] init];
self.alertWindow.rootViewController = [[UIViewController alloc] init];
self.alertWindow.windowLevel = UIWindowLevelAlert + 1;
...
}
...
//Your class that's presenting the alert
#import "AppDelegate.h"
...
- (void)requestHapticSetting{
AppDelegate *appDelegate = (AppDelegate *)UIApplication.sharedApplication;
[appDelegate.alertWindow makeKeyAndVisible];
if(isHapticOn){
hapticMessage = #"Haptic feedback is currently\nturned ON.\nPlease update preference.";
} else {
hapticMessage = #"Haptic feedback is currently\nturned OFF.\nPlease update preference.";
}
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"Haptic Setting"
message:hapticMessage
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* onAction = [UIAlertAction actionWithTitle:#"TURN ON" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[self saveHapticSettingOn];
[appDelegate.alertWindow setHidden:YES];
}];
UIAlertAction* offAction = [UIAlertAction actionWithTitle:#"TURN OFF" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[self saveHapticSettingOff];
[appDelegate.alertWindow setHidden:YES];
}];
[alert addAction:offAction];
[alert addAction:onAction];
[appDelegate.alertWindow.rootViewController presentViewController:alert animated:YES completion:nil];
}
For Swift code, check this answer.
I have created a helper class which support new UIWindowScene and iOS 13.X and swift 5.X. You guys can try
https://github.com/emraz/ERAlertController

No known class method for selector presentViewController in UIAlertController

I know it is a very simple question and i am working on it since 3 hour but didn't able to make it working. I am trying to implement UIAlertController to show error message using Apple documentation, but i am getting error on this line that no known class method for selector presentViewController [self presentViewController:alert animated:YES completion:nil]; I searched and got many solutions but none is working here. AlertMessageViewController is my custom class, which is inherited from UIViewController.
AlertMessageViewController.h
#import <UIKit/UIKit.h>
#interface AlertMessageViewController : UIViewController
+(instancetype)showAlert: (NSString *) title withMessage: (NSString*) message preferredStyle:(UIAlertControllerStyle)preferredStyle;
#end
AlertMessageViewController.m
#import "AlertMessageViewController.h"
#import <UIKit/UIKit.h>
#interface AlertMessageViewController ()
#end
#implementation AlertMessageViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
+(instancetype)showAlert: (NSString *) title withMessage: (NSString*) message preferredStyle:(UIAlertControllerStyle)preferredStyle
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"title" message:#"alertMessage" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok =[UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){NSLog(#"ok action");}];
[alert addAction:ok];
[self presentViewController:alert animated:YES completion:nil];
}
#end
Why is your return type for showAlert: method instancetype? And you didn't return anything, it should be void.
EDIT: Also, your method shouldn't be Class method
this should work:
-(void)showAlert: (NSString *) title withMessage: (NSString*) message preferredStyle:(UIAlertControllerStyle)preferredStyle
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"title" message:#"alertMessage" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok =[UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){NSLog(#"ok action");}];
[alert addAction:ok];
[self presentViewController:alert animated:YES completion:nil];
}
UPDATE:
Okay try this:
+(UIAlertController*)alertWithTitle: (NSString *) title withMessage: (NSString*) message preferredStyle:(UIAlertControllerStyle)preferredStyle
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle: preferredStyle];
UIAlertAction *ok =[UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){NSLog(#"ok action");}];
[alert addAction:ok];
return alert;
}
}
Then when you want to show it, call it like this:
[self presentViewController:[AlertMessageViewController alertWithTitle:#"Title" withMessage:#"Message" preferredStyle:UIAlertControllerStyleAlert] animated:YES completion:NULL];

iOS 8.3: Alert View Cancel Button not responding in AppDelegate

I am working on my project in iOS 8.3 in Xcode 6.3.2, I have placed an AlertView in AppDelegate class when my web service returns error, but when I am trying to click cancel button on Simulator, it is not responding. Does anyone facing same error?
Below is my code:
UIAlertView *alertFailure = [[UIAlertView alloc] initWithTitle:#"Error Occured" message:#"Something went wrong" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alertFailure show];
Edit 1: Added Delegate Method on request
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
// the user clicked OK
if (buttonIndex == 0) {
// do something here...
alertView.hidden = YES;
}
}
Edit 2: It is not even sensing the delegate
AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate, UIAlertViewDelegate>
You have to implement the following delegate method in your application.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
Here whenever you will click on the Cancel Button then it will work without any problem. As seems that you have already set the delegate for UIAlertView.
Please let me know if you still face any issue.
If you didn't already, you need to add that the AppDelegate is conforming to UIAlertViewDelegate like this:
In AppDelegate.h:
#interface AppDelegate : UIResponder <UIApplicationDelegate, UIAlertViewDelegate>
Edit: I just created an empty project and pasted your code in applicationDidBecomeActive:, and it worked. No delegate methods, no nothing. Maybe remove the whole alertView:clickedButtonAtIndex: method?
Edit 2: If you're only targeting iOS 8+, then you can (and should, since UIAlertView is deprecated in iOS 8) use the new UIAlertController:
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"Error Occurred"
message:#"Something went wrong."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
If you're targeting iOS 8.3 you can use UIAlertController instead of UIAlertView, you don't need to implement any protocols or set a delegate, just use an action:
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"Error Occured"
message:#"Something went wrong"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:#"OK"
style:UIAlertActionStyleCancel
handler:NULL];
[alert addAction:cancel];
[self presentViewController:alert
animated:YES
completion:nil];

UIAlertView and UIActionSheet not displaying properly in iOS 8

UIAlertView and UIActionSheet not displaying properly in iOS 8, its hiding the view controller, also In alert view title is not displaying. I am running the app from Xcode 5.1.1.
Did you added any category for ViewController in your application. like below shown
#implementation UIViewController (CustomeAction)
- (void)setTitle:(NSString *)title{
// YOU CODE///
}
#end
This may the issue. I have solved by removing this category - (void)setTitle:(NSString *)title.
Note: From iOS 8, UIAlertViewController is inherited from UIViewController. If you use category method, it will be effect on UIAlertView & UIActionSheet titles.
You can refer apple docs at UIAlertController Class Reference
It should be noted, that UIAlertView and UIActionSheet is deprecated in iOS 8. You can check out this question or the apple link. May be it will help you.
You can use following code using UIAlerController for XCode 6 and IOS 8
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Title"
message:#"Your Message"
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];
For ActionSheet
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Title"
message:#"Your Message"
preferredStyle:UIAlertControllerStyleActionSheet];