Как правильно проверить наличие пустой строки в Objective-C?


184

Я использовал это в своем приложении для iPhone

if (title == nil) {
    // do something
}

но он выдает какое-то исключение, и консоль показывает, что заголовок "(null)".

Итак, я использую это сейчас:

if (title == nil || [title isKindOfClass:[NSNull class]]) {
    //do something
}

В чем разница, и как лучше определить, является ли строка нулевой?


Ответы:


395

Как уже отмечали другие, в Какао / Objective C. есть много видов «нулей». Но еще одна вещь, на которую следует обратить внимание, - это то, что [title isKindOfClass: [NSNull class]] бессмысленно сложен, поскольку [NSNull null] задокументировано как синглтон, так что вы можете просто проверить на равенство указателей. См. Темы для Какао: Использование Нуль .

Таким образом, хороший тест может быть:

if (title == (id)[NSNull null] || title.length == 0 ) title = @"Something";

Обратите внимание, как вы можете использовать тот факт, что даже если title равен nil, title.length вернет 0 / nil / false, то есть 0 в этом случае, так что вам не нужно его использовать в особых случаях. Это то, к чему люди, плохо знакомые с Objective C, испытывают трудности с привыканием, особенно из других языков, где сообщения / методы вызывают ноль сбой.


Спасибо! Однако я задал этот вопрос в первую очередь потому, что получал исключение, потому что «заголовок» нулевой.
Тео Чунг Пинг

1
Какого типа должен быть заголовок? Например, если это строка NSString, я получаю следующее предупреждение: при сравнении различных типов Objective C 'struct NSNull *' и 'struct NSString *' отсутствует приведение. Есть ли способ удалить это (я не знаю, изменились ли вещи с тех пор этот вопрос был задан)?
боссмен

1
Подходит для публикации кода без его компиляции ;-). title, предположительно, является строкой NSString, но независимо от типа заголовка просто приведите null к общему типу id: (id) [NSNull null].
Питер Н Льюис

1
@JLT nil и [NSNull null] никогда не будут одинаковыми. [NSNull null] - это одноэлементный объект, который можно использовать в качестве замены для nil, когда нельзя использовать nil (например, в значении NSArray или NSDictionary). Таким образом, случай использования может быть, когда у вас есть NSArray необязательных строк, некоторые из которых могут быть нулевыми, и вы используете [NSNull null] в массиве для нулевых наблюдений. На практике этот тест требуется редко, только когда вы (или библиотека, которую вы используете!) Активно используете [NSNull null] в качестве заполнителя.
Питер Н Льюис

1
Попадая сюда из флаттера, и искать причину , почему Mapзначение элемента - что nullв Dart - не соответствует nilили NULLв Objective C. Причина в том , что это на самом деле NUNull null, а не NULLнулевой. Спасибо @PeterNLewis!
Александар

25

это так же просто, как

if([object length] >0)
{
  // do something
}

помните, что в цели C, если объект равен нулю, он возвращает 0 в качестве значения.

Это даст вам как нулевую строку, так и строку 0 длины.


49
Это не сработает, если object NSNull, но сначала нужно явно проверить это.
Джереми Мак

6
Вы также можете создать категорию для NSNull, чтобы она возвращала 0 к длине сообщения :)
Михай Тимар

1
Да, это потерпит крах, если объект NSNull.
Майк Гледхилл

Это будет вылетать , если объект равен NSNull
Joan

1
В дополнение к нераспознанной проблеме селектора NSNull это не будет дифференцироваться между указателем NSString, который равен nil, и строкой NSString, которая фактически существует, но по сути является пустой строкой. (Например, как буквальное object = @"";или object = nil;)
KellyTheDude

6

Обратитесь к следующим связанным статьям на этом сайте:

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

Также см. Этот связанный вопрос: Правильная проверка nil sqlite текстового столбца


Досадно, что у меня недостаточно «точек», чтобы добавить вторую гиперссылку (даже на что-то на этом сайте), см. Также: - stackoverflow.com/questions/598396/…
TimM

...позволь мне. Хотя вы должны иметь возможность редактировать свои собственные сообщения от представителя 0.
Рог

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

6

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

if ( ( ![myString isEqual:[NSNull null]] ) && ( [myString length] != 0 ) ) {
}

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


5

Что со всеми этими "работает на меня ответы"? Мы все пишем на одном языке, и правила

  1. Убедитесь, что ссылка не ноль
  2. Проверьте и убедитесь, что длина строки не равна 0

Это то, что будет работать для всех. Если данное решение только «работает для вас», это только потому, что поток вашего приложения не допускает сценарий, в котором ссылка может быть нулевой или длина строки равна 0. Правильный способ сделать это - метод, который будет обрабатывать что вы хотите во всех случаях.


4
Если ссылка nil(примечание: не «ноль»), то при отправке сообщения, например length, будет получено 0 (или соответствующее значение 0 для типа возврата метода). Это правило языка. Там нет необходимости проверять nilотдельно в этом случае.
ОАО

