Using functions

After you have exposed the headers to Swift, it is very simple to call functions. You can simply call the functions directly as if they didn't have parameter names:

NSArray *addInviteeToListIfSpotAvailable
     (
     NSArray *invitees,
     NSString *newInvitee
     );
addInviteeToListIfSpotAvailable(inviteeList, "Sarah")

Xcode will even autocomplete the code for you. From your Swift files point of view, there is no way to know if that function is implemented in Objective-C or Swift.

Using types

You can use types the same way you use functions. Once the proper header files are imported in the bridging header, you can just use the type as if it were a Swift type:

@interface Contact : NSObject
@property NSString *firstName;
@property NSString *lastName;
- (NSArray *)addToInviteeList:(NSArray *)invitees includeLastName:(BOOL)include;
@end
var contact = Contact()
contact.firstName = "First"
contact.lastName = "Last"
contact.addToInviteeList(inviteeList, includeLastName: false)

Again, from Swift's point of view, there is absolutely no difference between how we write the code that uses our Objective-C class and how we would write it if the class were implemented in Objective-C. We were even able to call the addToInviteeList:includeLastName: method with the same parameter names. This makes it even more clear that Swift was designed with backwards compatibility in mind.

The only real restrictions are that all classes defined in Objective-C are still going to inherit from NSObject and Objective-C enumerations aren't going to translate perfectly into Swift enumerations. Instead, they are still exposed as individual constants:

typedef enum {
    PrimaryColorRed,
    PrimaryColorGreen,
    PrimaryColorBlue,
} PrimaryColor;
var color: PrimaryColor = PrimaryColorRed

Containers

You may have also noticed that the NSString and NSArray types seem to translate transparently to String and Array classes in the preceding code. This is another wonderful feature of the bridge between Swift and Objective-C. These types, as well as dictionaries, translate almost perfectly. The only difference is that since Objective-C does require an element type when defining a container, they are translated into Swift as containing objects of type AnyObject. If you want to treat them as a more specific type, you will have to cast them:

inviteeList = contact.addToInviteeList(
    inviteeList,
    includeLastName: false
    ) as! [String]

The actual return value of this method when translated to Swift is [AnyObject]!. Therefore, if you are sure that the method never returns nil and always returns an array of Strings, it is safe to do the forced casting that we did above. Otherwise, you should still check for nil and do an optional casting (as?).

Annotations

You will note that this acts as a pattern when Objective-C types are translated to Swift. Any reference type is going to be translated, by default, to an implicitly unwrapped optional because of the nature of Objective-C reference types. The compiler can't automatically know if the value returned could be nil or not, so it doesn't know if it should be translated as a regular optional or a non-optional. However, Objective-C developers can add annotations to let the compiler know if a value can be nil or not.

Nullability

The first thing Objective-C developers can add annotations for is whether a specific variable can be null or not:

- (NSArray * __nonnull)addToInviteeList:
        (NSArray * __nullable)invitees;

The __nonnull keyword indicates that it cannot be nil, so it will be translated in Swift to a non-optional and the __nullable keyword indicates that it can be nil, so in Swift it will translated to a regular optional.

Container element types

Objective-C developer can also annotate their container types to say what type they contain. For this, use the angled brackets just like Swift:

- (NSArray<NSString *> * __nonnull)addStringToInviteeList:
        (NSArray<NSString *> * __nullable)invitees;

Now, this method will really work just like Swift methods in that it will take an optional array of strings and return a non-optional array of strings; there will be no casting necessary:

inviteeList = contact.addStringToInviteeList(inviteeList)

If you have control over the Objective-C code you are importing then you may want to add it. Otherwise, you might be able to ask the developer of the code to add the annotations to make your Swift coding much easier and more clean.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset