Какао - переключение BOOL без повторения его названия - PullRequest
9 голосов
/ 23 июля 2010

Если BOOL имеет хорошее короткое имя, достаточно просто написать:

myBOOL = !myBOOL;

Но что, если BOOL имеет длинное имя?

objectWithLongishName.memberWithLongishName.submember.myBOOL = !(objectWithLongishName.memberWithLongishName.submember.myBOOL);  

. , , выглядит не очень красиво.

Мне интересно, есть ли простой способ переключения BOOL без повторного ввода его имени?

Ответы [ 6 ]

10 голосов
/ 23 июля 2010

Вот еще один:

MyBooleanYaddaYadda ^= YES;

Это довольно хрупко - оно сломается на унаследованном коде C, что означает, что любое ненулевое целое число оценивается как true Но опять же, то же самое будет и с кодом Apple Framework - в Какао я встречал случаи, когда ненулевое, не одно int, при передаче в виде BOOL, не вызывало бы того же эффекта, что и передача YES.

Однако он не полагается на битовую комбинацию YES - только на NO, равный 0. Что в значительной степени является данностью, учитывая то, как C интерпретирует целые числа как логические значения. Кроме того, он не принимает фактический тип данных BOOL (который, кстати, на Какао signed char).

Битовая комбинация YES на Какао равна 1. Но это не универсальное соглашение. На некоторых платформах без встроенного логического типа данных целочисленная константа, которая служит логической ИСТИНОЙ, равна -1 - все в одном бите. Это 0xFFFFFFFF, если интерпретируется как неподписанный. Это кодирование имеет смутное преимущество в том, что битовое НЕ (оператор ~ в C) эквивалентно логическому NOT (оператор! В C). То есть ~ 0xFFFFFFFF равно 0, т.е. е. ~ ИСТИНА ЛОЖЬ. Не работает, если TRUE определено как 1.

10 голосов
/ 23 июля 2010
#define NOT(b) (b) = !(b)

NOT(MyBooleanVariableWithAFreakishlyLongName);

Или, если это Цель C ++:

inline void NOT(BOOL &b)
{
    b = !b;
}
9 голосов
/ 23 июля 2010

Нет, в (Objective-) C нет очевидного способа сделать то, что вы описываете (без использования макроса препроцессора), но смотрите ответ Севы для возможного (хотя и потенциально хрупкого) решения. Что еще более важно, что-то вроде objectWithLongishName.memberWithLongishName.submember.myBOOL указывает на нарушение Закона Деметры ; вы должны предоставлять submember напрямую любой кодовой единице, которой требуется доступ submember.myBOOL.

6 голосов
/ 23 июля 2010

Написать метод для класса submember, который переключает его для вас?

- (void) toggleMyBOOL {
  self.myBool = !self.myBool;
}

Тогда вы можете сделать:

[objectWithLongishName.memberWithLongishName.submember toggleMyBOOL];
2 голосов
/ 23 июля 2010

Используйте XOR. В Си это ^.

BOOL x = YES;
x ^= YES; // it's now NO
x ^= YES; // it's now YES
x ^= YES; // it's now NO
x ^= YES; // it's now YES
x ^= YES; // it's now NO
x ^= YES; // it's now YES
...

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

0 голосов
/ 23 июля 2010

У вас есть прекрасный набор ответов, сфокусированных на переключении ДА на НЕТ или наоборот, но нет ответов , которые затронули то, что в коде представляется архитектурной проблемой.

Ну, некоторые ответы.Я слепой.

А именно, у вас есть это:

objectWithLongishName.memberWithLongishName.submember.myBOOL =
    !(objectWithLongishName.memberWithLongishName.submember.myBOOL);  

Это пахнет как потенциальное нарушение инкапсуляции.В частности (и предполагая, что это уровень модели), это означает, что связность подграфа объектов открыто выставляется - фактически сглаживается - точкой входа этого пути;независимо от того, что objectWithLongishName должно теперь иметь достаточно глубокие знания внутренних объектов на остальной части пути.

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

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

...