1. 程式人生 > >2014s406 Integrating Swift with Objective-C

2014s406 Integrating Swift with Objective-C

[ Silence ][ Applause ]>> Good morning.

Welcome to Session 406:Integrating Swift with Objective-C.

Now many of the Swift demos here at the conference startby creating either a brand-new project from oneof expo's project templates or a playground and that's great.

Playgrounds are a great way to explore the Swift language.

But many of you already have Mac or iOS apps and someof you have spent years writing Objective-C code.

You have written it carefully.

You have debugged it, polished it, optimized it.

It's just perfect, hmm?And we certainly don't want you to have to throw anyof that away or rewrite anything that you don't want to.

Also some of you have really a lot of Objective-C codethat you maybe spent a decade writing and maybe it's...

not-so-perfect.

It's not as clean and shiny.

So you are going to be usingthat Objective-C code for a while.

You might want to rewrite it, but it's not goingto happen this time around, because you've got an appto ship, etc.

So, Objective-C is not going away.

Both Swift and Objective-C are first class citizensfor doing Cocoa and Cocoa Touch development.

And, in fact, we don't want you to spend any timethat you don't have to.

We don't want you to stop refining the Objective-C code.

We want you to be able to integrate Swift as you want to.

And we do think that as you implement new features,as you finally get around to replacing crufty subsystemsthat you want to use Swift for thatbecause of its better type safety,its expressiveness, its performance.

Now, many of you have also gained a lot of knowledgeand experience in Cocoa and Cocoa Touch through your yearsof Objective-C development and that applies to Swift as well.

You're using the same frameworks, the same classes,the same APIs with some syntactic differences, in fact,the same design patterns, such as delegation.

So all that knowledge applies and so we expect that a lotof you are going to end up with projects that contain both Swiftand Objective-C and we worked hard to make surethat Xcode lets you freely mix Swift and Objective-C.

So this session over the next hour we're goingto be talking a little bit more detailthan what you've probably seen so far about exactly howthat works in practice.

We're going to start simple by just introducing some Swift codeinto an existing Objective-C app.

Then we'll get a little bit more interesting.

We're going to start to add some Swift codeto a model-level framework, which is then embeddedin an Objective-C app and call that from Objective-C.

We'll talk about how to start accessing your pure Swiftframework which will start showingup from an Objective-C app.

And then we'll talk as we go along about how to adopt someof the common, well-established Cocoa patterns in Swift.

And again Swift is designed from the groundup to be a great Cocoa/Cocoa Touch development language.

And so it has language support for some of the Cocoa idiomsthat we've gotten used to.

So, I could go on here for, you know, two dozen slides and talkin detail about how this works, but I'd rather just give a demobecause that's usually a bit more clear.

Alright, so I've got a project here.

It's, it's an iOS app and it has an embedded frameworkso it's decently designed here.

It's got a top layer which is the actual app with the viewand the controller layer in our MVC design.

There is a framework called ListerKit down here,which contains our model objects.

And all of this is currently written in Objective-C.

Just to give a sense of what this is, let's go aheadand run it in the simulator and we're gonna go ahead hereand bring up the simulator.

We see that, yeah, it's a typical list-taking application.

I can go in and add colored lists here.

I can check off items, etcetera, edit them.

What I can't do right now is to add a new list.

This happens to be an iCloud app so I could do that in my Mac appand it would show up here...

But, for this example we're going to use Swiftto add the ability to add a new list in iOS.

Alright, so I'm going to go back hereand the first thing I'm going to do is look down hereto the group ViewControllers.

And here we have some ViewControllers already writtenin objectives [ahem] in Objective-C.

I go to File, Create New File, and in this case I'm just goingto create an empty Swift file because I want to show you howto get started from scratch.

Xcode has great file templates and can fillin a lot of code for you.

And we want to do it in a basic way here,to show how it's going to work.

I'm going to call it NewListController and I'm goingto make sure that it is going to gointo the application target here.

We also see that I have ListerKit, which is my frameworkand one of the new extensions, here,for showing in the status view.

So, NewListController.

Now as I create this, my first Swift file,in a pure Objective-C project...

Xcode will offer to createfor me what's called a bridging header.

So a bridging header, we'll talk about that in more detail later,but basically what it is, is a way for you to expose someof your Objective-C APIs to Swift.

I'm going to go ahead and create that.

So I get that by default.

Now, import foundation...

actually I'm going to be needing some UIKit API here.

So I go ahead and change that to UIKit.

And I know that I will need to import my own model frameworkbecause we want to obviously create our model objectsfrom within the ViewController.

And I'm just going to go ahead here and say NewListController.

And now, when I complete, we see that because I said"import UIKit" there,Swift pulls in the Objective-C framework UIKitand gives me a Swift view of those symbols.

So I'm going to subclass from UIControllerand just leave it like that for now.

So we have just a basic empty class --a Swift class, subclassing an Objective-C class --that we get from UI- ...

from Cocoa Touch.

