Есть ли разница между YES/NO,TRUE/FALSE и true / false в objective-c?



простой вопрос на самом деле; есть ли разница между этими значениями (и есть ли разница между BOOL и bool)? Коллега отметил, что они оценивают разные вещи в Objective-C, но когда я посмотрел на типов в их .H файлы, да / TRUE / true все были определены как 1 и NO / FALSE / false были определены как 0. Разве есть разница?

645   9  

9 ответов:

нет никакой практической разницы предоставил вы используете BOOL переменные логическими значениями. C обрабатывает булевы выражения, основанные на том, оцениваются ли они в 0 или нет 0. Итак:

if(someVar ) { ... }
if(!someVar) { ... }

означает то же, что

if(someVar!=0) { ... }
if(someVar==0) { ... }

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

обратите внимание, что там и разница, если вы назначаете тупые значения так называемому BOOL переменная и тест для определенных значений, поэтому всегда используйте их как логические значения и назначайте их только из их #define значения.

важно, никогда не тестируйте булевы, используя сравнение символов - это не только рискованно, потому что someVar может быть присвоено ненулевое значение, которое не является да, но, на мой взгляд, что более важно, он не может выразить намерение правильно:

if(someVar==YES) { ... } // don't do this!
if(someVar==NO ) { ... } // don't do this either!

другими словами, используйте конструкции, как они предназначены и документированы для использования, и вы избавите себя от мира боли в C.

Я верю, что есть и разницу между bool и BOOL, проверьте эту веб-страницу для объяснения, почему:
http://iosdevelopertips.com/objective-c/of-bool-and-yes.html

, потому что BOOL это unsigned char вместо примитивного типа, переменные типа BOOL может содержать значения, отличные от YES и NO.

рассмотрим этот код:

BOOL b = 42;

if (b) {
    printf("b is not NO!\n");
}

if (b != YES) {
    printf("b is not YES!\n");
}

выход:

b не нет!
b - это не да!

для большинства людей это ненужная забота, но если вы действительно хотите логическое значение, лучше использовать bool. Я должен добавить: iOS SDK обычно использует BOOL на его интерфейсных определениях, так что это аргумент, чтобы придерживаться BOOL.

Я сделал исчерпывающий тест на этом. Мои результаты должны говорить сами за себя:

//These will all print "1"
NSLog(@"%d", true == true);
NSLog(@"%d", TRUE == true);
NSLog(@"%d", YES  == true);
NSLog(@"%d", true == TRUE);
NSLog(@"%d", TRUE == TRUE);
NSLog(@"%d", YES  == TRUE);
NSLog(@"%d", true == YES);
NSLog(@"%d", TRUE == YES);
NSLog(@"%d", YES  == YES);

NSLog(@"%d", false == false);
NSLog(@"%d", FALSE == false);
NSLog(@"%d", NO    == false);
NSLog(@"%d", false == FALSE);
NSLog(@"%d", FALSE == FALSE);
NSLog(@"%d", NO    == FALSE);
NSLog(@"%d", false == NO);
NSLog(@"%d", FALSE == NO);
NSLog(@"%d", NO    == NO);


//These will all print "0"
NSLog(@"%d", false == true);
NSLog(@"%d", FALSE == true);
NSLog(@"%d", NO    == true);
NSLog(@"%d", false == TRUE);
NSLog(@"%d", FALSE == TRUE);
NSLog(@"%d", NO    == TRUE);
NSLog(@"%d", false == YES);
NSLog(@"%d", FALSE == YES);
NSLog(@"%d", NO    == YES);

NSLog(@"%d", true == false);
NSLog(@"%d", TRUE == false);
NSLog(@"%d", YES  == false);
NSLog(@"%d", true == FALSE);
NSLog(@"%d", TRUE == FALSE);
NSLog(@"%d", YES  == FALSE);
NSLog(@"%d", true == NO);
NSLog(@"%d", TRUE == NO);
NSLog(@"%d", YES  == NO);

выход:

2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.072 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.076 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.082 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.091 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.092 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.097 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.098 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.101 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0

вы можете прочитать ответы на этот вопрос. Таким образом, в Objective-C (из определения в objc.h):

typedef signed char        BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used.
#define OBJC_BOOL_DEFINED


#define YES             (BOOL)1
#define NO              (BOOL)0

основной (опасно!) разница между true и YESнаходится в сериализации JSON.

например, у нас есть запрос сервера типа JSON и нужно отправить true / false в JSON sence:

NSDictionary *r1 = @{@"bool" : @(true)};
NSDictionary *r2 = @{@"bool" : @(YES)};
NSDictionary *r3 = @{@"bool" : @((BOOL)true)};

затем мы преобразуем его в строку JSON перед отправкой как

NSData *data = [NSJSONSerialization  dataWithJSONObject:requestParams options:0 error:nil];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

результат

