วิธีที่ถูกต้องในการตรวจสอบสตริงว่างใน Objective-C คืออะไร?


184

ฉันใช้สิ่งนี้ในแอพ iPhone ของฉัน

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

แต่มันมีข้อยกเว้นบางอย่างและคอนโซลแสดงให้เห็นว่าชื่อเรื่องคือ "(null)"

ดังนั้นฉันใช้สิ่งนี้ตอนนี้:

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

ความแตกต่างคืออะไรและวิธีที่ดีที่สุดในการพิจารณาว่าสตริงเป็นโมฆะคืออะไร?


วิธีแก้ปัญหา: jayprakashdubey.blogspot.in/2014/09/…
Jayprakash Dubey

คำตอบ:


395

ตามที่คนอื่น ๆ ชี้ให้เห็นมีหลายประเภทของ "โมฆะ" ภายใต้โกโก้ / วัตถุประสงค์ C. แต่สิ่งหนึ่งที่ควรทราบก็คือ [ชื่อ isKindOfClass: [ชั้น NSNull]] มีความซับซ้อนอย่างไม่มีจุดหมายตั้งแต่ ซิงเกิลเพื่อให้คุณสามารถตรวจสอบความเท่าเทียมกันของตัวชี้ ดูหัวข้อโกโก้: การใช้ Null

ดังนั้นการทดสอบที่ดีอาจเป็น:

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

โปรดสังเกตว่าคุณสามารถใช้ความจริงที่ว่าแม้ว่าชื่อเรื่องเป็นศูนย์ชื่อเรื่องความยาวจะส่งกลับ 0 / ศูนย์ / เท็จเช่น 0 ในกรณีนี้ดังนั้นคุณไม่จำเป็นต้องเป็นกรณีพิเศษ นี่คือสิ่งที่ผู้ที่เพิ่งเริ่มใช้งาน Objective C มีปัญหาในการคุ้นเคยโดยเฉพาะอย่างยิ่งการจัดรูปแบบภาษาอื่น ๆ ที่ข้อความ / วิธีการเรียกใช้เพื่อไม่ให้เกิดความผิดพลาด


ขอบคุณ! อย่างไรก็ตามฉันถามคำถามนี้ตั้งแต่แรกเพราะฉันได้รับการยกเว้นเพราะ "ชื่อ" null
Teo Choong Ping

1
ชื่อประเภทใดควรเป็น ตัวอย่างเช่นถ้าเป็น NSString ฉันได้รับคำเตือนดังต่อไปนี้: การเปรียบเทียบกับประเภทของ Objective-C ที่แตกต่างกัน 'struct NSNull *' และ 'struct NSString *' ไม่มีตัวละครมีวิธีลบสิ่งนี้หรือไม่ คำถามนี้ถูกถาม)?
thebossman

1
ให้บริการฉันที่ถูกต้องสำหรับการโพสต์รหัสโดยไม่ต้องรวบรวมมัน ;-) ชื่อเรื่องน่าจะเป็น NSString แต่ไม่คำนึงถึงประเภทของชื่อเพียงแค่โยน null เป็นประเภท id ทั่วไป: (id) [NSNull null]
Peter N Lewis

1
@JLT ไม่มีและ [NSNull null] จะไม่เหมือนเดิม [NSNull null] เป็นวัตถุเดี่ยวที่สามารถใช้เป็นขาตั้งสำหรับศูนย์เมื่อไม่สามารถใช้ศูนย์ (เช่นในค่า NSArray หรือ NSDictionary) ดังนั้นกรณีการใช้งานอาจเป็นที่ที่คุณมี NSArray ของสตริงตัวเลือกซึ่งบางส่วนอาจเป็นโมฆะและคุณใช้ [NSNull null] ในอาร์เรย์สำหรับกรณีที่เป็นโมฆะ ในทางปฏิบัติแล้วการทดสอบนั้นไม่ค่อยจำเป็นต้องใช้เฉพาะเมื่อคุณ (หรือห้องสมุดที่คุณใช้!) ใช้ [NSNull null] เป็นตัวยึดตำแหน่งอย่างแข็งขัน
Peter N Lewis