Now we could sit here and drag out rectanglesand create an API- ...

create a UI for this,but fortunately I happen to already have one.

How lucky.

It isn't wire up though,so we're going to do that right now.

The first thing I'm going to do here is,just like with Objective-C, I need to set what the classof my UIController is.

So I can go up here and now we see that the NewListControllerthat I just created is shown here among all the onesimplemented in Objective-C.

So when you access your classesfrom Swift-...

from Interface Builder, the Swiftand Objective-C classes show up next to each otherand you can work with them as equals.

Alright, so now the next thing I want to do after setting that,I'm going to go ahead and create a bar button item here.

I'm going to drag that up into the toolbar, up here,and I'm going to change the identifier to be Add,and that also changes the visual appearanceto give it a standard Cocoa Touch "Add button" look.

I'll create a segue, it's going to be a mobile segue.

This is, after all, the storyboardand I'll change the name of that segue to be New List.

Now that's going to be important a little bit later on sothat we can access it from within our code.

Okay.

So now, you may have seen in oneof the other demos how we can drag from Swift code and connectto objects inside of IB.

We can do the same thing in the other direction as well.

If I option-click here on my Swift class --my ViewController class implemented in Swift --now I can drag the other direction.

First thing I'm going to do is I'm going to go ahead and dragfrom an outlet and insert a new outlet here.

And I'm going to call this "nameField".

And we see that it's a UIText field and the storage is weakbecause we have a controller class,the super view- ...

the view hierarchy owns the button,and the fields and the buttons in here,and so we just want a weak reference to it.

And, in fact, when we insert this,Interface Builder knows it's a Swift file.

So it uses the Swift syntax just as it would for Objective-C.

And it uses the IBOutlet propertyfor the stored property- ...

I'm sorry, the IBOutlet attributefor the stored property here.

And this is implicitly weak and also optionalbecause not all the outlets may be connected.

Give myself some space there; I'm going to go aheadand do the same thing here for the buttons.

I'm just going to control-drag these and I'm just goingto fill these in in the same way.

Now this is a sample app.

Let me go ahead and adjust the spacing there.

This is a sample app and so it's not rescalableto just have six buttons and six outlets.

But I know that you all design better,more maintainable code than this.

This is for illustrative purposes only.

You might want something where you can load colorsfrom a TableView- ...

uh, from a Plist and show themin a TableView or something like that.

I'm going to go ahead and finish connecting these.

Alright, so now we have our outlets to the UI components.

We can also create Actions in this way.

If I choose the Cancel button down here and I drag in the,I can create an Action up at the top here just for-...

just as for Objective-C.

I change the connection type to Action.

I will type here "cancel" and we can just leave the typeof the sender as any object here.

We don't actually care because we're not goingto be messaging it.

What we will do, however, is to invoke some Cocoa Touch API.

I give myself some more room and I can say "self.

dismiss"and then the code completion gives me accessto the Cocoa Touch API that we already know.

I can complete here.

I'm not going to need a- ...

I want itto be animated, so I put "true".

I don't need a completion block, so I give it "nil".

Now, in Objective-C we always have to message "self"if we want to talk to self.

Swift knows from context when you are messaging yourself.

So we can actually leave this outand make this a little bit more readable.

[ Applause ]Excellent.

Alright, so now we will connect the buttons here as well.

And I'm going to be calling this "pickColor".

Now in this case I choose UIButton.

(I'm sorry, I need to make it an Action.

)I choose UIButton down herebecause in this case we will actually want to talkto the button, or compare the button,so we want to have that type.

And as you can see, Interface Builder generates the codeand makes the sender be a UIButton.

Before I forget, I'm also going to wireup the other actions here as well.

Let me see here.

To connect to this one,give myself a little bit of space there.

And now they're all wired up to the same Action.

So they're all wired up to the same Action.

The sender will be different dependingon which button we touch.

Now, I want to show that some of the powerof the Swift select statement here, the switch statement.

Unlike Objective-C or other C-based languages,I can actually switch on a wide varietyof different kinds of patterns.

In this case I'm just switching on what the sender is.

But this is a very rich construct in the Swift languageand I encourage you to catch one of the later talksabout advanced Swift to really get into the depthof what you can use this for.

For right now, to keep it simple, I'm just goingto use it to match on a button.

And what I will say is "okay,now I need to assign something here.

"So I'm going to need to have a stored property.

I create a stored property called selectedLabelbecause we're actually choosing labels here representedas colors on the screen.

And then what I can do here is I can say this isan AAPLListLabel.

So this again is an Objective-C type that has been importedthrough my import of ListerKit up there.

I'm going to start out by sayingthat that is an APLListLabel.

Gray.

That's the default value of it.

Because I don't put a question mark, I don't make it optional,that means that it has to have a value.

Remember the IB outlets are implicitly optional.

Now it's kind of ugly to have to repeat the same thing here.

And, in fact, Swift has great support for type inference.