Я сказал ноль просто из-за привычек C ++, и если ваш код вызывает методы для nil-объектов, скорее всего, ваш код не работает. Вы обнаружите, что вызов методов для NULL / NIL (та же концепция), как правило, плохая идея на любом языке. То, что obj-c позволяет вам делать что-то подобное, не означает, что вы должны просто обойти ноль объектов и пытаться использовать их, не заботясь о них.
Ненчев

1
Отправка длины в ноль приводит к 0 - НО, длина отправки в NSNull создает исключение.
cdstamper

@nenchev Никто не говорит ничего о том, чтобы просто обойти nil-объекты, но проверка на nil, затем вызов метода и использование его возвращаемого значения IMO хуже, чем использование языковой функции, как будто она предназначена для использования, и проверка правильности возвращаемого значения метода впоследствии.
Кевин

@Kevin Я не уверен, насколько он на самом деле хуже, просто потому, что его языковая особенность не означает, что это здорово. Не проверка, может ли его значение null открыть путь к коду, что может привести к усложнению отслеживания ошибок во время выполнения. Обычно лучше убедиться, что ваши входные данные соответствуют вашим ожиданиям, и реагировать соответствующим образом, если это не так. Мне лично не нравится «особенность» - не получать исключения во время выполнения при попытке отправить сообщение нулевому объекту, поскольку это часто позволяет упустить некоторые ошибки во время выполнения.
Ненчев

4

Если вы хотите проверить все ноль / пустые объекты (например, пустые строки или пустые массивы / наборы), вы можете использовать следующее:

static inline BOOL IsEmpty(id object) {
    return object == nil
        || ([object respondsToSelector:@selector(length)]
        && [(NSData *) object length] == 0)
        || ([object respondsToSelector:@selector(count)]
        && [(NSArray *) object count] == 0);
}

2
Это на самом деле не проверяет объект == [NSNull null], что, вероятно, имеет смысл.
Питер Н Льюис

3

Есть две ситуации:

Возможно, что объект есть [NSNull null], или это невозможно.
Ваше приложение обычно не должно использовать [NSNull null];вас, используйте его, только если вы хотите поместить « нулевой » объект в массив или использовать его в качестве значения словаря. И тогда вы должны знать, какие массивы или словари могут содержать нулевые значения, а какие нет.
Если вы считаете, что массив никогда не содержит [NSNull null]значений, не проверяйте его. Если есть [NSNull null], вы можете получить исключение, но это нормально: исключения Objective-C указывают на ошибки программирования. И у вас есть программная ошибка, которую нужно исправить, изменив некоторый код.

Если объект может быть [NSNull null], то вы проверяете это довольно просто путем тестирования
(object == [NSNull null]). Вызов isEqualили проверка класса объекта - нонсенс. Есть только один [NSNull null]объект, и простой старый оператор C проверяет его в порядке, самым простым и эффективным способом.