1
มาที่นี่จาก Flutter และมองหาเหตุผลว่าทำไมMapมูลค่าของสินค้า - ซึ่งอยู่nullใน Dart - ไม่ตรงกับnilหรือNULLใน Objective C เหตุผลก็คือว่ามันเป็นจริงNUNull nullไม่ใช่NULLโมฆะ ขอบคุณ @PeterNLewis!
Aleksandar

25

มันง่ายเหมือน

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

โปรดจำไว้ว่าใน C วัตถุประสงค์ถ้าวัตถุเป็นโมฆะมันจะส่งกลับ 0 เป็นค่า

สิ่งนี้จะทำให้คุณได้รับทั้งสตริงว่างและสตริงความยาว 0


49
สิ่งนี้จะไม่ทำงานหากวัตถุคือ NSNull ยังคงต้องตรวจสอบอย่างชัดเจนก่อน
Jeremy Mack Mack

6
คุณสามารถสร้างหมวดหมู่สำหรับ NSNull เพื่อให้ส่งคืน 0 เป็นข้อความความยาว :)
Mihai Timar

1
ใช่สิ่งนี้จะพังถ้าวัตถุเป็น NSNull
Mike Gledhill

สิ่งนี้จะผิดพลาดหากวัตถุเท่ากับ NSNull
joan

1
นอกเหนือจากปัญหาตัวเลือกที่ไม่รู้จักของ NSNull สิ่งนี้จะไม่แยกความแตกต่างระหว่างตัวชี้ NSString ที่เป็นศูนย์หรือ NSString ที่มีอยู่จริง แต่มีสตริงว่างเปล่าเป็นหลัก (ตัวอย่างเช่นเป็นตัวอักษรobject = @"";หรือobject = nil;)
KellyTheDude

6

อ้างถึงบทความที่เกี่ยวข้องต่อไปนี้ในเว็บไซต์นี้:

ฉันคิดว่าข้อผิดพลาดของคุณเกี่ยวข้องกับอย่างอื่นเนื่องจากคุณไม่จำเป็นต้องทำการตรวจสอบเพิ่มเติม

ดูคำถามที่เกี่ยวข้องเช่นนี้: ตรวจสอบคอลัมน์ข้อความของ sqlite อย่างเหมาะสม


น่ารำคาญฉันมี "คะแนน" ไม่เพียงพอที่จะเพิ่มไฮเปอร์ลิงก์ที่สอง (แม้แต่บางอย่างในไซต์นี้) ดูเพิ่มเติม: - stackoverflow.com/questions/598396/…
TimM

... อนุญาตให้ฉัน แม้ว่าคุณควรจะสามารถแก้ไขโพสต์ของคุณเองจากตัวแทน 0
Rog