And when it knows exactly what type you mean,then you can go ahead and leave out the type.

So from this, Swift can tell exactly that, "okay this hasto be an AAPLListLabel," because that's how I'm initializing it,so I can just leave out the type.

Now I can complete my statement here.

I can say "selectedLabel = .

Gray" and, in fact,I can add to the rest of them here as well.

I'm a very fast typer.

Now we see here that Objective-C- ...

I mean, sorry,Xcode, Swift has a message for us here.

So in Swift, one of the things to notice is eachof the cases is implicitly endedat the beginning of the next case.

So you don't have the case of C where you implicitly fallthrough and that's the source of a lot of bugs.

In fact, Swift was explicitly designed to avoid manyof the common pitfalls that are common in C-based languages.

Now in this case, another thing about the switch statement isthat it has to be exhaustive.

So you have to say that you cover all the cases.

In this particular case I'm just going to add a defaultand what I'm going to do in this case right here isto use a Swift standard library functionto just trap into the debugger.

Because I want to make sure that if I just add new buttonsand hook them up that I actually have the code for that as well.

So now Xcode is happy.

That's excellent.

We've just set our property.

That's all we've done so far.

But now we can use some more of the Cocoa Touch APIto actually make the button show a reflected state-...

show it's selected state, I should say.

So, we say, in this case we can say "sender.

"and then we can use our code completion to access the layer.

And then we'll set it's borderWidth to be five.

And then, of course, we have to initializethat to be a borderColor as well.

Now in this case, because we're accessing the layer --that's a core graphics API --we get the CGColor from the UILabel- ...

the UIColor.

And all of these are standard Cocoa Touch APIs.

So you see that when we access our own Objective-C APIsor the Cocoa Touch APIs it looks all the same.

We still use the same, nice Swift syntax.

Another thing we can do here is to just saythat the view's tint color is going to be the colorthat corresponds to the label.

And for this we can call another one of our functionsthat we brought in from Objective-C.

And we pass it the selectedLabel.

And, in fact, if we command-click on this,we see here that we can get to a Swift representationof our own Objective-C API.

In Navigate we could actually go back to the header itselfthat we declared it from.

Alright, so now those of youwho are following closely here may have seen a little bitof a problem: we set the borderWidth to 5;we never actually deselect the previous button.

So what we can do is to keep trackof the currently selectedButton and in this case,I'm going to explicitly say that it's a weak stored property.

So this is not going to cause, ah, the- ...

extend the lifetimeof that button which is, after all,owned by the view hierarchy.

And I'm going to declarethat this is a UIButton but it's optional.

Because when we first start out it has no value.

And so, we're going to be ableto check whether it has a value or not.

We add some code to set the selectedButton to the senderat the end of having assigned it.

And then here we can say "if selectedButton" then we're goingto go ahead and clear out the border on that one.

Now this happens to be a object reference so I could do the samein Objective-C with a nil value.

But one of the nice things about optionals in Swift isthat they apply to any typeof value even a Boolean or a scalar.

So in this particular case, I'm just going to go aheadand select the selectedButton's layer borderWidth to 0.

Now you'll notice the exclamation mark there.

This is the unwrapping operator and that saysthat if I have an optional value,then when I've determined it has a value,I get at the actual value.

And if I forgot to check whether it has a value,that will cause a trap if it doesn't.

So this is one of the ways that Swift makes it saferto write your apps, because you can catch these errors earlierwithout having to add a lot of assertions to your code.

So I think we're probably good to go here.

Let's go ahead and take a lookand I'm sure I forgot something somewhere...

"selectED button"!And that's because I mistyped it.

So that shows that this is live right?I'm not playing a QuickTime movie up here.

[Laughter] Okay, so now we're here.

We have our add button.

We bring up the modal sheet.

As we select the various buttons we can seethat we have the border and then we do the, the tint,we tint the buttons down here and, of course,the Save button doesn't yet work.

Now I'm just a UI guy.

So I just make it look pretty.

But to actually do the model level work we're going to haveto ask one of my colleagues to come up here in a moment.

First let's take a look at what we did in this part.

Okay.

So what did we just do?So first of all, we added some Swift code to an Objective-C appand Xcode offered to create us a bridging header,which the next action we'll go onto some more detail about.

We subclassed the Cocoa class- ...

Cocoa Touch class in Swift.

In this case it happened to be a Cocoa Touch class that's partof the standard libraries of Cocoa Touch itself.

But it could also be one of your Objective-C classesthat you've declared.

We used Swift class in the Interface Builderand as I hope you saw, it's exactly like workingwith an Objective-C class.

And that's actually a theme under here that we wantedto feel like exactly the same thing; it's interchangable.

And so now to make this a bit more real in terms of the model,I'm going to ask my colleague Dave to come upand complete the project here or work on it further.

[ Applause ]>> Alright.

Thanks Anders.

What we saw is that you have access to everythingin Cocoa Touch and the power that you've got in Xcodefrom Swift without really doing anything.