Если вы проверяете NSStringобъект, который не может быть [NSNull null](потому что вы знаете, что он не может быть [NSNull null]или потому что вы только что проверили, что он отличается от этого [NSNull null], то вам нужно спросить себя, как вы хотите обрабатывать пустую строку, то есть ту, которая имеет длину 0. Если вы обрабатывать это как nullстроку nil, затем test (object.length == 0). object.length вернет 0 если object == nil, так что этот тест охватывает ноль объектов и строк длиной 0. Если вы обрабатываете строку длиной 0, отличную от нулевой строки, просто проверьте, если object == nil.

Наконец, если вы хотите добавить строку в массив или словарь, и строка может быть nil, у вас есть выбор не добавлять ее, заменять ее @""или заменять ее [NSNull null]. Замена его @""означает, что вы теряете способность различать «без строки» и «строка длины 0». Замена его [NSNull null]означает, что вы должны писать код при доступе к массиву или словарю, который проверяет [NSNull null]объекты.


Очень долго, но это хорошо. NSNull должен появиться только в одиночку! Весь этот вопрос не имеет смысла, говорит мне, что кодер не делал что-то правильное, и многие другие в будущем также не читали руководство / хорошая практика кода
Стивен Дж

2

Вы просто проверьте на ноль

if(data[@"Bonds"]==nil){
  NSLog(@"it is nil");
}

или

if ([data[@"Bonds"] isKindOfClass:[NSNull class]]) {
    NSLog(@"it is null");
}

2

Решение MACRO (2020)

Вот макрос, который я использую для безопасной строки вместо получения строки « (null) » в UILabel например:

#define SafeString(STRING) ([STRING length] == 0 ? @"" : STRING)

Допустим, у вас есть класс-член и свойство name, а имя равно nil:

NSLog(@"%@", member.name); // prints (null) on UILabel

с макросом:

NSLog(@"%@", SafeString(member.name)); // prints empty string on UILabel

красиво и чисто 😊

Решение для расширения (2020)

Если вы предпочитаете проверять nil Null и пустую строку в вашем проекте, вы можете использовать мою дополнительную строку ниже:

NSString + Extension.h

///
/// Checks if giving String is an empty string or a nil object or a Null.
/// @param string string value to check.
///
+ (BOOL)isNullOrEmpty:(NSString*)string;

NSString + Extension.m

+ (BOOL)isNullOrEmpty:(NSString*)string {
    if (string) { // is not Nil
        NSRange range = [string rangeOfString:string];
        BOOL isEmpty = (range.length <= 0 || [string isEqualToString:@" "]);
        BOOL isNull = string == (id)[NSNull null];

        return (isNull || isEmpty);
    }

    return YES;
}

Пример использования

if (![NSString isNullOrEmpty:someTitle]) {
    // You can safely use on a Label or even add in an Array for example. Remember: Arrays don't like the nil values!
}



1
@interface NSString (StringFunctions)
- (BOOL) hasCharacters;
@end

@implementation NSString (StringFunctions)
- (BOOL) hasCharacters {
    if(self == (id)[NSNull null]) {
        return NO;
    }else {
        if([self length] == 0) {
            return NO;
        }
    }
    return YES;
}
@end

NSString *strOne = nil;
if([strOne hasCharacters]) {
    NSLog(@"%@",strOne);
}else {
    NSLog(@"String is Empty");
}

Это будет работать в следующих случаях NSString *strOne = @""ИЛИ NSString *strOne = @"StackOverflow"ИЛИ NSString *strOne = [NSNull null]ИЛИ NSString *strOne.


0

Если такого рода вещи еще не существуют, вы можете создать категорию NSString:

@interface NSString (TrucBiduleChoseAdditions)

- (BOOL)isEmpty;

@end

@implementation NSString (TrucBiduleChoseAdditions)

- (BOOL)isEmpty {
    return self == nil || [@"" isEqualToString:self];
}

@end

Это, вероятно, излишне, и я не думаю, что это решит эту проблему.
Рог

9
«Я» == ноль бессмысленно - если бы «я» было ноль, цель С не назвала бы вас в первую очередь. [(NSString *) nil isEmpty] просто вернет 0 / nil / false, даже не вызывая ваш код.
Питер Н Льюис

4
На самом деле, в дополнение к этому, [(NSString *) nil isEmpty] вернет false. При написании таких методов Objective C лучше определить их так, чтобы nil = 0 / nil / false имел смысл, поэтому было бы лучше написать метод как hasCharacters. Обратите внимание, что длина уже работает для этого, так как вы можете использовать if (s.length) везде, где вы хотели бы использовать if (! S.isEmpty) и s.length, правильно вернет 0 для случая s == nil.
Питер Н Льюис

Это серьезный сбой. Вы реализовали «isEmpty» для NSString, но если это на самом деле NSNull, то isEmpty будет отправлено в NSNull, и произойдет сбой, потому что он не отвечает на это сообщение!
daniel.gindi

0

Что работает для меня это if ( !myobject )


3
Это не работает для нулевых объектов, только для нулевых объектов. Например ... NSArray *testarray = [NSArray arrayWithObjects:[NSNull null],@"", nil]; NSString *string = [testarray objectAtIndex:0]; NSLog(@"null string value: %@",string); if (!string) { NSLog(@"string evaluates to null"); } if (string && (string==(id)[NSNull null])) { NSLog(@"string does not evaluate to null"); }
Рик Смит-Унна

Эээ .. извините за форматирование, но код скомпилируется :)
Rik Smith-Unna

0

Полная проверка строки на нулевые условия может быть следующей: <\ br>

    если (MyString)
     {
       если ([mystring isEqualToString: @ ""])
        {
          mystring = @ "некоторая строка";
        }
     }    
    еще
     {
        //заявления
     }

0

Я проверяю только нулевую строку с

if ([myString isEqual: [NSNull null]])


0
if ([linkedStr isEqual:(id)[NSNull null]])
                {
                    _linkedinLbl.text=@"No";
                }else{
                    _linkedinLbl.text=@"Yes";
                }

1
Хотя этот фрагмент кода может ответить на вопрос, он не предоставляет никакого контекста, объясняющего, как и почему. Попробуйте добавить предложение или два, чтобы объяснить свой ответ.
brandonscript

0
if ([strpass isEqual:[NSNull null]] || strpass==nil || [strpass isEqualToString:@"<null>"] || [strpass isEqualToString:@"(null)"] || strpass.length==0 || [strpass isEqualToString:@""])
{
    //string is blank  
}

0

Для строки:

+ (BOOL) checkStringIsNotEmpty:(NSString*)string {
if (string == nil || string.length == 0) return NO;
return YES;

}

Смотрите картинку ниже:

введите описание изображения здесь


0

Для строки:

+ (BOOL) checkStringIsNotEmpty:(NSString*)string {
if (string == nil || string.length == 0) return NO;
return YES;}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.