ขอบคุณ - นั่นใจดีมาก เมื่อฉันเขียนโพสต์ครั้งแรกของฉันมันกล่าวว่าบางสิ่งบางอย่างเช่นผู้ใช้ใหม่สามารถเพิ่มไฮเปอร์ลิงก์ได้เพียง 1 ลิงก์เท่านั้น (ซึ่งดูเหมือนจะรุนแรงเล็กน้อย
TimM

6

ฉันได้พบว่าเพื่อที่จะทำในสิ่งที่ถูกต้องคุณจะต้องทำสิ่งที่คล้ายกัน

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

มิฉะนั้นคุณจะได้รับสถานการณ์แปลก ๆ ที่การควบคุมจะยังคงผ่านการตรวจสอบของคุณ ฉันยังไม่เจอที่ทำให้ผ่านการisEqualตรวจสอบและความยาว


5

อะไรคือสิ่งที่ "ใช้งานได้สำหรับคำตอบ" เหล่านี้? เราทุกคนเขียนโค้ดด้วยภาษาเดียวกันและมีกฎ

  1. ตรวจสอบให้แน่ใจว่าการอ้างอิงไม่เป็นศูนย์
  2. ตรวจสอบและตรวจสอบให้แน่ใจว่าความยาวของสตริงไม่ใช่ 0

นั่นคือสิ่งที่จะทำงานให้กับทุกคน หากโซลูชันที่ระบุ "ใช้งานได้กับคุณเท่านั้น" เท่านั้นเนื่องจากโฟลว์แอปพลิเคชันของคุณจะไม่อนุญาตให้ใช้กับสถานการณ์ที่การอ้างอิงอาจเป็นโมฆะหรือความยาวสตริงเป็น 0 วิธีที่เหมาะสมในการทำเช่นนี้คือวิธีการที่จะจัดการ สิ่งที่คุณต้องการในทุกกรณี


4
หากการอ้างอิงคือnil(หมายเหตุ: ไม่ใช่ "null") ดังนั้นการส่งข้อความเช่นlengthจะสร้าง 0 (หรือค่า 0 ที่เหมาะสมสำหรับประเภทส่งคืนของวิธีการ) นั่นคือกฎของภาษา ไม่จำเป็นต้องตรวจสอบnilแยกต่างหากในกรณีนี้
jscs

ฉันบอกว่าเป็นโมฆะเพราะนิสัยของ C ++ และถ้ารหัสของคุณเรียกวิธีการบนวัตถุไม่มีโอกาสรหัสของคุณจะเสีย คุณจะพบว่าวิธีการโทรบน NULL / NIL (แนวคิดเดียวกัน) เป็นความคิดที่ไม่ดีในภาษาใด ๆ เพียงเพราะ obj-c ช่วยให้คุณทำสิ่งที่ไม่ได้หมายความว่าคุณควรจะผ่านวัตถุไม่มีศูนย์และพยายามที่จะใช้พวกเขาโดยไม่ต้องดูแล
nenchev

1
การส่งความยาวถึงศูนย์จะสร้าง 0 - BUT แต่ส่งความยาวให้ NSNull สร้างข้อยกเว้น
cdstamper

@ nenchev ไม่มีใครพูดอะไรเกี่ยวกับแค่ผ่านวัตถุศูนย์ แต่ตรวจสอบศูนย์แล้วเรียกวิธีการและการใช้ค่าส่งคืนเป็น IMO ที่เลวร้ายยิ่งกว่าการใช้คุณสมบัติภาษาเช่นมันตั้งใจที่จะใช้และการตรวจสอบความถูกต้องของค่าตอบแทนวิธี
Kevin

@ เควินฉันไม่แน่ใจว่ามันแย่จริง ๆ เพียงเพราะคุณสมบัติภาษาไม่ได้หมายความว่ามันยอดเยี่ยม ไม่ตรวจสอบว่าค่าว่างนั้นสามารถเปิดเส้นทางโค้ดที่อาจนำไปสู่ข้อผิดพลาดรันไทม์ที่ยากขึ้นในการติดตาม โดยปกติแล้วมันจะดีที่สุดในการตรวจสอบว่าอินพุตของคุณเป็นไปตามที่คุณคาดหวังและตอบสนองตามนั้นหากไม่มี ฉันไม่ชอบ "คุณสมบัติ" เป็นการส่วนตัวที่ไม่ได้รับข้อยกเว้นแบบรันไทม์เมื่อพยายามส่งข้อความไปยังวัตถุศูนย์เนื่องจากมักจะทำให้พลาดข้อบกพร่องรันไทม์ได้ง่ายขึ้น
nenchev

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
สิ่งนี้ไม่ได้ตรวจสอบ object == [NSNull null] ซึ่งอาจสมเหตุสมผล
Peter N Lewis

3

มีสองสถานการณ์:

เป็นไปได้ว่าวัตถุนั้นเป็น[NSNull null]หรือเป็นไปไม่ได้
แอปพลิเคชันของคุณมักจะไม่ควรใช้[NSNull null];เฉพาะเมื่อคุณต้องการใส่วัตถุ " null " ลงในอาร์เรย์หรือใช้เป็นค่าพจนานุกรม แล้วคุณควรรู้ว่าอาเรย์หรือพจนานุกรมใดที่อาจมีค่า 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นั้นการทดสอบ(object.length == 0). object.length จะกลับ 0 ถ้าobject == nilเพื่อให้การทดสอบนี้ครอบคลุมศูนย์วัตถุและสตริงที่มีความยาว 0 ถ้าคุณรักษาสตริง 0 object == nilยาวที่แตกต่างกันจากสตริงศูนย์เพียงตรวจสอบว่า

สุดท้ายหากคุณต้องการที่จะเพิ่มสายไปยังอาร์เรย์หรือพจนานุกรมและสตริงอาจจะไม่มีคุณมีทางเลือกที่จะไม่เพิ่มแทนที่มันด้วยหรือแทนที่มันด้วย@"" [NSNull null]การแทนที่ด้วย@""หมายความว่าคุณสูญเสียความสามารถในการแยกความแตกต่างระหว่าง "no string" และ "string of length 0" แทนที่ด้วย[NSNull null]วิธีที่คุณต้องเขียนรหัสเมื่อคุณเข้าถึงอาร์เรย์หรือพจนานุกรมที่ตรวจสอบ[NSNull null]วัตถุ


ยาวมาก แต่ก็ดี NSNull ควรปรากฏใน SINGLETONS เท่านั้น! คำถามทั้งหมดนี้ไม่มีเหตุผลบอกฉันว่า coder ไม่ได้ทำอะไรถูกต้องและอื่น ๆ อีกมากมายในอนาคตเช่นกันไม่ได้อ่านคู่มือ / รหัสปฏิบัติที่ดี
สตีเฟ่นเจ


2

โซลูชันมาโคร (2020)

นี่คือแมโครที่ฉันใช้สำหรับสตริงที่ปลอดภัยแทนการรับสตริง " (null) " ในUILabelตัวอย่างเช่น:

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

สมมติว่าคุณมีคลาสสมาชิกและชื่อคุณสมบัติและชื่อเป็นศูนย์:

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

ด้วยมาโคร:

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

ดีและสะอาด😊

โซลูชั่นเสริม (2020)

หากคุณต้องการตรวจสอบไม่มีศูนย์และสตริงว่างเปล่าในโครงการของคุณคุณสามารถใช้ส่วนขยายของฉันด้านล่าง:

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

นั่นอาจจะเกินกำลังและฉันไม่คิดว่ามันจะแก้ปัญหานี้ได้
Rog

9
ตัวเอง == nil นั้นไม่มีจุดหมาย - หากตัวเองเป็นศูนย์วัตถุประสงค์ C จะไม่เรียกคุณตั้งแต่แรก [(NSString *) nil isEmpty] จะคืนค่า 0 / nil / false โดยไม่ต้องเรียกรหัสของคุณ
Peter N Lewis

4
ที่จริงยิ่งไปกว่านั้น [(NSString *) nil isEmpty] จะคืนค่าเท็จ เมื่อเขียนวิธี Objective C ดังกล่าวจะเป็นการดีกว่าที่จะกำหนดไว้เพื่อให้ 0 / nil / false ไม่มีเหตุผลจึงควรเขียนวิธีการที่มีตัวอักษรจะดีกว่า โปรดทราบว่าความยาวใช้งานได้แล้วเนื่องจากคุณสามารถใช้ถ้า (s.length) ทุกที่ที่คุณต้องการใช้ถ้า (! s.isEmpty) และ s.length จะส่งคืนค่า 0 สำหรับ s == nil อย่างถูกต้อง
Peter N Lewis

นี่เป็นความผิดพลาดร้ายแรง คุณใช้ "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 ([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;

}

ดูภาพด้านล่าง:

ป้อนคำอธิบายรูปภาพที่นี่


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.