But I'm sure what you're thinking now is"what about MY code?What about the Objective-C code that I havein MY target in MY app?"And that's what I want to show you.

As Anders said, we could spend a lot of time in slidesand everything else and I'm actually goingto cut it a little shorter than he didand just go straight into a demo.

And so we come back right where we were beforeand for our purposes the first thing we want do here is alittle bit of tidy-up, and that isto make our UI text field behave the waythat we want for our user.

It offers a great dealof configurability using the delegate pattern.

And to do that we're going to make NewListController conformto UITextFieldDelegate, which is as easy as...

if I could type...

finding our UITextField...

Man, I'm having some time here.

[laughter] It's a comedy show, I promise.

[laughter]There we go.

Alright, something to call out there is-...

[ Applause ]Success! And that's the hardest thing I'm goingto do the whole time I'm up here.

[laughter] So UITextFieldDelegate,all we did here was add the protocol conformance to the endof a common separated list after our class.

In our case it's important because we're actually,we actually have a superclass.

The superclass is the first thing in that listand then our protocols follow.

Now that I have managedto declare textual delegate I'm actually going to take it easyfor the next part and just bring in...

the implementation of TextField should return.

And the only thing we're doing here is resigning firstresponder on our TextField and returningto make sure the keyboard dismisseswhen the user hits return.

Not particularly interesting, but it was just as easyas it would be in Objective-C to go aheadand implement this protocol.

Next, as Anders promised, we are going to look a little bit moreat the interaction with the model side of thingsand actually implement Save.

The first thing I'm going to do in-...

who caught the error here?Somebody knows what I forgot to do, and that is:manage to declare it as a UITextFieldDelegatebut we never actually connected it and that would have madefor an interesting end.

So now that we've got that set up I will control-drag over,manage to hit the button, set it up as an action, call it "Save".

Now, inside here I actually want to interactwith the representation of our documents that we seein the document list on the main screen.

And that's a part of our app target, not a part of ListerKit.

And because of that we have to take a different approach.

We can't just simply import our framework in.

And this is where we make use of the Objective-C bridging headerthat Xcode offered to create for uswhen we created the first Swift file in this project.

So we'll navigate over to that and it gets createdin the same directory -- or in the same group, I should say --as the Swift file that we created.

It's not overly interesting at first.

It simply has a comment that's very instructive.

This is where we put the imports for the classes in our targetthat we want to expose to Swift.

In our case, it's a single class and that is our ListInfo class.

This is the representation that backs the TableView that you seewhen the app initially comes up.

We save that and head back to...

really don't need the storyboard anymore, so, I'm gonna go aheadand collapse things down and let us actually focus on the code,because the wrapping really kind of gets on my nerves.

That's one of the things that I like about Swift,is it's a little more succinct.

So just heading back down to our Save...

Now that we've pulled in the bridging header - or,now that we've added our class to the bridging header --we can actually create one.

I'm going to create it as a "let"because it's going to be constant.

I'm only going to assign it once.

And so my ListInfo is equal ListInfo.....

and, of course, I keep saying "ListInfo"like we instruct you guys to dowhen we're writing Objective-C code we actually use a prefix.

And I've been writing a lot of Swift code lately,so it's not on the forefront of my mind.

So, our ListInfo...

and it offers us two constructors.

One of them takes URL.

The other takes an NSMetadataItemfor that iCloud support we were talking about.

We're going to go with the URL one.

I could construct the URL right here.

A little bit of forethought, thinking forward,I know that I'm actually going to wantto revise this a little bit later and iterate on it.

So I'm going to setup a computed property as a convenience.

Now to declare a computed property is pretty similarto the way that we define a stored property.

And we'll go with var.

I'm going to call it "fileURL".

Now with a computed property we do haveto be explicit about our type.

I'm going to make it optional and that'sbecause if the user actually hasn't provided us a valuein the TextField yet, I can't actually construct a valid URL.

I've got an implementation ready that just happens to make useof the list coordinator from down in the ListerKit.

And after defining the computed property I can come downand make use of it right away.

And you'll notice as Anders had mentioned earlier we don'tactually have to explicitly refer to selfwhen accessing our property.

We set up a few pieces of information that we've capturedfor the user so we'll get the name from our nameFields.

textand the label is going to be equalto our selectedLabel and that looks good.

So now that we've set it up, we actually want to save this outand ListInfo provides us a convenience for that.

And we will createAndSaveWith CompletionHandler.

And this CompletionHandler is actually going to call-...

is going to come back to uswith a Bool letting us know whetheror not the save was successful.

And I could use what code completion's suggesting hereand fillout my completionHandler closure inside of the parentheses.

But because it's the last argument in the calland because it's a closure and it's going to be a little long,I'm actually going to make useof Swift's trailing closure syntax.

And in this case I don't even have to put the parensafter the method call because our createAndSaveWithCompletionHandler actually doesn't take anyother arguments.

So inside of here I will note the variable name that's beingpassed in, which is success....

