Show keyboard when Textfield inside Alert in WkWebView is tapped - objective-c

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

Related

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

UIAlertController automatically dismisses in iOS 10

I have a UIAlertController in my AppDelegate and present it with my rootViewController when I receive a notification. But when the alert view pops up, it quickly dismisses itself instead of waiting for a tap event on the "Ok" button... Here's my code in AppDelegate.m. Any idea? Thanks!
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
[self showNotification:"Success message here"];
}
- (void)showNotification:(NSString *)text {
UIAlertController* avc = [UIAlertController alertControllerWithTitle:#"Success" message:text
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:#"Ok" style:UIAlertActionStyleCancel handler:nil];
[avc addAction:ok];
[self.window.rootViewController presentViewController:avc animated:true completion:nil];
}
EDIT: I have another view controller; call it X. X's viewDidLoad function has a timer counting down before X dismisses itself and presents another view controller. I noticed an interesting timing issue here: when the notification comes slowly enough so that the UIAlertController appears after X's timer is up and another view controller has been presented, the alertController doesn't dismiss itself. If the opposite happens - the notification comes quickly enough making the UIAlertController appears before X dismisses itself, then the whole AlertController will be flushed when the timer is up (which makes sense, I guess...). How can I prevent this from happening?
You can use perform selector method, like this:
- (void)showNotification:(NSString *)text {
UIAlertController* avc = [UIAlertController alertControllerWithTitle:#"Success" message:text
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:#"Ok" style:UIAlertActionStyleCancel handler:nil];
[avc addAction:ok];
[self performSelector:#selector(dissmissAlert:) withObject:avc afterDelay:3.0];
[self.window.rootViewController presentViewController:avc animated:true completion:nil];
}
-(void)dissmissAlert:(UIAlertController *) alert{
[alert dismissViewControllerAnimated:true completion:nil];
}

insert UITextField (from a UIAlertController) into an NSMutableArray

Hello I am tying to insert user input attained from an alert txtfield into a mutable array.
So, I have a tableView with a button to add a additional row. When the button is pressed the user can enter a message.
I would like to have that message be inserted into my array.
I was going to use the method clickedButtonAtIndex but Xcode states that that method is now deprecated.
Is there any other way to go about doing this??
here is the code for my array:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.exampleMessages = [[NSMutableArray alloc]initWithObjects:#"Example Message..", #"Example Message..",#"Example Message..",#"Example Message..",#"Example Message..", #"Example Message..",#"Example Message..",#"Example Message..", nil];}
here is my function that is executed once the add row button is pressed:
- (void)insertNewObject
//function that is executed after a new object is inserted
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#""
message:nil
preferredStyle:UIAlertControllerStyleAlert];
//create a UIAlert named alert
[alert addTextFieldWithConfigurationHandler:^(UITextField *messageTextField) {
messageTextField.placeholder = NSLocalizedString(#"message content", #"Message");
}];
//add a UITextField to the UIAlert
UIAlertAction *messageAction = [UIAlertAction
actionWithTitle:NSLocalizedString(#"Add", #"Message action")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
UITextField *userMessage = alert.textFields.firstObject;
NSLog(#"%#", userMessage);
//capture the value of the UITextField
}];
//add a button called "add"
UIAlertAction *cancelAction = [UIAlertAction
actionWithTitle:NSLocalizedString(#"Cancel", #"Cancel action")
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action) {}];
//add a button called "cancel"
[alert addAction:messageAction];
//add the add button to the alert
[alert addAction:cancelAction];
//add the cancel button to the alert
[self presentViewController:alert animated:YES completion:nil];
//present the alert to the UI
}
In the code right here I am capturing the value and storing it in a variable but now how do I put it in my array?
UITextField *userMessage = alert.textFields.firstObject;
NSLog(#"%#", userMessage);
//capture the value of the UITextField
Replace comment
//capture the value of the UITextField
with the following line:
[self.exampleMessages addObject:userMessage.text ?: #""];
Looks like after that you will need to update table view, via [self.tableView reloadData] or similar call.

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