Подтвердить что ты не робот

Каковы общие случаи использования __IPHONE_OS_VERSION_MAX_ALLOWED?

Каковы ситуации, в которых вы использовали бы проверку __IPHONE_OS_VERSION_MAX_ALLOWED? Как насчет __IPHONE_OS_VERSION_MIN_REQUIRED?

4b9b3361

Ответ 1

Важно понимать, что это константы времени компиляции, поэтому они не являются полезными для обнаружения во время выполнения той версии платформы или ОС, на которой вы работаете (например, если вы работаете на iPad против iPhone).

Что эти константы делают, это позволяет вам во время компиляции определять, будет ли этот код создан для данного SDK или цели развертывания. Например, если вы написали библиотеку с открытым исходным кодом, которая содержит код, который работает только при компиляции с iOS 5 SDK, вы можете включить эту проверку, чтобы определить, какой SDK скомпилирован для:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 50000
    //you can use iOS 5 APIs here because the SDK supports them
    //but the code may still crash if run on an iOS 4 device
#else
    //this code can't use iOS 5 APIs as the SDK version doesn't support them
#endif

Или, наоборот, если вы хотите узнать, какая минимальная версия ОС является таковой...

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
    //minimum deployment target is 5.0, so it safe to use iOS 5-only code
#else
    //you can use iOS5 APIs, but the code will need to be backwards
    //compatible or it will crash when run on an iOS 4 device
#endif

Это отличается от обнаружения во время выполнения операционной системы. Если вы скомпилируете код в первом примере выше с помощью iOS 4 SDK, он будет использовать ваш iOS 4-безопасный код, но не будет использовать любые функции iOS 5 при работе на устройстве iOS 5. Если вы построите его с помощью SDK iOS 5, установите цель развертывания на iOS 4 и попробуйте запустить его на устройстве iOS 4, он будет компилироваться и устанавливать нормально, но все равно может потерпеть крах во время выполнения, потому что API iOS 5 там нет.

Во втором примере выше, если вы установили цель развертывания в iOS 4 или ниже, то он будет использовать путь к безопасному коду iOS 4, но если вы установите цель развертывания для iOS 5, она не будет запущена вообще на устройстве iOS 4 (он откажется устанавливать).

Чтобы создать приложение, работающее на iOS 4 и 5, и по-прежнему можно использовать функции iOS 5, если они доступны, вам необходимо выполнить проверку во время выполнения. Чтобы обнаружить версию iOS во время выполнения, вы можете сделать это:

if ([[[UIDevice currentDevice] systemVersion] compare:@"5.0.1" options:NSNumericSearch] != NSOrderedAscending) {
    //running on iOS 5.0.1 or higher
}

Но это означает, что нужно отслеживать, какие именно функции API были добавлены в версию ОС, которая является неуклюжей и должна быть сделана только в качестве последнего средства. Обычно лучше использовать функцию обнаружения признаков, например:

if ([SomeClass class]) {
    //this class exists
}

if ([SomeClass instancesRespondToSelector:@selector(someMethod:)]) {
    //this method exists
}

Кроме того, чтобы обнаружить во время выполнения, если вы находитесь на iPad или iPhone, вы можете сделать это:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    //on an ipad
}

Выполнение этих проверок во время выполнения позволяет создать одно приложение, работающее на нескольких устройствах и версиях iOS, и может использовать преимущества каждой платформы.

Ответ 2

практическая реализация/пример использования экземпляровRespondToSelector:, расширение на @Nick Lockwood anwser:

+(BOOL) testIsHeaderInConnectData:(NSData *) connectData {
    static NSString *headString = nil;
    static NSData *headData = nil;
    static BOOL rangeCheckOk = NO;
    static BOOL rangeCheckTestComplete = NO;
    if (!rangeCheckTestComplete) {
        rangeCheckOk = [NSData instancesRespondToSelector:@selector(rangeOfData:options:range:)]; 
        headString = @"HEAD ";
        headData = (rangeCheckOk?[[NSData alloc] initWithBytes:headString.UTF8String length:headString.length]:nil);
        headString = (rangeCheckOk?nil:[[NSString alloc ]initWithString:headString]);
        rangeCheckTestComplete = YES;
    }

    NSInteger testLength = connectData.length;
    BOOL isHeader = testLength > 5;
    if (isHeader) {
        testLength = (testLength < 128?testLength:128);
        if (rangeCheckOk) {
             isHeader = [connectData rangeOfData:headData options:0 range:(NSRange){0,testLength}].location!=NSNotFound;
        } else {
            NSString *headStart = [[NSString alloc] initWithBytes:connectData.bytes length:testLength encoding:NSUTF8StringEncoding];
            isHeader = [headStart rangeOfString:headString].location!=NSNotFound;
            [headStart release];
        }
    }
    return isHeader;
}