having more typing problemsso that you guys can get a good laugh.

And I'll just check the value and for now I'm just goingto print a little debug messageto let me know that it was saved.

And just like Cancel, we want to get out of the user's way now,so we'll go ahead and dismiss.

So let's build and run, seethat everything is doing what we want it to do,make sure that everything is good to go.

Bring it up...

Let's see, I need to goto the hardware store a little bit later.

And so we'll name our list hardware, hit return.

Keyboard goes away; that's a good sign.

The hardware store I frequent actually uses orangein the logo rather heavily, so that's goingto help me remember what's going on there.

And I'll go ahead and hit the Save button.

That's not really what we wanted.

I really wanted to see my hardware list show up here.

Did it actually save?I'll go over and check the debug console.

Indeed it did save and just for fun I'll actually stopand run the app again.

And you'll see that it actually did save and get created.

But we never passed anything back to our document listto let it know that we created anything new and we kindof wanted this to not be sitting thereand polling the file system over and over and over again,just looking for new files that might show up.

So for our purposes, we're going to take a pageout of UITextField's book and we're actually goingto use Delegation to pass information backto the ViewController that presented us.

The first step there is usually to define a protocolthat we expect our delegate to conform to.

And in Swift we can do that just as easily as declaring a classor a struct or anything else.

We'll just start with the"protocol" keyword (that I actually spelled correctly)and NewListControllerDelegate.

And I already have a method that I want my delegate to conformto that I've prepared that just takes a new ListControllerand a ListInfo letting it know what's been createdand done over here.

Now at this point this protocol is visible to my Swift codebut I want to make sure that my Objective-C code can see itas well.

To do that it's as simple as adding an attribute at Obj-Cand this is going to go ahead and say,"even though this is all Swift here,we do want to make this availableto Objective-C a little bit later on.

"So now that I have a delegate protocol I'll actually define adelegate and we'll make it weakbecause we don't really want to own it.

We don't want to extend its lifetime.

And I can declare it as being justof the NewListControllerDelegate type.

I don't have to do something like ID and angle bracketsaround my protocol to indicate what's going on here.

I can simply have a property that is of this delegate type.

It's going to be optionalbecause I may not have a delegate.

So now that we've defined a delegate property I think maybewe ought to do something a little more usefulthan printing a debug statement down here.

And for that we're going to reach out to our delegateand I'm going to make use of another Swift feature,which is optional chaining.

So the delegate is an optional.

It may or may not have a value.

By adding a question mark here before actually callingout to the method that we want to invoke, I'm going to be ableto say, "IF I have a delegate --if there is a value there -- make this call.

If there's not, don't do anything.

"[ Applause ]And now I'm trying to remember what the name of it was.

Ah, there we go.

Pass my self and the ListInfo that we just created.

(REALLY not much of a typist, in case you can't tell.

)And at this point we've wrapped up the Swift implementationof this, but we've defined this delegate.

Now we actually need our Objective-C code to be ableto see the Swift code we've just put togetherand interact with it.

To do that I'm going to head back over to the document-...

the, the controller for the document list,and inside of here we're brought to- ...

I mean,what comes to your mind is the factthat the way I make one object in Objective-C availableand visible to another object is by importing its header.

Well, with Swift we don't have headers.

We think that's a good thing within Swift, but we've gotto find a way to bridge the gap back to Objective-C.

And so in that case Xcode's got our back and is goingto provide us with a generated headerthat contains the entirety of our Swift interface.

Being generated, obviously it hasto have a well-constructed naming scheme, and that's goingto be our product name --which in this case is "Lister-Swift.

h".

And so this is a generated header, so I'm going to go aheadand take the time to build, to make surethat we've got the most up-to-date items in it.

And after importing that we will come over here and we're goingto go through basically the same processthat you would ordinarily to implement any of the Cocoaor Cocoa Touch delegates on your own class.

We'll add our protocol conformance and we can pullin our NewListControllerDelegate.

I'm going to choose to use the jump bar to headdown to an appropriate place I feelto go ahead and implement this.

And as I code complete herewith the NewListController didCreateListInfo, you'll noticethat even though we declared this completely in within Swift,what we get is a syntax that matches what I'd expectfrom Objective-C so that everything still feels natural;everything feels like a first class citizen in its place.

Happen to have the implementation...

Wellllll...

The implementation of the last thing ready.

In this case what we're really doing is just updating our datasource and then refreshing the TableViewwith a little bit of new information.

And the very last thing here, or the final step,is that we actually need this ViewControllerto make itself the delegate for our new ListController.

We're using a modal segue,so why not do it in prepareForSegue?Down here we'll just check to make surethat it's the right segue.

We'll grab the newListController and we'll set ourselves --in this case our ListDocumentsViewController --as the delegate.

At this point I fully expect things to do what I want.

And...

Coming up with another list, "WWDC Must Haves".

Not really sure what those are yet,but I'm pretty sure I'm going to think something up.

