According to the Xcode release notes, Apple has been "auditing" their existing APIs to remove implicitly unwrapped optionals. That means that instead of T!, their APIs will return T or T? where appropriate.
Where do they do this? How can I annotate/wrap my existing Objective-C code (especially libraries) to make it cleaner to use from Swift?
Xcode 6.3 added official support for annotating nullability in Objective-C.
The nullability of a value can be declared by annotating the type with the keywords __nullable, __nonnull and __null_unspecified (the default). In properties and methods the keywords are nullable, nonnull and null_unspecified.
Examples from the Xcode release notes
   - (void)registerNib:(nonnull UINib *)nib
forCellReuseIdentifier:(nonnull NSString *)identifier;
- (nullable UITableViewCell *)cellForRowAtIndexPath:(nonnull NSIndexPath)indexPath;
@property (nonatomic, readwrite, retain, nullable) UIView *backgroundView;
null_unspecified (which translates to T!) is the default for all existing code. A useful feature is the ability to change the default for sections of your API.
NS_ASSUME_NONNULL_BEGIN
// nonnull is the default here
NS_ASSUME_NONNULL_END
This removes a lot of noise, since methods that accept and handle nil usually are the exception, not the rule. Personally, I would use this for all audited APIs.
null_resettable is an additional annotation that is used for the uncommon case where you can set a property to nil, but it will never be nil (because it resets to a default value).
 @property (nonatomic, retain, null_resettable) UIColor *tintColor;
Personally, I would avoid this behavior for new code. The hybrid nature of such properties isn't a good fit for Swift.
Xcode 7 adds support for annotating generic types in Objective-C.
NSArray, NSSet and NSDictionary (which are automatically bridged to Swift's Array, Set and Dictionary can be annotated with the type of their contents.
@property NSArray<NSString *> *stringArray;
@property NSSet<NSString *> *stringSet;
@property NSDictionary<NSString *, NSString *> *stringDict;
There's also the __kindof keyword that tells the Objective-C compiler to be less strict and allow downcasting. But it doesn't affect the Swift side.
@interface MyArray1<__covariant T> : NSObject
- (void)addObject:(T)object;
@end
@interface MyArray2<__covariant T : NSObject *> : NSObject
- (void)addObject:(T)object;
@end
@interface MyArray3<__covariant T : id<NSCopying>> : NSObject
- (void)addObject:(T)object;
@end
The @implementation doesn't know about T and uses id/NSObject */id<NSCopying> as it always did.
I believe there's a way to do this at the moment. It looks like the information is being compiled to
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator
in files like
UIKit.apinotesc 
UIKit.swiftdoc 
UIKit.swiftmodule
The *.swiftmodule classes are generated by Xcode as part of the swift build but the additional information may be in the .apinotesc file, which there doesn't appear to be a documented form of generating it at the moment.
However, the swift command has an -apinotes option, which is used to generate this. You can see from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator/UIKit.apinotesc that you can parse this with:
xcrun swift -apinotes -binary-to-yaml  -o=- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator/UIKit.apinotesc
This generates a YAML file looking like:
Classes:         
  - Name:            NSFileProviderExtension
    Availability:    available
    AvailabilityMsg: ''
    Methods:         
      - Selector:        'URLForItemWithPersistentIdentifier:'
        MethodKind:      Instance
        Nullability:     [ N ]
        NullabilityOfRet: U
        Availability:    available
        AvailabilityMsg: ''
If I were a betting man (and I'm not), I'd say that the MethodKind determines whether it's an Instance or a Class and that the Nullability is being used by Swift to determine whether it's an optional or not. I would suspect:
U - (implicitly) unwrapped optionalO - optionalN - non-optional?These are wild guesses though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With