No known class method for selector presentViewController in UIAlertController - objective-c

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];

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

Show keyboard when Textfield inside Alert in WkWebView is tapped

There is a game that i load in the WKWebView and this Alert and textField appear after the game is finished. I want to display keyboard when user taps on the textField. But the problem is there is no code to display this alert and textfield, otherwise i would have managed the textField to becomeFirstResponder().
Desperately need some help. I would really appreciate it.
Okay so i have found the solution. I had a textField in custom Alert/Popup in WkwebView and i wanted the textField to becomeFirstResponder() so i could take user input.
// So i Implemented WKUIDelegate..
#import <WebKit/WebKit.h>
#interface MyController : UIViewController<WKUIDelegate>
Assigned the Delegate..
- (void)viewDidLoad {
[super viewDidLoad];
_webkitView.UIDelegate = self;
}
//implemented delegate function.
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *result))completionHandler
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"BlockChaid Id, Email or Username"
message:prompt
preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = prompt;
textField.secureTextEntry = NO;
textField.text = defaultText;
}];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(#"Cancel", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
completionHandler(nil);
}]];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(#"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
completionHandler([alert.textFields.firstObject text]);
}]];
[self presentViewController:alert animated:YES completion:nil];
}
After successful build, this was the output.
I tapped the textField, and javaScript Alert appeared.
This right here is what i wanted to achieve.
Maybe i was not good enough to explain my question, but this is what i was asking for. Thank you :)

UItextField - iOS multiple line textfield on AlertView

Here is my code
I am adding uitextfield to alertview , what I need is to get the data from the array to uitextfield with multiple lines and should be editable.
NSString *selected = [lineItemsArray objectAtIndex:indexPath.row];
UIAlertController *controller = [UIAlertController alertControllerWithTitle:#"Notice" message:#"Selected" preferredStyle:UIAlertControllerStyleAlert];
[controller addTextFieldWithConfigurationHandler:^(UITextField *linetextField)
{
linetextField.text=selected;
}];
UIAlertAction *alertAction = [UIAlertAction actionWithTitle:#"Okay"
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *action) {
[self.navigationController popViewControllerAnimated:YES];
NSLog(#"Dismiss button tapped!");
}];
[controller addAction:alertAction];
[self presentViewController:controller animated:YES completion:nil];
PackageLineItemViewController *pLineVC = [[PackageLineItemViewController alloc]init];
pLineVC.view.backgroundColor = [UIColor whiteColor];
[self.navigationController pushViewController:pLineVC animated:YES];
[self.view endEditing:YES];
I tried the solution for your question.If you use alertViewController with textField you can't set multiple line.For label you can set multiple line but for textfield you can't set.
#import "ViewController.h"
#interface ViewController ()<UITextFieldDelegate>
{
NSArray *arr;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
arr = [NSArray arrayWithObjects:#"iOS",#"Android",#"Windows",nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)actionShowClickTextField:(id)sender
{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil
message:#"Enter your text"
preferredStyle:UIAlertControllerStyleAlert];
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.delegate = self;
textField.text = #"";
for(int i=0;i<[arr count];i++)
{
textField.text = [textField.text stringByAppendingString:[NSString stringWithFormat:#"%#,\n",[arr objectAtIndex:i]]];
}
NSLog(#"The textField text is - %#",textField.text);
}];
[self presentViewController:alertController animated:YES completion:nil];
UIAlertAction *actionAlert = [UIAlertAction actionWithTitle:#"Save"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
// access text from text field
NSString *text = ((UITextField *)[alertController.textFields objectAtIndex:0]).text;
NSLog(#"The text is- %#",text);
}];
actionAlert.enabled = YES;
[alertController addAction:actionAlert];
}
#end
The printed output results are
The textField text is - iOS, Android, Windows
UITextFIeld is specific to one line. you cannot have multi-line textfeild. IF you need multi line , you should go for UITextView. Again you cannot add UITextView to the alert controller. You need to build a custom alert view.

UIAlertController not working Xibs?

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];
}

How to properly use a UIAlertAction handler in Objective-C

Simply put, I would like to call a method or reference a variable from my class in a UIAlertAction handler.
Do I need to pass in a block to this handler or is there some other means to achieve this?
#interface OSAlertAllView ()
#property (nonatomic, strong) NSString *aString;
#end
#implementation OSAlertAllView
+ (void)alertWithTitle:(NSString *)title message:(NSString *)msg cancelTitle:(NSString *)cancel inView:(UIViewController *)view
{
__weak __typeof(self) weakSelf = self;
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:cancel style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
// I'd like to reference a variable or method here
weakSelf.aString = #"Apples"; // Not sure if this would be necessary
self.aString = #"Apples"; // Member reference type 'struct objc_class *' is a pointer Error
[self someMethod]; // No known class method Error
}];
[alert addAction:defaultAction];
[view presentViewController:alert animated:YES completion:nil];
}
- (void)someMethod {
}
The + at the start of your alertWithTitle... method means it is a class method. When you call it, self will be the class OSAlertAllView, not an instance of type OSAlertAllView.
There are two ways you could change it to make it work.
Change the + at the start of the method to a - making it an instance method. Then you would call it on an instance instead of the class.
// Old Class Method Way
[OSAlertAllView alertWithTitle:#"Title" message:#"Message" cancelTitle:#"Cancel" inView:viewController];
// New Instance Methods Way
OSAlertAllView *alert = [OSAlertAllView new];
[alert alertWithTitle:#"Title" message:#"Message" cancelTitle:#"Cancel" inView:viewController];
The other way would be to create an instance to OSAlertAllView inside of you alertWithTitle... and replace the uses of self with that object.
+ (void)alertWithTitle:(NSString *)title message:(NSString *)msg cancelTitle:(NSString *)cancel inView:(UIViewController *)view
{
OSAlertAllView *alertAllView = [OSAlertAllView new];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:cancel style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
alertAllView.aString = #"Apples";
[alertAllView someMethod];
}];
[alert addAction:defaultAction];
[view presentViewController:alert animated:YES completion:nil];
}