And this time it actually comes through,shows up in our DocumentViewControllerand just for, you know, proof's sake I can come into it;I can change it around.

I really like this salmon color that they're usingfor the Apple badges this year.

So I'm going to actually pick thatand that's integrating our code.

[ Applause ]And just to head back to the slides for a second,what we've just seen here is that it's very easyto expose our Objective-C code to Swift.

Simply import whatever headers you wantinto the bridging header and they'll be made availableto the Swift in your target.

We defined a protocol in Swift which was as easyas defining a protocol in Objective-C.

And finally, we've exposed that protocol and the classthat we just created in Swift backto the Objective-C code in our target.

And we actually didn't have to do anything there.

Xcode did the generation of the headerthat provided that interface.

So just to reiterate a little bit more when we want to gofrom our Objective-C headersand make our Objective-C objects available to Swift we're goingthrough the bridging header.

This is going to be created- ...

Xcode will offerto create this for you automaticallywhen you add a Swift file to an existing Objective-C targetor an Objective-C file to an existing Swift target.

When we want to get our Swift interface exposedto our Objective-C implementation,there we're looking at the generated headerthat Xcode provides and this is going to be namedafter our product and it's going to be"our product name dash Swift dot h".

One last thing to remember about these,is that the bridging header is created for you by Xcodebut you own it from that point forward.

So it should be something you checkinto your source control system.

It should be something that you maintain, you manageand it's there so that you only exposeto Swift what you want to expose to Swift.

In the case of the generated header, it's just that.

It's generated as part of the build process.

It's going to contain your com- .

.

.

the complete interfacefor the Swift files within your target.

And those are going to be readily availableto Objective-C simply by importing that header.

So at this point to talk with you a little bit moreabout what you can do with frameworks in your product-...

in your projects, I'd like to invite my colleague Jordan up.

[ Applause ]>> Thanks Dave.

Alright, so we've seen how easy it is to dealwith integrating your Swift codeinto an existing Objective-C app.

And Xcode pretty much takes care of all the details for you.

It's available in Interface Builder.

It's going to show up in the simulator.

Everything works just fine.

So I'd like to move a step down in the hierarchyand look at the framework.

So at this point we've been working pretty much the entiretime up in this Lister part of the application,which is the actual application target.

Now we're going to move down to ListerKitwhich handles the model and the object graph for this target.

And specifically we're going to add a new functionality:the ability to add attachments to every list item,something like, oh, a photo or a voice recording.

To do this in Objective-C you would create a new class,add it to your object graph by adding a new propertyand then setting up an interface to mange it and we're goingto do the exact same thing but using Swift.

So I'll start here by going to File, New Fileand this time let's use the Cocoa Touch class template.

I can name this APLListItemAttachment.

Subclass of NSObject and the language, of course, is Swift.

I make sure that it'sin the ListerKit target and click Create.

You notice here that Xcode did not offerto create a bridging header for us.

This is because we're working with a framework target.

In a framework you already have a headerthat specifies the entire contents of the framework.

That's your umbrella header.

So when you're working with a framework targetin Swift everything that's availablein your umbrella header will automatically be visibleto the Swift code, no work required.

So we're going to want attachment objects to persist.

So the very first thing I'm going to do is add a conformanceto a standard Cocoa Touch protocol, NSCoding.

Attachments are made up of two things:their data (which will I represent using NSData)and their type.

For types of data Cocoa Touch likesto use uniform type identifiers, which are a very general wayto represent file and data typesthat the user just stored as Strings.

The next thing to do here is to declare an initializerand that just takes the data and type from outsideand will assign them into our own fields.

But we do need to be careful because the datathat we are given might be an NS mutable dataand somebody might try to change itafter they've created our attachment.

So in order to work around this, we need to call the copy method.

However, copy returns ID in Objective-Cand in Swift that's going to comethrough as the Any object type.

We can't go directly from any object to NSData in Swift,because that's not guaranteed to be safe.

So instead, we haveto explicitly tell the compiler to do a cast here.

And this is important, because if anybody ever implements thecopy method incorrectlyand doesn't return an NSData we would much rather findout about it right here in the initializer than crash somewheredown the line when we try to use it.

On the other hand, we can just assign the type directlyand this is because strings in Swift are values.

Unlike NSString, every Swift string has anindependent existence.

And when you assign across using the equal operator you getindependent strings.

So, whatever somebody does over hereto their string won't affect your string over here.

[ Applause ]So next I need to implement the NSCoding protocol.

(Let's close this for a bit more room.

)And here we can co- (ah!)...

code complete here, no code completion, awesome.

So here I'm implementing the NSCoder initializerand you'll notice something a little funny here.

In Objective-C we'd have the method named initWithCoder.

But in Swift we have an initializer that's justinit coder.

So in order for more consistency in the Swift world,where object creation syntax is a little different,an init method from Objective-C that starts with"initWith" will come into Swift with the "With" dropped.

This ensures a consistent world with Objective-C.

