问题
I am working on a project that uses UIAlertView
, now the problem is I have to replace all of the UIAlertView's
with UIAlertController's
and there are around 1250 of them in the code. I am planning to uses the existing Utility class to create a function that does this, following is what I am planning to do:
+(void)showAlert:(NSString *)title errorMessage:(NSString *)msg {
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alertController animated:YES completion:nil];
}
I have the following questions before doing this:
1 - Is this worth the efforts (Using UIAlertController
instead of UIAlertView
) ?
2 - How do I handle UIAlertView's
that had tags and different delegate implementation across hundreds of files ?
3 - The fourth line the function above gives an error : No known class method for selector 'presentViewController:animated:completion:'
Any help is greatly appreciated.
回答1:
You've to use UIAlertController
as UIAlertView
is deprecated.
Apple Doc says:
In apps that run in versions of iOS prior to iOS 8, use the UIAlertView class to display an alert message to the user. An alert view functions similar to but differs in appearance from an action sheet (an instance of UIActionSheet). 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. Availability
Alternatively, you can do this way. In your Utils
Class, do this:
+ (void)showAlertWithTitle:(NSString *)title message:(NSString *)msg controller:(id)controller {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:okAction];
[controller presentViewController:alertController animated:YES completion:nil];
}
Usage from your ViewController
class:
[Utils showAlertWithTitle:@"Camera" message:@"It seems that your device doesn't support camera. " controller: self];
If your existing UIAlertView
is having tags then you've to use the UIAlertViewController
class instead of the Util method.
Hope it helps.
回答2:
You can use a common alertcontroller class method. Here is an example how you can solve the no.4 error. Basically you pass also the viewController that wants to call the alertview.
+(UIImage *)showAlert:(NSString *)title errorMessage:(NSString *)msg inViewController:(id)vc {
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[vc presentViewController:alertController animated:YES completion:nil];
}
On the issue of alertviews with tags that require user input, to handle those inputs you might want to put the handler in and not let it nil and turn your method into a completionBlock method:
+(UIImage *)showAlert:(NSString *)title message:(NSString *)msg inViewController:(id)vc completedWithBtnStr:(void(^)(NSString* btnString))completedWithBtnStr {
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
completedWithBtnStr(@"Yes");
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
completedWithBtnStr(@"No");
}]];
[vc presentViewController:alertController animated:YES completion:nil];
}
An example of calling this is
[YourClass showAlert:@"Sure?" message:@"Delete this record?" inViewController:self completedWithBtnStr:^(NSString* btnString) {
if ([btnString isEqualToString:@"Yes"]) {
// delete record
}
}];
The parameter btnString can be anything really. The code is not tested so if you found error, do inform me.
回答3:
Answering your questions:
- It's definitely worth doing that. You have to use
UIAlertController
anyway in near future as ofUIAlertview
is deprecated. - Use blocks or protocol to get a callback when delegate methods in utility class are fired.
- Looks like you are presenting that on
NSObject
. Present on view class. In this case, you can usewindow
rootViewController
to present on
回答4:
+(void) showAlert
{
UIWindow* topWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
topWindow.rootViewController = [UIViewController new];
topWindow.windowLevel = UIWindowLevelAlert + 1;
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"title" message:@"message" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okButton = [UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
//Handle your yes please button action here
topWindow.hidden = YES;
//your ok button action handling
}];
[alertController addAction:okButton];
[topWindow makeKeyAndVisible];
[topWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
}
来源:https://stackoverflow.com/questions/43778603/show-uialertcontroller-from-a-common-utility-class