# Uninitialised nonnull properties of Foundation types are set to sensible defaults in Swift

**URL:** <https://forums.swift.org/t/uninitialised-nonnull-properties-of-foundation-types-are-set-to-sensible-defaults-in-swift/20323>\
**Category:** Using Swift\
**Tags:** string, bridging, objective-c, array, swift4\
**Created:** [February 10, 2019, 5:23pm UTC](https://forums.swift.org/t/uninitialised-nonnull-properties-of-foundation-types-are-set-to-sensible-defaults-in-swift/20323 "2019-02-10T17:23:41Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![elitalon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/elitalon/32/21933_2.png) [@elitalon](https://forums.swift.org/u/elitalon)\
**Post date:** [February 10, 2019, 5:23pm UTC](https://forums.swift.org/t/uninitialised-nonnull-properties-of-foundation-types-are-set-to-sensible-defaults-in-swift/20323/1 "2019-02-10T17:23:41Z")

</div>

Hello everyone,

I was writing a unit test in Swift for a class written in Objective-C when I came across the following behaviour: `nonnull` properties of some Foundation types (e.g. `NSString` or `NSArray`) declared in a Objective-C class are automatically set to a default value (e.g. an empty string or an empty array) when they're bridged to Swift.

Here's a code sample demonstrating this behaviour. Given an Objective-C class:

```nohighlight
@interface Team : NSObject

@property (nonatomic, copy, nonnull) NSString *name;

@property (nonatomic, copy, nonnull) NSArray<NSString *> *codes;

@end

@implementation Team

// Note there is no explicit initialisation here

@end

```

and a unit test written in Swift:

```swift
final class TeamTests: XCTestCase {

    func testExample() {
        let team = Team()

        XCTAssertNil(team.name) // fails, name is an empty string
        XCTAssertNil(team.codes) // fails, codes is en empty array

        XCTAssert(team.name.isEmpty)
        XCTAssert(team.codes.isEmpty)
    }

}

```

the assertions checking for `nil` always fail. That shouldn’t be surprising, as the types become `String` (not `String?`) and `Array<String>` (not `Array<String>?`) in Swift. The same assertions written in an Objective-C test succeed:

```nohighlight
@interface TeamTests : XCTestCase

@end

@implementation TeamTests

- (void)testExample {
    Team *team = [[Team alloc] init];

    XCTAssertNil(team.name); // succeeds
    XCTAssertNil(team.codes); // succeeds
}

@end

```

Admittedly this is a programmer error. Without initialising `name` and `codes` to proper values we are indeed breaking the contract established by `nonnull` in the public interface.

And I would argue that this implicit initialisation makes sense. Without setting these properties to any value, it is not possible to implement the equivalent generated interface:

```swift
open class Team : NSObject {
    
    open var name: String    
    open var codes: [String]

}

```

An empty string and an empty array are perfect candidates for a sensible default value when bridging.

Is this expected and/or intended behaviour or rather a detail of the bridging implementation. Moreover, is it documented anywhere?

Thank you!

PS: Whether the compiler should emit a warning when using `XCTAssertNil` with a non optional type is another discussion.

---

<div class="post-metadata">

**Author:** ![marco.masser](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/marco.masser/32/6010_2.png) [@marco.masser](https://forums.swift.org/u/marco.masser)\
**Post date:** [February 11, 2019, 12:57pm UTC](https://forums.swift.org/t/uninitialised-nonnull-properties-of-foundation-types-are-set-to-sensible-defaults-in-swift/20323/2 "2019-02-11T12:57:32Z")

</div>

I have no inside knowledge on this, but I would guess that this is an effect of the bridging behavior that is probably not actually intentional. Apart from trapping at runtime, there’s not much that could be done, though.

Note that this mapping to empty strings and arrays can only happen when the Objective-C representation is a class and the Swift representation is not a class.

> [@elitalon](#):
>
> An empty string and an empty array are perfect candidates for a sensible default value when bridging.

I would argue very strongly against this statement. It is highly dependent on the situation whether empty arrays or strings are acceptable values, much less “sensible” values.

* * *

I came across this very behavior a few weeks ago while debugging some code that behaved in unexpected ways. Essentially, it was a Swift method that expected a non-optional `String` that was called from Objective-C and passed `nil` where it shouldn’t have been.

(Fun fact: the very first thing that method does is verify that the input is not an empty string 😉)

Just like this:

```swift
@objcMembers class Greeter: NSObject {
    class func sayHello(to name: String) { … }
}

```

… and called from Objective-C like this:

```objc
NSString *name = nil;
[Greeter sayHelloTo:name]; // No warning here.

```

The surprising thing here was that the Swift method receives an empty `String`. If that had trapped with some assertion or something like that, it would have been much easier to debug.

---

<div class="post-metadata">

**Author:** ![elitalon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/elitalon/32/21933_2.png) [@elitalon](https://forums.swift.org/u/elitalon)\
**Post date:** [February 11, 2019, 2:33pm UTC](https://forums.swift.org/t/uninitialised-nonnull-properties-of-foundation-types-are-set-to-sensible-defaults-in-swift/20323/3 "2019-02-11T14:33:09Z")

</div>

> [@marco.masser](#):
>
> It is highly dependent on the situation whether empty arrays or strings are acceptable values […]

Yes, you are right. I meant they are perfect candidates in the context where such initialisation is the intended behaviour and the implementation must set a value. But I would rather have some kind of trap or compiler diagnostic as well.

I'm curious now about something in your code sample. When you pass `nil` to `-sayHelloTo:`, does the compiler emit a warning if you set `CLANG_ANALYZER_NONNULL=YES`?

---

<div class="post-metadata">

**Author:** ![marco.masser](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/marco.masser/32/6010_2.png) [@marco.masser](https://forums.swift.org/u/marco.masser)\
**Post date:** [February 11, 2019, 2:35pm UTC](https://forums.swift.org/t/uninitialised-nonnull-properties-of-foundation-types-are-set-to-sensible-defaults-in-swift/20323/4 "2019-02-11T14:35:48Z")

</div>

> [@elitalon](#):
>
> When you pass `nil` to `-sayHelloTo:` , does the compiler emit a warning if you set `CLANG_ANALYZER_NONNULL=YES` ?

It’s set in Xcode to `Yes (Aggressive)` and I get no warning at all. It looks like you only get warnings if you pass the `nil` literal directly, but if there’s an indirection via a variable, clang does not seem to catch it.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [February 11, 2019, 5:36pm UTC](https://forums.swift.org/t/uninitialised-nonnull-properties-of-foundation-types-are-set-to-sensible-defaults-in-swift/20323/5 "2019-02-11T17:36:15Z")

</div>

> [@marco.masser](#):
>
> I have no inside knowledge on this, but I would guess that this is an effect of the bridging behavior that is probably not actually intentional. Apart from trapping at runtime, there’s not much that could be done, though.

This is in fact intentional, both as a guard against incorrectly-annotated Objective-C APIs, and as backward compatibility support for Objective-C APIs that historically returned `nil` instead of empty strings/arrays but don't make a semantic distinction between those as return values. Note that this behavior is specific to bridged types that have a reasonable empty state; bridged types that don't have empty states will trap at runtime if the ObjC API tries to smuggle a null result through to Swift.

---

<div class="post-metadata">

**Author:** ![marco.masser](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/marco.masser/32/6010_2.png) [@marco.masser](https://forums.swift.org/u/marco.masser)\
**Post date:** [February 12, 2019, 8:25am UTC](https://forums.swift.org/t/uninitialised-nonnull-properties-of-foundation-types-are-set-to-sensible-defaults-in-swift/20323/6 "2019-02-12T08:25:59Z")

</div>

Ah, that makes sense. Thanks for the clarification.

If anyone reading this is interested in actual code, here’s [`String._unconditionallyBridgeFromObjectiveC(_:)`](https://github.com/apple/swift/blob/6e7051eb1e38e743a514555d09256d12d3fec750/stdlib/public/Darwin/Foundation/String.swift#L54) that maps `nil` to `String()` and here’s [`Locale. _unconditionallyBridgeFromObjectiveC(_:)`](https://github.com/apple/swift/blob/498b72270ba411358170e35a733136821b59b279/stdlib/public/Darwin/Foundation/Locale.swift#L470) that just traps on `nil`.

---

<div class="post-metadata">

**Author:** ![elitalon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/elitalon/32/21933_2.png) [@elitalon](https://forums.swift.org/u/elitalon)\
**Post date:** [March 1, 2019, 12:54pm UTC](https://forums.swift.org/t/uninitialised-nonnull-properties-of-foundation-types-are-set-to-sensible-defaults-in-swift/20323/7 "2019-03-01T12:54:05Z")

</div>

@Joe_Groff Shouldn't this be documented somewhere, maybe in ["Working with Foundation Types"](https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/working_with_foundation_types) or ["Designating Nullability in Objective-C APIs"](https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/designating_nullability_in_objective-c_apis)?

If so, how can I help there? Opening a radar? Since this is specific to interoperability with Objective-C I don't see a place in [the Swift documentation](https://swift.org/documentation/) to include it.

---

<div class="post-metadata">

**Author:** ![eskimo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/eskimo/32/13558_2.png) [@eskimo](https://forums.swift.org/u/eskimo)\
**Post date:** [March 4, 2019, 8:37am UTC](https://forums.swift.org/t/uninitialised-nonnull-properties-of-foundation-types-are-set-to-sensible-defaults-in-swift/20323/8 "2019-03-04T08:37:52Z")

</div>

> Opening a radar?

Yes. The articles you referenced are Apple documents and thus bugs should go through [Apple Bug Reporter](https://developer.apple.com/bug-reporting/).

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

---

<div class="post-metadata">

**Author:** ![elitalon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/elitalon/32/21933_2.png) [@elitalon](https://forums.swift.org/u/elitalon)\
**Post date:** [March 7, 2019, 7:13am UTC](https://forums.swift.org/t/uninitialised-nonnull-properties-of-foundation-types-are-set-to-sensible-defaults-in-swift/20323/9 "2019-03-07T07:13:55Z")

</div>

Reported in rdar://48666585