Sure, the implementation of this is pretty much the sameas what you'd expect.

Just call decodeObjectForKeyand again explicitly downcasting to the type we want.

If somebody hands us a bad archive we'll findout about it now rather than crashing later on.

Finally, the last thingto do here is implement the encodeWithCoder methodand this one does not get any name changesbecause that is limited specifically to initializers.

And the implementation of this, again, is very simple.

We call encodeObjectForKey with both the data and the type.

And that's it; this is an entire Swift model objectand it fits on one slide.

I didn't do anything crazy or confusing here beyond someof the things you need to do to be a good Cocoa Touch citizen.

[ Applause ]The next step, of course, is to add this into our object graph.

So I go back to our Objective-C headerand now we have a bit of a problem.

Because last time that we wanted to access Swift codefrom Objective-C what we did is import the generated headerinto the Objective-C file.

But we can't do that herebecause the generated header depends on the Swift.

And the Swift reads the entire public contentsof our framework (via the umbrella header)and that includes this header right here.

So instead, I use exactly the same mechanismthat I have in Objective-C.

This is what we use to break cycles.

It's a forward declaration using @classand I can forward-declare the Swift class justlike I would any Objective-C class.

And now I am perfectly ableto create a property here using the attachment.

The last thing to do, of course, is to update the implementationof the list item to actually handle the attachment and forthat I'm going to import the generated header nowthat we're in a .

m file.

And because this is a framework, and the generated header is partof our public interface, we are goingto use framework syntax to import it.

All that's left to do here now is to update the implementationof this class so that we actually handle thisnew property.

So that means having an extra key for encoding here.

Setting the attachment explicitly to nil,making sure that we can encode and decode it.

And while I'm doing this I'd like you all to notethat this is exactly what you'd be doingif we had implemented the attachment class in Objective-C.

There's nothing surprising going on here.

It's exactly what you would have done before.

Finally we do need to make sure that we update the copy methodso that when we copy a list item,that we actually do get a copy of the attachment as well.

(Square bracket.

)And since we made our attachments immutable using that"let" keyword to define the properties,we can just assign this across directly.

We don't need to do any special copying to ensurethat they are independent and not going to change on us.

So that's it; that's the entire model.

And now you're probably thinking, "Oh great,here we go again, back to Interface Builderto define a new layout, a new ViewController and add a bunchof outlets and actions and hook everything up all over again.

We already saw that!"And you'd be right.

.

.

except that, we're actually really lucky here.

The three of us work in a department with lotsof other great people and another team is workingon a very similar app that needs to dealwith these kind of attachments.

And because their app is new,they've written it entirely in Swift.

But they've also factored out their attachment ViewControllerinto a separate framework, which is a new feature of iOS 8.

So we're going to use their framework, written entirelyin Swift, to implement the interface that dealswith this model object.

To start off here I'm going to go to the bottom hereand check the plus, yet another wayto add new files to our target.

Choose "Add Files Here" and I'm going to the media view folderto select their project, mediaviewer.

xcodeproj.

Once I have this in my project then I can just add thisto our target by going to our own project, selecting the listor target and in the embedded binary section clickingthe plus.

This lets us add the framework directly.

Notice what we just did there.

This is a new feature of iOS to allow embedded frameworks.

Of course, if you're a Mac programmer you're probably usedto this by now.

These embedded frameworks need to be made availableto Interface Builder, to other classes in your project,linked into your binary so that you can actually run it,and copied into the app so thatwhen other people download it they don't needto download the framework separately.

And Xcode 6 did all of that for us without askingif the framework was written in Objective-C or Swiftor a mixture of the both.

[ Applause ]So in our storyboard now.

We can zoom out, and.

.

.

let's bring up the library here to bringout a new ViewController.

And in this case I'm going to set the classof that ViewController to be the media ViewControllerfrom the other framework.

And you'll see the module field here populates as well;this is that feature of Swiftthat keeps different framework classes from steppingon each other at runtime, even without a prefix.

We don't need the view that Interface Builder providesfor us, because it already has one in its own framework.

So I can just delete that.

And now, to make sure that we can actually get to this,I'll select the tables out here and drag over- ...

control-drag,to create a new segue.

Make that a push segue and we'll give that a name: "attachment".

Now we've set up Interface Builder.

We've set up the interface and the model object.

It's time to put them together.

And once again we're going to use a delegate for that.

So let's go to our Objective-C code.

This is the code that displays the lists.

At the top here we have the NotificationCenterwhich is a system framework and the import for ListerKit,which is our own model framework within this project.

I can add a third import for MediaViewer,which is the framework in the other project.

I'm going to hit Build again, to make surethat everything is compiled and up to date.

And now I get code completionfor the MediaViewerDelegate protocol.

Just like before I'm going to jump down to a nice,convenient place in the application to implement this.

And the first thing I'm goingto do is implement a little helper method herethat just returns the selectedItem.

