Swift - Check nil of an unwrapped optional variable
Asked Answered
S

2

7

I am having a model class as follows, which is in a library written in Objective-C. I am consuming this class in my swift project. In swift it becomes property of type String!. Sometimes that property will be nil. So, I am testing the nil validation as follows:

Vendor.h

@interface Vendor: NSObject {

@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, strong) NSString *middleName;
}

In my Swift project, I am checking the nil validation for the middleName property as below:

if anObject.middleNam != nil { // Here, It throws runtime error: fatal error: Unexpectedly found nil while unwrapping an Optional value
}

It throws me an following runtime error:

fatal error: unexpectedly found nil while unwrapping an Optional value

If the objective-C properties exposed in swift as String? then I would have used the following:

if let middleName = anObject.middleName {

}

How would I check for the unwrapped optional variable.

Thanks in advance.

Syndactyl answered 28/6, 2016 at 8:7 Comment(1)
You can use if let with implicitly unwrapped optionals – although the != nil check should work properly with middleName, how is anObject defined?Genip
O
6

If you want ObjectiveC property to be exposed in Swift as optional, mark it with _Nullable tag like

@property (nonatomic, strong) NSString * _Nullable middleName;

Now middleName name would be optional of type String? instead of String! and you could conditionally unwrap it.

Read more about Nullability in ObjC

Overdye answered 28/6, 2016 at 8:18 Comment(3)
Note that OP's property is already exposed in Swift as an optional (it's just implicitly unwrappable) & he can use conditional unwrapping on it. In Swift 3, an implicitly unwrapped optional is the exact same type as a regular optional – it just has an attribute telling the compiler that it has the option to force unwrap it in certain situations. And these situations don't include nil checks or conditional unwrapping. OP's code is working fine for me – I suspect his problem is that anObject is defined as an IUO and that's what is getting force unwrapped.Genip
Although I definitely agree that adding nullability tags to obj-c types is a good way to go, especially when interfacing with Swift.Genip
@originaluser2 I agree to your point. it will be implicitly unwrapped optional, and he can still use conditional unwrapping on it but compiler wont complain if you are not doing and this would cause crash in situations like ``let middleName:String = object.middleName` . So its a good practise to mark with nullable tag, thus who ever is going to use it will get compiler warning and he can handle it safely.Overdye
I
3

As Anil mentioned, the best solution would be to edit your objective-c code to add some _Nullable. But, as I understand, your Objective-C code is a library that you cannot edit. So, you have to deal with these String! that can be nil.

But you can simply use if let technique like this:

if let firstName = vendor.firstName {
    print("Here is my firstName: \(firstName)")
} else {
    print("I have no firstName")
}
if let middleName = vendor.middleName {
    print("Here is my middleName: \(middleName)")
} else {
    print("I have no middleName")
}

if let lastName = vendor.lastName {
    print("Here is my name: \(lastName)")
} else {
    print("I have no lastName")
}

With this Vendor code, it returns the following result:

@interface Vendor: NSObject
    @property (nonatomic, strong) NSString *firstName;
    @property (nonatomic, strong) NSString *lastName;
    @property (nonatomic, strong) NSString *middleName;
@end
@implementation Vendor
- (instancetype)init
{
    self = [super init];
    if (self) {
        self.firstName = @"Julien";
        self.middleName = nil;
        self.lastName = @"Quere";
    }

    return self;
}
@end

Result:

Here is my firstName: Julien 
I have no middleName 
Here is my name: Quere
Interphone answered 28/6, 2016 at 8:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.