[ Silence ] [ Applause ] >> Good morning.
Welcome to Session 406: Integrating Swift with Objective-C.
Now many of the Swift demos here at the conference start by creating either a brand-new project from one of 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 some of 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 any of that away or rewrite anything that you don't want to.
Also some of you have really a lot of Objective-C code that 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 using that Objective-C code for a while.
You might want to rewrite it, but it's not going to happen this time around, because you've got an app to ship, etc.
So, Objective-C is not going away.
Both Swift and Objective-C are first class citizens for doing Cocoa and Cocoa Touch development.
And, in fact, we don't want you to spend any time that 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 subsystems that you want to use Swift for that because of its better type safety, its expressiveness, its performance.
Now, many of you have also gained a lot of knowledge and experience in Cocoa and Cocoa Touch through your years of 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 lot of you are going to end up with projects that contain both Swift and Objective-C and we worked hard to make sure that Xcode lets you freely mix Swift and Objective-C.
So this session over the next hour we're going to be talking a little bit more detail than what you've probably seen so far about exactly how that works in practice.
We're going to start simple by just introducing some Swift code into an existing Objective-C app.
Then we'll get a little bit more interesting.
We're going to start to add some Swift code to a model-level framework, which is then embedded in an Objective-C app and call that from Objective-C.
We'll talk about how to start accessing your pure Swift framework which will start showing up from an Objective-C app.
And then we'll talk as we go along about how to adopt some of the common, well-established Cocoa patterns in Swift.
And again Swift is designed from the ground up to be a great Cocoa/Cocoa Touch development language.
And so it has language support for some of the Cocoa idioms that we've gotten used to.
So, I could go on here for, you know, two dozen slides and talk in detail about how this works, but I'd rather just give a demo because 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 framework so it's decently designed here.
It's got a top layer which is the actual app with the view and 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 ahead and run it in the simulator and we're gonna go ahead here and 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 app and it would show up here...
But, for this example we're going to use Swift to add the ability to add a new list in iOS.
Alright, so I'm going to go back here and the first thing I'm going to do is look down here to the group ViewControllers.
And here we have some ViewControllers already written in objectives [ahem] in Objective-C.
I go to File, Create New File, and in this case I'm just going to create an empty Swift file because I want to show you how to get started from scratch.
Xcode has great file templates and can fill in 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 going to make sure that it is going to go into the application target here.
We also see that I have ListerKit, which is my framework and 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 create for 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 some of 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 framework because we want to obviously create our model objects from 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 UIKit and gives me a Swift view of those symbols.
So I'm going to subclass from UIController and 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 rectangles and 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 class of my UIController is.
So I can go up here and now we see that the NewListController that I just created is shown here among all the ones implemented in Objective-C.
So when you access your classes from Swift-...
from Interface Builder, the Swift and Objective-C classes show up next to each other and 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 appearance to 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 storyboard and I'll change the name of that segue to be New List.
Now that's going to be important a little bit later on so that we can access it from within our code.
Okay.
So now, you may have seen in one of the other demos how we can drag from Swift code and connect to 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 drag from 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 weak because 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 property for the stored property- ...
I'm sorry, the IBOutlet attribute for the stored property here.
And this is implicitly weak and also optional because not all the outlets may be connected.
Give myself some space there; I'm going to go ahead and do the same thing here for the buttons.
I'm just going to control-drag these and I'm just going to 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 rescalable to 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 colors from a TableView- ...
uh, from a Plist and show them in 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 type of the sender as any object here.
We don't actually care because we're not going to 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 access to the Cocoa Touch API that we already know.
I can complete here.
I'm not going to need a- ...
I want it to 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 out and 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 here because in this case we will actually want to talk to the button, or compare the button, so we want to have that type.
And as you can see, Interface Builder generates the code and makes the sender be a UIButton.
Before I forget, I'm also going to wire up 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 depending on which button we touch.
Now, I want to show that some of the power of the Swift select statement here, the switch statement.
Unlike Objective-C or other C-based languages, I can actually switch on a wide variety of 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 language and I encourage you to catch one of the later talks about advanced Swift to really get into the depth of what you can use this for.
For right now, to keep it simple, I'm just going to 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 selectedLabel because we're actually choosing labels here represented as colors on the screen.
And then what I can do here is I can say this is an AAPLListLabel.
So this again is an Objective-C type that has been imported through my import of ListerKit up there.
I'm going to start out by saying that 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 has to 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 each of the cases is implicitly ended at the beginning of the next case.
So you don't have the case of C where you implicitly fall through and that's the source of a lot of bugs.
In fact, Swift was explicitly designed to avoid many of the common pitfalls that are common in C-based languages.
Now in this case, another thing about the switch statement is that 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 default and what I'm going to do in this case right here is to use a Swift standard library function to just trap into the debugger.
Because I want to make sure that if I just add new buttons and 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 API to 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 initialize that 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 APIs or 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 say that the view's tint color is going to be the color that corresponds to the label.
And for this we can call another one of our functions that 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 representation of our own Objective-C API.
In Navigate we could actually go back to the header itself that we declared it from.
Alright, so now those of you who are following closely here may have seen a little bit of a problem: we set the borderWidth to 5; we never actually deselect the previous button.
So what we can do is to keep track of 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 lifetime of that button which is, after all, owned by the view hierarchy.
And I'm going to declare that 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 able to check whether it has a value or not.
We add some code to set the selectedButton to the sender at the end of having assigned it.
And then here we can say "if selectedButton" then we're going to go ahead and clear out the border on that one.
Now this happens to be a object reference so I could do the same in Objective-C with a nil value.
But one of the nice things about optionals in Swift is that they apply to any type of value even a Boolean or a scalar.
So in this particular case, I'm just going to go ahead and select the selectedButton's layer borderWidth to 0.
Now you'll notice the exclamation mark there.
This is the unwrapping operator and that says that 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 safer to write your apps, because you can catch these errors earlier without 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 look and 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 see that 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 have to 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 app and 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 part of the standard libraries of Cocoa Touch itself.
But it could also be one of your Objective-C classes that you've declared.
We used Swift class in the Interface Builder and as I hope you saw, it's exactly like working with an Objective-C class.
And that's actually a theme under here that we wanted to 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 up and complete the project here or work on it further.
[ Applause ] >> Alright.
Thanks Anders.
What we saw is that you have access to everything in Cocoa Touch and the power that you've got in Xcode from 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 have in 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 slides and everything else and I'm actually going to cut it a little shorter than he did and just go straight into a demo.
And so we come back right where we were before and for our purposes the first thing we want do here is a little bit of tidy-up, and that is to make our UI text field behave the way that we want for our user.
It offers a great deal of configurability using the delegate pattern.
And to do that we're going to make NewListController conform to 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 going to do the whole time I'm up here.
[laughter] So UITextFieldDelegate, all we did here was add the protocol conformance to the end of 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 list and then our protocols follow.
Now that I have managed to declare textual delegate I'm actually going to take it easy for the next part and just bring in...
the implementation of TextField should return.
And the only thing we're doing here is resigning first responder on our TextField and returning to make sure the keyboard dismisses when the user hits return.
Not particularly interesting, but it was just as easy as it would be in Objective-C to go ahead and implement this protocol.
Next, as Anders promised, we are going to look a little bit more at the interaction with the model side of things and 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 UITextFieldDelegate but we never actually connected it and that would have made for 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 interact with the representation of our documents that we see in 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 header that Xcode offered to create for us when we created the first Swift file in this project.
So we'll navigate over to that and it gets created in 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 target that 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 see when the app initially comes up.
We save that and head back to...
really don't need the storyboard anymore, so, I'm gonna go ahead and 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 do when 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 NSMetadataItem for 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 want to revise this a little bit later and iterate on it.
So I'm going to set up a computed property as a convenience.
Now to declare a computed property is pretty similar to 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 have to be explicit about our type.
I'm going to make it optional and that's because if the user actually hasn't provided us a value in the TextField yet, I can't actually construct a valid URL.
I've got an implementation ready that just happens to make use of the list coordinator from down in the ListerKit.
And after defining the computed property I can come down and make use of it right away.
And you'll notice as Anders had mentioned earlier we don't actually have to explicitly refer to self when accessing our property.
We set up a few pieces of information that we've captured for the user so we'll get the name from our nameFields.
text and the label is going to be equal to our selectedLabel and that looks good.
So now that we've set it up, we actually want to save this out and 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 us with a Bool letting us know whether or not the save was successful.
And I could use what code completion's suggesting here and fill out my completionHandler closure inside of the parentheses.
But because it's the last argument in the call and because it's a closure and it's going to be a little long, I'm actually going to make use of Swift's trailing closure syntax.
And in this case I don't even have to put the parens after the method call because our createAndSaveWith CompletionHandler actually doesn't take any other arguments.
So inside of here I will note the variable name that's being passed in, which is success....
having more typing problems so that you guys can get a good laugh.
And I'll just check the value and for now I'm just going to print a little debug message to 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, see that 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 go to 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 orange in the logo rather heavily, so that's going to 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 stop and 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 list to let it know that we created anything new and we kind of wanted this to not be sitting there and 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 page out of UITextField's book and we're actually going to use Delegation to pass information back to the ViewController that presented us.
The first step there is usually to define a protocol that we expect our delegate to conform to.
And in Swift we can do that just as easily as declaring a class or 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 conform to that I've prepared that just takes a new ListController and a ListInfo letting it know what's been created and done over here.
Now at this point this protocol is visible to my Swift code but I want to make sure that my Objective-C code can see it as well.
To do that it's as simple as adding an attribute at Obj-C and this is going to go ahead and say, "even though this is all Swift here, we do want to make this available to Objective-C a little bit later on.
" So now that I have a delegate protocol I'll actually define a delegate and we'll make it weak because we don't really want to own it.
We don't want to extend its lifetime.
And I can declare it as being just of the NewListControllerDelegate type.
I don't have to do something like ID and angle brackets around 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 optional because I may not have a delegate.
So now that we've defined a delegate property I think maybe we ought to do something a little more useful than printing a debug statement down here.
And for that we're going to reach out to our delegate and 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 calling out to the method that we want to invoke, I'm going to be able to 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 implementation of this, but we've defined this delegate.
Now we actually need our Objective-C code to be able to see the Swift code we've just put together and 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 fact that the way I make one object in Objective-C available and 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 got to find a way to bridge the gap back to Objective-C.
And so in that case Xcode's got our back and is going to provide us with a generated header that contains the entirety of our Swift interface.
Being generated, obviously it has to have a well-constructed naming scheme, and that's going to 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 ahead and take the time to build, to make sure that we've got the most up-to-date items in it.
And after importing that we will come over here and we're going to go through basically the same process that you would ordinarily to implement any of the Cocoa or Cocoa Touch delegates on your own class.
We'll add our protocol conformance and we can pull in our NewListControllerDelegate.
I'm going to choose to use the jump bar to head down to an appropriate place I feel to go ahead and implement this.
And as I code complete here with the NewListController didCreateListInfo, you'll notice that even though we declared this completely in within Swift, what we get is a syntax that matches what I'd expect from 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 data source and then refreshing the TableView with a little bit of new information.
And the very last thing here, or the final step, is that we actually need this ViewController to 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 sure that 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 DocumentViewController and 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 using for the Apple badges this year.
So I'm going to actually pick that and 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 easy to expose our Objective-C code to Swift.
Simply import whatever headers you want into the bridging header and they'll be made available to the Swift in your target.
We defined a protocol in Swift which was as easy as defining a protocol in Objective-C.
And finally, we've exposed that protocol and the class that we just created in Swift back to the Objective-C code in our target.
And we actually didn't have to do anything there.
Xcode did the generation of the header that provided that interface.
So just to reiterate a little bit more when we want to go from our Objective-C headers and make our Objective-C objects available to Swift we're going through the bridging header.
This is going to be created- ...
Xcode will offer to create this for you automatically when you add a Swift file to an existing Objective-C target or an Objective-C file to an existing Swift target.
When we want to get our Swift interface exposed to our Objective-C implementation, there we're looking at the generated header that Xcode provides and this is going to be named after 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 Xcode but you own it from that point forward.
So it should be something you check into your source control system.
It should be something that you maintain, you manage and it's there so that you only expose to 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 interface for the Swift files within your target.
And those are going to be readily available to Objective-C simply by importing that header.
So at this point to talk with you a little bit more about 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 deal with integrating your Swift code into 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 hierarchy and look at the framework.
So at this point we've been working pretty much the entire time up in this Lister part of the application, which is the actual application target.
Now we're going to move down to ListerKit which 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 property and then setting up an interface to mange it and we're going to do the exact same thing but using Swift.
So I'll start here by going to File, New File and 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's in the ListerKit target and click Create.
You notice here that Xcode did not offer to create a bridging header for us.
This is because we're working with a framework target.
In a framework you already have a header that specifies the entire contents of the framework.
That's your umbrella header.
So when you're working with a framework target in Swift everything that's available in your umbrella header will automatically be visible to 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 conformance to 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 likes to use uniform type identifiers, which are a very general way to represent file and data types that the user just stored as Strings.
The next thing to do here is to declare an initializer and that just takes the data and type from outside and will assign them into our own fields.
But we do need to be careful because the data that we are given might be an NS mutable data and somebody might try to change it after 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-C and in Swift that's going to come through 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 have to explicitly tell the compiler to do a cast here.
And this is important, because if anybody ever implements the copy method incorrectly and doesn't return an NSData we would much rather find out about it right here in the initializer than crash somewhere down the line when we try to use it.
On the other hand, we can just assign the type directly and this is because strings in Swift are values.
Unlike NSString, every Swift string has an independent existence.
And when you assign across using the equal operator you get independent strings.
So, whatever somebody does over here to 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 initializer and 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 just init 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 same as what you'd expect.
Just call decodeObjectForKey and again explicitly downcasting to the type we want.
If somebody hands us a bad archive we'll find out about it now rather than crashing later on.
Finally, the last thing to do here is implement the encodeWithCoder method and this one does not get any name changes because 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 object and it fits on one slide.
I didn't do anything crazy or confusing here beyond some of 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 header and now we have a bit of a problem.
Because last time that we wanted to access Swift code from Objective-C what we did is import the generated header into the Objective-C file.
But we can't do that here because the generated header depends on the Swift.
And the Swift reads the entire public contents of our framework (via the umbrella header) and that includes this header right here.
So instead, I use exactly the same mechanism that I have in Objective-C.
This is what we use to break cycles.
It's a forward declaration using @class and I can forward-declare the Swift class just like I would any Objective-C class.
And now I am perfectly able to create a property here using the attachment.
The last thing to do, of course, is to update the implementation of the list item to actually handle the attachment and for that I'm going to import the generated header now that we're in a .
m file.
And because this is a framework, and the generated header is part of our public interface, we are going to use framework syntax to import it.
All that's left to do here now is to update the implementation of this class so that we actually handle this new 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 note that this is exactly what you'd be doing if 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 method so 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 ensure that 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 Builder to define a new layout, a new ViewController and add a bunch of 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 lots of other great people and another team is working on a very similar app that needs to deal with 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 ViewController into a separate framework, which is a new feature of iOS 8.
So we're going to use their framework, written entirely in Swift, to implement the interface that deals with this model object.
To start off here I'm going to go to the bottom here and check the plus, yet another way to add new files to our target.
Choose "Add Files Here" and I'm going to the media view folder to select their project, mediaviewer.
xcodeproj.
Once I have this in my project then I can just add this to our target by going to our own project, selecting the list or target and in the embedded binary section clicking the 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 used to this by now.
These embedded frameworks need to be made available to 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 that when other people download it they don't need to download the framework separately.
And Xcode 6 did all of that for us without asking if the framework was written in Objective-C or Swift or a mixture of the both.
[ Applause ] So in our storyboard now.
We can zoom out, and.
.
.
let's bring up the library here to bring out a new ViewController.
And in this case I'm going to set the class of that ViewController to be the media ViewController from the other framework.
And you'll see the module field here populates as well; this is that feature of Swift that keeps different framework classes from stepping on each other at runtime, even without a prefix.
We don't need the view that Interface Builder provides for 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 NotificationCenter which 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 sure that everything is compiled and up to date.
And now I get code completion for 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 going to do is implement a little helper method here that just returns the selectedItem.
Again, even though this is sort of details of, like, how the application currently works, I want you to remember that everything we're doing here is exactly what you do in Objective-C.
From the perspective of this code you can't really tell that 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 easy to add an attachment to the currently selected item.
So here we say that its attachment is going to be a new attachment that we create now by 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 ways so that you have a consistent world in Swift and in Objective-C.
[ Applause ] I'll do a bit of housekeeping here to make sure that we update our backing store and now we have everything set up here.
All that's left to do, just like Dave did, is set ourselves as the delegate for the MediaViewController.
So this starts off the same, where we set the attachment and we set ourselves as the delegate.
And then we can also set the title of the NewViewController and make sure that it's showing the attachment that's actually on 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 here and you see now we have these disclosure indicators on 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 ViewController from 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 persist in the Thunderbolt display section.
So it looks like everything's working.
So you saw how easy it was, to not just deal with a new model object- ...
or, sorry, not just a new object in 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 interface and added a delegate- ...
adopted a delegate protocol.
And once again I want to impress on you that it's exactly what we would have done had the delegate protocol and the ViewController been implemented in Objective-C.
We didn't have to do anything unusual or different because 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 same as 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 you to be using @import instead of #import.
For Swift- ...
for frameworks containing Swift code this is absolutely required.
But even for other frameworks, if they've been built with Xcode 6 and have the defined module build setting turned on -- which is on, by default -- then you have- .
.
.
then you'll have a framework ready for use in Objective-C or Swift.
The only reasons now to use #import are if you are working with an older framework that has not yet been rebuilt with Xcode 6 in a defined module setting or if you're working with C++, which does not yet support the modules feature we introduced last year.
So with that, everything seems to be working and 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 ways of 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 patterns that we already know.
It's still Cocoa and Cocoa Touch on iOS.
So that means that the knowledge and experience that you've gained over the years and the code you have applies to Swift as well.
And as we've seen some of the patterns such as optionally calling a delegate method are much easier in Swift and much more succinct.
And in other cases you've seen how Swift makes us define our intentions much more clearly, which can help save us later on so we don't just accidentally message nil or message an object of the wrong type.
And another thing that I hope you've seen here is we've put a lot of effort into making sure that Xcode takes care of the details so that when you're using Objective-C your Swift code looks like Objective-C and when you're using Swift the Objective-C code looks 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 attention to the Using Swift with Cocoa and Objective-C document that we have on developer.
apple.
com.
It's available as a PDF file that you can download and read on your favorite iOS device and it goes into 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 session on Swift Interoperability in Depth and that goes into more of the language details of how to mix Objective-C with Swift.
There's a great session on Creating Modern Cocoa Apps coming up and another one on Building Modern Frameworks so that you can make sure that you make your frameworks embeddable on iOS and useable from Swift.
Thanks and enjoy the rest of the week.
[ Applause]