Again, even though this is sort of details of, like,how the application currently works, I want you to rememberthat everything we're doing here is exactly what you doin Objective-C.

From the perspective of this code you can't really tellthat the entire framework was written in Swift.

We even get code completion for the delegate method here.

MediaViewController didChooseNewMedia, type.

And now that we have all of this set up it's really easyto add an attachment to the currently selected item.

So here we say that its attachment is goingto be a new attachment that we create nowby calling alloc initWithData.

Wait a second!We designed this attachment class in Swift,and it had an initializer named "initData, type".

But in Objective-C it's showing up as "initWITHData, type".

So you see that this name translation works both waysso that you have a consistent worldin Swift and in Objective-C.

[ Applause ]I'll do a bit of housekeeping here to make surethat we update our backing storeand now we have everything set up here.

All that's left to do, just like Dave did, is set ourselvesas the delegate for the MediaViewController.

So this starts off the same, where we set the attachmentand we set ourselves as the delegate.

And then we can also set the title of the NewViewControllerand make sure that it's showing the attachment that's actuallyon the selected item.

Or if the selected item does not have an attachment,make sure that the controller isn't showing anything.

So with that, everything should be working.

Let's build and run.

Let's go into the tech toys section hereand you see now we have these disclosure indicatorson each of the items.

We'll go into Thunderbolt this way.

Then I can see it says No Attachment.

But I can click this Edit button using the ViewControllerfrom the media views framework.

That brings up a standard iOS control.

Making sure that our privacy is protected, and, ah.

.

.

This kid looks like he'd really enjoy a Thunderbolt display.

[Laughter] Okay, we can go back to another one of these here;managed to get myself stuck editing.

There we go.

And you can see that the image actually does persistin the Thunderbolt display section.

So it looks like everything's working.

So you saw how easy it was, to not just dealwith a new model object- ...

or, sorry, not just a new objectin your application target,but also a new model object in your framework.

Additionally, this is not related to Swift at all.

But in iOS 8 we now have embedded frameworks.

And Xcode 6 will handle all the details of that for you.

Yes, clap![ Applause ]Finally, once again, we updated our interfaceand added a delegate- ...

adopted a delegate protocol.

And once again I want to impress on youthat it's exactly what we would have done had the delegateprotocol and the ViewController been implemented in Objective-C.

We didn't have to do anything unusual or differentbecause it was implemented in Swift.

So you see how easy it is with Xcode 6 to use user frameworks.

And in general we want you to be treating those the sameas we do system frameworks.

So that means in Swift you'll be using "import MyFramework"and in Objective-C you'll be using"@import MyFramework; (semicolon)".

In general we do want youto be using @import instead of #import.

For Swift- ...

for frameworks containing Swift code this isabsolutely required.

But even for other frameworks, if they've been builtwith Xcode 6 and have the defined module build settingturned on -- which is on, by default --then you have- .

.

.

then you'll have a framework ready for usein Objective-C or Swift.

The only reasons now to use #import are if you are workingwith an older framework that has not yet been rebuiltwith Xcode 6 in a defined module setting or if you're workingwith C++, which does notyet support the modules feature we introduced last year.

So with that, everything seems to be workingand our walkthrough is complete.

I'd like to hand it back to Anders.

[ Applause ]>> Thank you Jordan.

So, over the past hour we've seen several different waysof mixing Swift and Objective-C.

Swift is a better, safer way to do Cocoa development.

It was designed to support the Cocoa frameworks,the Cocoa Touch idioms and the common patternsthat we already know.

It's still Cocoa and Cocoa Touch on iOS.

So that means that the knowledge and experiencethat you've gained over the yearsand the code you have applies to Swift as well.

And as we've seen some of the patternssuch as optionally calling a delegate method are much easierin Swift and much more succinct.

And in other cases you've seen how Swift makes us define ourintentions much more clearly, which can help save us lateron so we don't just accidentally message nilor message an object of the wrong type.

And another thing that I hope you've seen here is we've put alot of effort into making sure that Xcode takes careof the details so thatwhen you're using Objective-C your Swift code lookslike Objective-C and when you're using Swift the Objective-C codelooks like Swift.

And you saw some examples of subclassing Cocoa Touch classes,but that equally applies to your own classes as well.

So for more information about this there is, of course,the Swift book in the iBooks Bookstore,but I'd also especially like to call your attentionto the Using Swift with Cocoa and Objective-C documentthat we have on developer.

apple.

com.

It's available as a PDF file that you can download and readon your favorite iOS device and it goesinto a lot more details about this.

There are several related sessions.

One of them has already been but it's on video.

It's the Introduction to Swift, of course.

Later on today there's going to be a sessionon Swift Interoperability in Depth and that goes into moreof the language details of how to mix Objective-C with Swift.

There's a great sessionon Creating Modern Cocoa Apps coming up and another oneon Building Modern Frameworks so that you can make surethat you make your frameworks embeddable on iOSand useable from Swift.

Thanks and enjoy the rest of the week.

[ Applause]