Programing

UIAlertView / UIAlertController iOS 7 및 iOS 8 호환성

lottogame 2020. 12. 15. 08:13
반응형

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

반응형