Как уменьшить высокую цикломатическую сложность при инициализации из NSUserDefaults

У меня есть этот инициализатор для объекта:

-(id)init
{
    self = [super init];
    if (self) {
        if([[NSUserDefaults standardUserDefaults] objectForKey:kTermsAccepted] != nil){
            _termsAccepted = [[NSUserDefaults standardUserDefaults] boolForKey:kTermsAccepted];
        }
        if([[NSUserDefaults standardUserDefaults] objectForKey:kInitialSetupCompleted] != nil){
            _initialSetupCompleted = [[NSUserDefaults standardUserDefaults] boolForKey:kInitialSetupCompleted];
        }
        if([[NSUserDefaults standardUserDefaults] objectForKey:kDashboardMessage] != nil){
            _dashboardMessage = [[NSUserDefaults standardUserDefaults] objectForKey:kDashboardMessage];
        } else{
            _dashboardMessage = [[NSBundle mainBundle] localizedStringForKey:kDMDefaultDashboardMessage value:kDMDefaultDashboardMessage table:nil];
        }
        //50 other if statements
    }
    return self;
}

Что было бы лучшим способом сделать это, чтобы я не получал эти предупреждения при выполнении анализа OCLint?

Спасибо!


person Jan    schedule 16.03.2016    source источник


Ответы (1)


Все переменные экземпляра инициализируются 0; это означает, что BOOLs инициализируются как NO. Поэтому эффект от:

if([[NSUserDefaults standardUserDefaults] objectForKey:kTermsAccepted] != nil){
    _termsAccepted = [[NSUserDefaults standardUserDefaults] boolForKey:kTermsAccepted];
}

... это: если есть сохраненное значение, установите для него _termsAccepted. В противном случае _termsAccepted будет NO.

boolForKey: имеет задокументированное возвращаемое значение:

Если логическое значение связано с defaultName в пользовательских значениях по умолчанию, возвращается это значение. В противном случае возвращается NO.

Итак, сравните и сопоставьте только:

_termsAccepted = [[NSUserDefaults standardUserDefaults] boolForKey:kTermsAccepted];

... в этом случае чистый результат будет таким: если есть сохраненное значение, установите для него _termsAccepted. В противном случае _termsAccepted будет NO.

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

РЕДАКТИРОВАТЬ: было правильно указано, что я упустил тот факт, что BOOL не используются исключительно.

Используйте -[NSUserDefaults registerDefaults:], чтобы установить запасные значения. Они хранятся в памяти после установки, но не записываются в хранилище. Затем пользовательские значения по умолчанию сами будут обрабатывать случай «если значение не сохранено, использовать это значение» для всех типов объектов.

person Tommy    schedule 16.03.2016
comment
Хорошо, возможно, мой вопрос был не ясен. Или, может быть, это так. Но там, где указано /50 другие операторы if, есть и другие типы переменных, а не только BOOL. У меня есть NSStrings, NSMutableArrays, NSDate и т. д. Будет ли прямое назначение работать с любым типом? - person Jan; 16.03.2016
comment
На самом деле я добавил одну из своих ситуаций, когда я хочу инициализировать значение по умолчанию, если NSUserDefaults там нет... - person Jan; 16.03.2016
comment
Я, наверное, недочитал вопрос. Моя вина. После редактирования попробуйте использовать -[NSUserDefaults registerDefaults:], чтобы установить значения, которые NSUserDefaults должны возвращать, если значения не найдены. Они никогда не перезаписывают фактически сохраненную информацию и сами никогда не записываются в хранилище. Это резервный вариант только в памяти. - person Tommy; 16.03.2016
comment
Потрясающий Томми, большое спасибо. Я попробую это и вернусь позже, чтобы выбрать как принятое, если все работает (что, я думаю, так и должно быть!). Спасибо - person Jan; 16.03.2016
comment
Я поддерживаю рекомендацию использовать registerDefaults:. Я демонстрирую пример в этом ответе: stackoverflow.com/a/4530149/277952 - person NSGod; 16.03.2016