UIAlertView / UIAlertController iOS 7 및 iOS 8 호환성
Swift를 사용하여 앱을 작성하고 있으며 경고를 표시해야합니다. 앱은 iOS 7 및 iOS 8과 호환되어야합니다. 이후 UIAlertView
로 대체되었습니다 UIAlertController
, 내가 어떻게이 경우 확인할 수 있습니다 UIAlertController
시스템 버전을 확인하지 않고 사용할 수 있습니까? 저는 Apple이 API의 가용성을 확인하기 위해 장치의 시스템 버전을 확인하지 말 것을 권장한다고 들었습니다.
이것은 내가 iOS 8에 사용하고 있지만 iOS 7에서 " dyld: Symbol not found: _OBJC_CLASS_$_UIAlertAction
" 와 함께 충돌합니다 .
let alert = UIAlertController(title: "Error", message: message, preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
alert.addAction(cancelAction)
presentViewController(alert, animated: true, completion: nil)
iOS 8 용 UIAlertView를 사용하면 다음 경고가 표시됩니다. Warning: Attempt to dismiss from view controller <_UIAlertShimPresentingViewController: 0x7bf72d60> while a presentation or dismiss is in progress!
감지 패턴은 Objective-C 스타일과 동일합니다.
현재 활성 런타임에이 클래스를 인스턴스화 할 수 있는지 여부를 감지해야합니다.
if objc_getClass("UIAlertController") != nil {
println("UIAlertController can be instantiated")
//make and use a UIAlertController
}
else {
println("UIAlertController can NOT be instantiated")
//make and use a UIAlertView
}
OS 버전에 따라 이것을 시도하고 해결하지 마십시오. OS가 아닌 능력을 감지해야합니다 .
편집하다
이 답변에 대한 원래 감지기는 최적화에서 NSClassFromString("UIAlertController")
실패 -O
하므로 릴리스 빌드에서 작동하는 현재 버전으로 변경되었습니다.
2 편집
NSClassFromString
Xcode 6.3 / Swift 1.2의 모든 최적화에서 작동합니다.
신속하지 않은 코드의 경우 순수 객관적인 C는 다음을 수행합니다.
if ([UIAlertController class])
{
// use UIAlertController
UIAlertController *alert= [UIAlertController
alertControllerWithTitle:@"Enter Folder Name"
message:@"Keep it short and sweet"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action){
//Do Some action here
UITextField *textField = alert.textFields[0];
NSLog(@"text was %@", textField.text);
}];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
NSLog(@"cancel btn");
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:ok];
[alert addAction:cancel];
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = @"folder name";
textField.keyboardType = UIKeyboardTypeDefault;
}];
[self presentViewController:alert animated:YES completion:nil];
}
else
{
// use UIAlertView
UIAlertView* dialog = [[UIAlertView alloc] initWithTitle:@"Enter Folder Name"
message:@"Keep it short and sweet"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK", nil];
dialog.alertViewStyle = UIAlertViewStylePlainTextInput;
dialog.tag = 400;
[dialog show];
}
두 가지 상황을 계속해서 작성해야해서 짜증이 나서 iOS 7에서도 작동하는 호환 가능한 UIAlertController를 작성해서 GitHub에 올렸습니다. UIAlertController의 버튼과 동작을 추가하는 (훨씬 더 나은) 메서드를 복제하기 위해 최선을 다했습니다. Objective-C와 Swift 모두에서 작동합니다. 나는 Google에서 검색 할 때이 질문을 발견하고 다른 사람들에게 도움이 될 수 있다고 생각했기 때문에 이것을 게시하고 있습니다.
https://github.com/BayPhillips/compatible-alert-controller
이 코드를 사용하여 문제를 해결할 수 있습니다.
var device : UIDevice = UIDevice.currentDevice()!;
var systemVersion = device.systemVersion;
var iosVerion : Float = systemVersion.bridgeToObjectiveC().floatValue;
if(iosVerion < 8.0) {
let alert = UIAlertView()
alert.title = "Noop"
alert.message = "Nothing to verify"
alert.addButtonWithTitle("Click")
alert.show()
}else{
var alert : UIAlertController = UIAlertController(title: "Noop", message: "Nothing to verify", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style:.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
UIKit은 Required가 아닌 Optional로 표시되어야합니다.
Courtsey : -iOS 7 및 iOS 8에서 작동 할 수있는 경고
스위프트 2.0
if #available(iOS 8.0, *) {
} else {
}
이것이 공유 코드이고 UIAlertController가 존재하지 않는 iOS 7뿐만 아니라 iOS 8 확장 (UIAlertView 및 UIActionSheet이 제한된 API 인 경우)에서 코드를 사용할 수있는 가능성이있는 경우 다음을 참조하십시오. JVAlertController
iOS 7 및 iOS 8 확장에서 SDK 코드를 안전하게 사용하기 위해 착수 한 것은 iOS 7에 대한 UIAlertController의 API 호환 백 포트입니다.
범주를 사용하여 해결할 수 있습니다 (단, Swift로 변환해야 함).
@implementation UIView( AlertCompatibility )
+( void )showSimpleAlertWithTitle:( NSString * )title
message:( NSString * )message
cancelButtonTitle:( NSString * )cancelButtonTitle
{
if( [[UIDevice currentDevice] isSystemVersionLowerThan: @"8"] )
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: title
message: message
delegate: nil
cancelButtonTitle: cancelButtonTitle
otherButtonTitles: nil];
[alert show];
}
else
{
// nil titles break alert interface on iOS 8.0, so we'll be using empty strings
UIAlertController *alert = [UIAlertController alertControllerWithTitle: title == nil ? @"": title
message: message
preferredStyle: UIAlertControllerStyleAlert];
UIAlertAction *defaultAction = [UIAlertAction actionWithTitle: cancelButtonTitle
style: UIAlertActionStyleDefault
handler: nil];
[alert addAction: defaultAction];
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
[rootViewController presentViewController: alert animated: YES completion: nil];
}
}
@end
@implementation UIDevice( SystemVersion )
-( BOOL )isSystemVersionLowerThan:( NSString * )versionToCompareWith
{
if( versionToCompareWith.length == 0 )
return NO;
NSString *deviceSystemVersion = [self systemVersion];
NSArray *systemVersionComponents = [deviceSystemVersion componentsSeparatedByString: @"."];
uint16_t deviceMajor = 0;
uint16_t deviceMinor = 0;
uint16_t deviceBugfix = 0;
NSUInteger nDeviceComponents = systemVersionComponents.count;
if( nDeviceComponents > 0 )
deviceMajor = [( NSString * )systemVersionComponents[0] intValue];
if( nDeviceComponents > 1 )
deviceMinor = [( NSString * )systemVersionComponents[1] intValue];
if( nDeviceComponents > 2 )
deviceBugfix = [( NSString * )systemVersionComponents[2] intValue];
NSArray *versionToCompareWithComponents = [versionToCompareWith componentsSeparatedByString: @"."];
uint16_t versionToCompareWithMajor = 0;
uint16_t versionToCompareWithMinor = 0;
uint16_t versionToCompareWithBugfix = 0;
NSUInteger nVersionToCompareWithComponents = versionToCompareWithComponents.count;
if( nVersionToCompareWithComponents > 0 )
versionToCompareWithMajor = [( NSString * )versionToCompareWithComponents[0] intValue];
if( nVersionToCompareWithComponents > 1 )
versionToCompareWithMinor = [( NSString * )versionToCompareWithComponents[1] intValue];
if( nVersionToCompareWithComponents > 2 )
versionToCompareWithBugfix = [( NSString * )versionToCompareWithComponents[2] intValue];
return ( deviceMajor < versionToCompareWithMajor )
|| (( deviceMajor == versionToCompareWithMajor ) && ( deviceMinor < versionToCompareWithMinor ))
|| (( deviceMajor == versionToCompareWithMajor ) && ( deviceMinor == versionToCompareWithMinor ) && ( deviceBugfix < versionToCompareWithBugfix ));
}
@end
그럼 그냥 전화 해
[UIView showSimpleAlertWithTitle: @"Error" message: message cancelButtonTitle: @"OK"];
그러나 시스템 버전을 확인하고 싶지 않다면
BOOL lowerThaniOS8 = NSClassFromString( @"UIAlertController" ) == nil;
카테고리 UIView (AlertCompatibility) 내부
위에서 설명한대로 iOS 7- UIAlertView 및 iOS 8+ UIAlertController를 모두 사용하고 UIAlertController 블록이 UIAlertView의 델리게이트 (예 : MyController)를 호출하도록하려는 경우 alertView : didDismissWithButtonIndex 메소드가 결과를 계속 처리하도록하려면 다음을 수행하는 방법의 예입니다. 그:
if ([UIAlertController class]) {
MyController * __weak mySelf = self;
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:alertTitle
message:alertMessage
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction
actionWithTitle:alertCancel
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action)
{
[mySelf alertView:nil didDismissWithButtonIndex:0];
}
];
...
이것은 블록에서 자신 을 캡처하기 위해 Apple의 권장 사항을 사용합니다. 자신 을 캡처 할 때 강력한 참조주기를 피하십시오 .
물론이 메서드는 컨트롤러에 UIAlertView가 하나만 있다고 가정하므로 nil을 대리자 메서드에 값으로 전달합니다. 그렇지 않으면 "가짜"UIAlertView를 인스턴스화 (및 태그)하여 alertView : didDismissWithButtonIndex에 전달해야합니다.
Here to check two way of UIAlertView
and UIAlertContoller.
Check 1 : iOS verstion check UIAlertController Class.
if #available(iOS 8.0, *) {
// UIALertController
let alert = UIAlertController(title: "Alert", message: "Alert after 8.0", preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
alert.addAction(cancelAction)
presentViewController(alert, animated: true, completion: nil)
} else {
// UIALertView
UIAlertView(title: "Alert", message: "Alert below iOS V 8.0", delegate: nil, cancelButtonTitle: "OK").show()
}
Check 2 : check UIAlertController
nil then iOS version below 8.0.
if objc_getClass("UIAlertController") != nil {
// UIALertController
let alert = UIAlertController(title: "Alert", message: "Alert after 8.0", preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
alert.addAction(cancelAction)
presentViewController(alert, animated: true, completion: nil)
}
else {
// UIALertView
UIAlertView(title: "Alert", message: "Alert below iOS V 8.0", delegate: nil, cancelButtonTitle: "OK").show()
}
If you want to be compatible with iOS 7, just don't use UIAlertController
. Simple as that.
UIAlertView
has not been replaced, it still works perfectly and will continue to work perfectly for the foreseeable future.
Here is my drag and drop swift solution:
//Alerts change in iOS8, this method is to cover iOS7 devices
func CozAlert(title: String, message: String, action: String, sender: UIViewController){
if respondsToSelector("UIAlertController"){
var alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: action, style: UIAlertActionStyle.Default, handler:nil))
sender.presentViewController(alert, animated: true, completion: nil)
}
else {
var alert = UIAlertView(title: title, message: message, delegate: sender, cancelButtonTitle:action)
alert.show()
}
}
Call like this:
CozAlert("reportTitle", message: "reportText", action: "reportButton", sender: self)
Beware this is only for the most basic alerts, you might need additional code for advanced stuff.
Try below code. It works fine for both iOS 8 and below version.
if (IS_OS_8_OR_LATER) {
UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action)
{
}];
[alertVC addAction:cancelAction];
[[[[[UIApplication sharedApplication] windows] objectAtIndex:0] rootViewController] presentViewController:alertVC animated:YES completion:^{
}];
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:msg delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
[alert show];
}
download alert class from this link and use it easily for ios 6 ,7 and 8
//Old code
**UIAlertView** *alert=[[**UIAlertView** alloc]initWithTitle:@"FreeWare" message:@"Welcome to Common class" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Ok", nil];
//New code
**MyAlertView** *alert=[[**MyAlertView** alloc]initWithTitle:@"FreeWare" message:@"Welcome to Common class" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Ok", nil];
In iOS8, there is a new class UIAlertController
that replaces UIAlertView
and UIActionSheet
. From iOS8 on, use UIAlertController, and for iOS8 and before use UIAlertView and UIActionSheet. I think that iOS8 added size classes
that change UIAlertView
display direction. See: https://github.com/wangyangcc/FYAlertManage
ReferenceURL : https://stackoverflow.com/questions/25111011/uialertview-uialertcontroller-ios-7-and-ios-8-compatibility
'Programing' 카테고리의 다른 글
Python matplotlib 다중 막대 (0) | 2020.12.15 |
---|---|
변수의 최소값에 해당하는 행을 그룹별로 추출 (0) | 2020.12.15 |
패닉이 발생했는지 확인하는 Rust 단위 테스트를 어떻게 작성합니까? (0) | 2020.12.15 |
Objective-C에서 상속과 범주의 차이점은 무엇입니까? (0) | 2020.12.15 |
grep을 사용하여`name =`바로 뒤에 무언가를 얻는 방법은 무엇입니까? (0) | 2020.12.15 |