问题
In Swift I am using C API that returns struct with char array (containing UTF8 null terminated string or null).
struct TextStruct {
char * text;
//other data
}
I use:
let text: String = String(cString: data.text)
This works, however, when data.text is nullptr, this fails with
fatal error: unexpectedly found nil while unwrapping an Optional value
Is there any workaround, or I have to check data.text manually before using cString ctor?
回答1:
In addition to Gwendal Roué's solution: You can annotate the C API to indicate whether the pointer can be null or not. For example,
struct TextStruct {
char * _Nullable text;
//other data
};
is imported to Swift as
public struct TextStruct {
public var text: UnsafeMutablePointer<Int8>?
// ...
}
where var text is a "strong" optional instead of an implicitly
unwrapped optional. Then
let text = String(cString: data.text)
// value of optional type 'UnsafeMutablePointer<Int8>?' not unwrapped; ...
no longer compiles, and forces you to use optional binding or other unwrapping techniques, and the "fatal error: unexpectedly found nil" cannot happen anymore accidentally.
For more information, see "Nullability and Objective-C" from the Swift Blog – despite the title, it can be used with pure C as well.
回答2:
Yes, you have to check data.text, in order to make sure it can feed the String(cString:) initializer, which is documented to require a non-null pointer.
A technique is to use a if let statement. This is a classic technique for safely unwrapping optional values:
let str: String?
if let ptr = ptr {
str = String(cString: ptr)
} else {
str = nil
}
print("got \(str ?? "nil")")
Another technique is the Optional.map function:
let str = ptr.map { String(cString: $0) }
print("got \(str ?? "nil")")
来源:https://stackoverflow.com/questions/47375208/swift-c-api-bridge-how-to-handle-null-pointers