jsonString1 // {"bool":1}
jsonString2 // {"bool":true}
jsonString3 // {"bool":true}

из-за логики API jsonString1 может привести к ошибке.

так что будьте осторожны с булевыми в Objective-C.

P. S. Вы можете использовать

@{@"bool" : @"true"}; // {"bool":true}

Я думаю, что они добавляют Да / нет, чтобы быть более понятным во многих случаях. Например:

[button setHidden:YES];

звучит лучше, чем

[button setHidden:TRUE];

есть тонкая ошибка, которую никто не упомянул здесь, что я думал, что включу... скорее логическая ошибка, чем что-либо:

int i = 2;
if(i);        //true
if(i==YES);   // false
if((!!i)==YES); //true

так что проблема здесь только в том, что (YES==1) и в C сравнение не является логическим, а основано на значении.

, потому что YES это просто #define (а не что-то присущее язык), это должно быть какое-то значение, а 1 имеет наибольший смысл.

сначала давайте рассмотрим, что такое истина и ложь и что дает им смысл в первую очередь.

мы можем построить структуру, называемую if a then b else c в лямбда-исчислении следующим образом:

(\ifThenElse. <use if then else>)(\a. \b. \c. a b c)

в JavaScript, это выглядит так:

(function(ifThenElse) {
    // use ifThenElse
})(function(a) {
    return function(b) {
        return function(c) {
            return a(b)(c);
        };
    };
});

чтобы ifThenElse был полезен, нам нужна функция "true", которая выбирает либо вправо, либо влево, и делает это, игнорируя другой параметр, или функция "false", которая выбирает параметр " true" не берет.

мы можем определить эти функции следующим образом:

(\true. <use true>)(\a. \b. a) and (\false. <use false>)(\a. \b. b)

в JavaScript это выглядит так:

(function(True) {
    // use True
})(function(a) {
     return function(b) {
         return a;
     }
});

(function(False) {
    // use True
})(function(a) {
     return function(b) {
         return b;
     }
});

теперь мы можем сделать следующее

(\true. \false. \ifThenElse. \doThis. \doThat. ifThenElse true doThis doThat)
(\a. \b. a)(\a. \b. b)(\a. \b. \c. a b c)(\a. ())(\a. ())

С doThis и doThat being (\a. ()) поскольку лямбда-исчисление не предлагает никаких услуг, таких как печать/математика/строки, все, что мы можем сделать, это ничего не делать и сказать, что мы это сделали (а затем обмануть, заменив его услугами в нашей системе, которые обеспечивают побочные эффекты, которые мы хотим)

так давайте посмотрим на это в действии.

(function(True) {
    return (function(False) {
        return (function(ifThenElse) {
            return (function(doThis) {
                return (function(doThat) {
                    return ifThenElse(True)(doThis)(doThat);
                });
            });
        });
    })
})(function(a) {
     return function(b) {
         return a;
     }
})(function(a) {
     return function(b) {
         return b;
     }
})(function(a) {
    return function(b) {
        return function(c) {
            return a(b)(c);
        };
    };
})(function(a) { console.log("you chose LEFT!"); })
(function(a) {console.log("you chose RIGHT");})();

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

обратите внимание, что имя True/False не имеет никакого внутреннего значения, мы можем легко переименовать их в yes/no, left/right, right/left, zero/one, apple/orange. Это имеет значение в что какой бы выбор ни был сделан, он вызван только тем, какой выбор сделал его. Поэтому, если" левый " напечатан, мы знаем, что выбор может быть только истинным, и на основе этого знания мы можем направлять наши дальнейшие решения.

Итак

function ChooseRight(left) {
    return function _ChooseRight_inner(right) {
        return right;
    }
}
function ChooseLeft(left) {
    return function _ChooseLeft_inner(right) {
        return left;
    }
}

var env = {
    '0': ChooseLeft,
    '1': ChooseRight,
    'false': ChooseRight,
    'true': ChooseLeft,
    'no': ChooseRight
    'yes': ChooseLeft,
    'snd': ChooseRight,
    'fst': ChooseLeft
};
var _0 = env['0'];
var _1 = env['1'];
var _true = env['true'];
var _false = env['false'];
var yes = env['yes'];
var no = env['no'];

// encodes church zero or one to boolean
function lambda_encodeBoolean(self) {
    return self(false)(true);
}
// decodes a Boolean to church zero or one
function lambda_decodeBoolean(self) {
    console.log(self, self ? env['true'] : env['false']);
    return self ? env['true'] : env['false'];
}

lambda_decodeBoolean('one' === 'two')(function() {
    console.log('one is two');
})(function() {
    console.log('one is not two');
})();

lambda_decodeBoolean('one' === 'one')(function() {
    console.log('one is one');
})(function() {
    console.log('one is not one');
})();

нет, да / нет-это другой способ ссылаться на TRUE / FALSE (1/0)

Comments

    Ничего не найдено.