 Welcome to Elixir Conf. I hope everyone's having a great day so far. I hope everyone's excited that we're in Orlando. I know Disney was always my favorite vacation growing up, and so I was like beside myself when I learned that we were going to have Elixir Conf in Disney World, and I was going to get to talk to really cool people about Elixir all day and then go to Disney at night, so I'm like beside myself. My name is David Stump, and I'm here today to talk about taking Phoenix beyond the browser, specifically building real-time applications with Swift and Phoenix. The overall goal for today is to convince you, to tell you, to show you that Phoenix is great for being the server-side component to your mobile apps. Additionally, Phoenix comes with real-time features out of the box that allow you to build some really, really incredible, powerful real-time apps with Swift. To do that, we're going to get started with some of the features that make Phoenix so great at being a mobile backend. And one of those Phoenix features, obviously, is channels, web sockets, which we will dive into a little bit. We'll talk about what a web socket is, how Phoenix approaches these web sockets, and how really the engine is driving our real-time behaviors. Following that, we're going to talk about Swift. I wish I had enough time to talk about why all the reasons that I think Swift is awesome. But instead, we're going to do kind of a glance at Swift. We're just going to talk about really what it is, from the types that Swift allows us to use, as well as one really quick example of a programmatic principle in Elixir, followed by that same principle in Swift. The purpose for that is just to kind of give you some approachability to Swift, if you don't have any already, if you have never encountered Swift before, for when we get to the later demo part of our talk, of my talk, it seems approachable, and it seems sane, and it seems a little easier to follow. So that is what, like I said, the next part of the talk, which is the meat of the talk, which is a demo. We're going to showcase a real-time iOS chat app that is communicating with a Phoenix server that I have running on my machine. The Phoenix server is Chris McCord's Phoenix chat example, and we're going to showcase all of the non-boiler plate code that it takes to write a real-time iOS app that's going to talk to that Phoenix instance. So we're going to go through that. We're going to go through why the code does what it does, how it's stable, what it offers us. And finally, we're going to wrap up, and we're going to talk about, just kind of reinforce what we learned, why Phoenix is so great with Swift, and then just kind of explore really, really briefly a few larger, more high-level possibilities with real-time apps with Swift and Phoenix. The first thing that I wanted to touch on really briefly, I'm going to try to be brief with this, I swear, because this is the slide that everybody cares about the least, but who on Earth am I? My name is David Stump, like I said. I'm the lead developer for Little Lines, which is a consulting firm out of Dayton, Ohio. We also are out of Seattle. I graduated from Butler in 2005 and went on to get my master's degree in human-computer interaction from DePaul. I've worked on most popular web stacks at one point or another through my career, and along that way, I ran into Ruby and I really fell in love with its expressive nature a while ago, and that really introduced me to Matt, Sears, who at the time still is and was Little Lines, and I started my journey with them. While I was working at Little Lines, I had the pleasure of working with Chris McCord, and it was infectious to see how enthusiastic he was about Elixir when everybody myself included had zero idea what Elixir was. Throughout that kind of time, while I was working with Chris, I was fortunate enough to see him start to build Phoenix and to see the care and dedication that he put into Phoenix. It was impossible not to really get caught up in some of the possibilities that are amazing to see today, just from the care, like I said, the care and dedication that he took in starting that platform. So that was amazing to watch, and I've been enthralled with the community and the stack ever since. So speaking of Phoenix, let's get to what we're all here to talk about. Why should I choose Phoenix as my mobile backend? So while discussing this today, we're gonna talk about a fake app that I'm going to write and is going to make me millions of dollars, and that app is called InstaFlicker. It's an Instagram clone, and I'm gonna get millions of users and I'm gonna have millions of dollars. All I have to do is figure out how to build it. So I'm making a checklist for server-side features that I need for my brilliant idea. And the number one giant red letter feature that I need is speed. This really isn't unique to native apps, but we're talking about native apps here, so that's really what I'm focused on, but anytime you choose any framework for anything, speed is usually among the number one features that you want. So I know there's like a gray area, especially more and more every passing day with responsive apps when you're talking about what is mobile. Since we're talking about Swift, when I talk about mobile, I'm more referring to native apps. And when I have a user that's on a native app, I know that they're concerned with speed and they're usually on the go more so than other apps. I want my app to be able to deliver them an experience. I want them to be able to do whatever they're gonna do, and I want them to be able to get it done quickly and God forbid get back to driving. So I'm sure you've all seen the Phoenix, or installed Phoenix yourself, seen the Phoenix demo, and seen that funky you character that you get when you look at response times. I will shamelessly admit, I had to look up what on earth that funky you sign was because I had no recollection of high school science at all. So it turns out that stands for microseconds. Microseconds are fantastic for my little checkbox for what I wanna choose. So Phoenix has speed and we have it in droves. The next thing that I want for my, the server side can put it from Emuable app is fault tolerance. And besides the big shiny marquee on the side of Elixir and Phoenix, what does this mean to me and what does this mean to my app? Excuse me. Well, if I have millions of users, like I said, I obviously will have, and user 1 million and 27 encounters a problem or some process that they have running encounters a problem, I want all other users on my app to continue having a great experience. And in a perfect world, if I could choose the perfect backend, that user would also continue to have a great experience. So without really delving in because it's probably multiple more talks to really what supervisors do, Elixir and ultimately then Phoenix comes with a strategy that allows me to tell failing processes, what strategy I want them to do and how I want them to hopefully continuing allowing the user to use my app. So I have fault tolerance with this stack. Fantastic. The next box that I want to check is concurrency and this really ties back into the first one because why do I want concurrency? I want concurrency because concurrency is awesome and it makes me feel really cool. But my users want concurrency because all they really care about is that my app is fast. And concurrency allows me to build an app that feels even faster than it would otherwise. If I have my Insta Flickr clone, I should have picked an app that was easier to say. If I have my Insta Flickr clone, I can have a process running that is in charge of syncing with my camera roll on my iOS device. I can have another process running that's downloading all of the user profile data. I can have another process running that's downloading my image feed, uploading my image, whatever I want. I'm working on a stack where I can spawn literally millions of processes for whatever I need to do. And it seems sane, it seems completely normal, but the speed increase that I get from doing all of those things at the same time versus all of those things one at a time is important and cool to me, but ultimately it's more important to my user because my app gives them what they want and it gives it to them quickly. So the next thing I want is I want scalability. And I'm gonna talk about scalability really quickly from two aspects, a technological aspect and a human aspect. So what do I want from it as a technological aspect? I want it not to die. And so luckily I was gonna reference the blog post where Chris McCord used it in his keynote. Now almost all of us, if not all of us, have seen the two million connections to channels and how well it behaved. And it could be wrong, but I think the problem there was not a Phoenix one when they stopped the two million as it was trying to provision more ports and a physical one, which is incredible. So from a technological standpoint, my stack is scalable and especially since we're talking about real-time features today, my stack is very scalable. So what do I mean from a human standpoint? Well, from a human standpoint, I want one that allows me to scale my InstaFlicker company. I want one that allows me to scale my team. And what does that mean to me? Well, I need a community. I need an ecosystem. I need people that are passionate about what my app's built on. If I choose a fad that has a grand total of 12 people that know it today, I'm taking a pretty big risk that that's gonna continue to be around for the lifestyle of my company. So I need something that allows people to be excited about what they're working on and to really scale their knowledge as they go. I need a community that's enthused, which you all are. And I need a community with established patterns, established libraries. People have thought about it for a while and have come up with things that are great, things that are terrible. And luckily, Phoenix is built on Elixir. Both have passionate communities and both are built on Erlang, which has been around for decades. So I'm not working with something where in a month, all of the things that they've come in, all of the theories, all of the practices that they've come in are completely obsolete and out the window. So that is fantastic for me as far as deciding which framework to choose. The last one is maintainability. I'm gonna do the same thing. I'm gonna talk about maintainability from a server side, from a technological stack. And I'm also gonna talk about it from a human perspective. And it's very similar. It's very similar to me to scalability. And that the server side component of maintainability comes with, part of that comes with the language, part of that comes with the stack, part of that really ties into scalability. How easy is this to maintain? Like I said, with supervisors getting into hot code reloading, which Chris touched on in his keynote today, which sounds even more promising than it already was, with Elixir having things like hot code reloading and allowing me to deploy features as I need to without destroying anyone's user experience is definitely great in my checklist of things that I want from my server side app. Also maintainability is, it kind of ties in a little bit to the human level, but the interest, the ease with which I can ration about the code that I'm writing. Elixir is a beautiful language. It's the first language that I've had, albeit I'm only 33, so I've seen languages, but I don't have a decades of experience going on here, but in the languages I've had the chance to write in, only Ruby back in its kind of early days really gave me the same sense that I get when I look at Elixir now in hiring people that are really passionate about the language that they write, the expressive nature of the code itself, and some of the really, really cool innovative patterns that you see people coming up with that a year from now I can look at and still think that looks pretty awesome. So that really ties in kind of the human level of maintainability as well as well as the technological level itself. So Phoenix checks every box that I have and then some. It really gets like a check plus I guess for concurrency, but that's neither here nor there. So I summed it up as why choose Phoenix? You should choose Phoenix because it's packed with all the features necessary to handle world-class mobile apps. I'm gonna apologize in advance. This is, we're talking about Swift. Swift was made by Apple. I could not resist, but add the following slide, but wait, we have one more thing. WebSockets. WebSockets really to me were the cherry on top of Phoenix. Phoenix, if I'm building a JSON API, it's already great. It's already great. It's already a fantastic choice for our mobile backend. Phoenix comes with WebSockets out of the box in the form of channels, and WebSockets allow us to build real-time applications that enable interactions from every device. So to start with, what on Earth is a WebSocket? Well, Wikipedia tells us that a WebSocket is a protocol providing full duplex communication channels over a single TCP connection. Back to the shameless self-analysis here. I definitely had to look up what on a full duplex meant, and full duplex means allowing communication in both directions. So from a human non-wikipedia level, what does this mean for us? This means we can establish one single connection and send and receive messages as much as we want as long as we have that connection established. And that's pretty incredible. That really is the engine, that really is the heart at our real-time functionality. If we have a hub, whatever abstract thing we wanna think that is being, and we allow people, no matter what device they're on, to connect to that hub, and then they can send and receive messages as much as they want once they're connected to that hub, that really is what we're talking about when we're talking about real-time apps, whether that be from the web, from an iOS device, from an Android device, or for crazy other things like embedded hardware, whatever you wanna talk about. How does Phoenix interact with these web sockets? Well, Phoenix has an amazing web socket layer called Channels. This is another one of those things where my initial presentation had probably like 50 slides about how cool channels were, and I would be here for about three hours. So, needless to say, channels are awesome. Phoenix comes with a web socket layer called Channels out of the box, and what does this mean for us? Why is it important that it comes out of the box? These rails, I can install a gem that gives me some form of web socket layer. Ignore Rails 5 and ActionCable for a moment. But, what does this mean for me? This means that I have zero additional code. I have zero additional dependencies. I really don't have anything else that I need to do. I mentioned how great this was for just the normal, flat JSON API layer for a mobile app. If later on Instaflicker takes off and I want to reload that feed in real time, I want to reload user data in real time, I have a tool to do it, and I don't have to really do anything to start using it other than dig in and start writing code. So, let's talk about, this is very, very, very brief, very, very abbreviated, but what is a channel? So, we're gonna use Chris McCord's Phoenix Chat example today, which mirrors a lot of the examples from the actual guides themselves, and so we're gonna build a Rooms channel. So, we have a Rooms channel here that's gonna allow people to connect to it, and as long as they connect to the lobby, they're all gonna be able to chat. If, however, they want a private room, in this case, for simplicity's sake, we're just gonna go ahead and boot them out and say you're unauthorized for that, but once we get this implemented, you could go on and add that feature if you wanted. So, what do I need? The first thing that I need is I need a join function. I need some way for somebody to join this channel. So, I have two to find here, and we're gonna use pattern matching to decide whether the topic that they're attempting to join is the lobby or whether the topic is one of those private channels. If it is the topic, I'm gonna tell it to do all of the things, tell me okay, and continue on its merry way. If, unfortunately, it's a room, but it's not a lobby, go ahead and tell them they're not authorized to be in that room, and we're gonna move on. The last really main function type feature that I wanna deal with for today's chat is the handle in function for handling events. So, in this case, I'm gonna handle in the new message event, and I'm gonna do things like I'm gonna broadcast to the whole socket that there was a new message, and pull off the user and the body from that message so it's easy to digest for everyone. Then I'm gonna have a few boilerplate end lines here. I'm gonna pass okay, I'm gonna pull the body off, and I'm gonna assign the user to the socket. This is an abbreviated version of this channel. There's definitely more things you could do, handle out, handle info. This is not the entirety of the channel API by any stretch, but this is more or less all that I need to start coming up with a functional channel that will allow people to chat, which is pretty incredible given the brevity of this code. So, Chris actually did a good job in already starting this topic today, which was unexpected and awesome, but what are some caveats to using WebSockets? So none of these are reasons not to use WebSockets. I think WebSockets are awesome, and the real-time behaviors, they power are awesome. These are just some caveats of things to think about when you're either reaching for a client that allows you to use WebSockets, or you're implementing your own. And the first is missed messages. And I quite honestly had come up with the tunnel example, but now that's what Chris said, and I don't really have another one off the top of my head, so we're gonna go ahead and continue using the tunnel example. So I go through the tunnel, I disconnect from the socket while I'm inside of that tunnel. Any messages that were sent through that connection while I was going through the tunnel, unless your application implements some form of persistence those messages are gone and I'm not gonna receive them. There's definitely numerous ways to fix this, like I said with either a client that goes ahead and implements this for you or with your own app implementing some form of persistence if that's crucial to your design. The next step is buffering, and not necessarily Netflix buffering, but in this case if I'm going through that tunnel and I'm typing and I'm typing messages, I want an implementation that will create a buffer queue for me that will go ahead and once I've reached the other side of the tunnel and I've re-established a sane connection, we'll go ahead and go one by one through the buffer queue and send those messages, giving me as limited of a user experience interruption as I can possibly have. That really ties in to the last one, which is reconnection. So I want a client that has some sane strategy for reconnecting to the socket. If I go through that tunnel, I don't want the user to have to really know that we disconnected or if they do, have to do anything to reconnect to the socket as soon as we're able. So I want a client that's gonna go ahead and implement some sane strategy for me to reconnect to the socket as soon as I can and like I said, preserve the user experience as much as possible. Like I said, none of these are reasons not to use web sockets in any way. These are just things that I would look for and make sure that if you're reaching for a client or implementing one, they're somewhere in your mind or in the creator of the client's mind, some way of solving each one of these. The name of my talk is beyond the browser and why is that? That is because web sockets aren't just for the web. This is really kind of the cool moment for me when Swift first came out and Phoenix was first being built and I wanted some way to play with both of them. So I've had to play with a way to get them both to interact and the sanest way that I thought of doing that was with web sockets. And it's no mind-blowing notion. It's nothing crazy. It's extremely obvious, but at the time it wasn't something that I had really ever played around with or I had given any thought to that anyone can connect to these web sockets. All major browsers now can. There's repositories, libraries on iOS, on Android. There's numerous on both. We're gonna deal with Starscream a little bit today. I don't know the clients in Java very well, so there may be one that is obviously used other than these. I'm gonna post all of these on GitHub after so somebody please tell me if there's a much, much, much better way of dealing with web sockets in Java than the couple that I have listed here. But anyway, it just seemed awesome to me that we're not just dealing with something that allows Chrome and Safari to interact together. This really is any device. But today we're dealing with iOS and we're dealing with Swift. So I figured I'd talk about the three main clients I've had exposure to that really marry Phoenix and Swift. I've come across Birdsong, Phoenix WebSocket and Swift Phoenix client that all do a great job of allowing you to connect your Swift access to Phoenix. They're maybe the same thing. There may be more. This was at the time that I was really coming up with these slides, that these were the main ones that I found. I don't mean to leave anyone off the list. If anyone comes up with one later or has one now, I would be happy to either add it to the slide or add it to any GitHub discussion because the more the merrier. Full transparency I wrote the last one. It is no better in any way than the other two. And if you're planning on writing a Swift app, I heavily encourage you to look at all three of them and decide which one and which style works best for you. But for today, we're gonna deal with Swift Phoenix client because I wrote it and I'm more familiar with it. So let's talk about Swift. Like I said, I wish this could tell you all of the reasons that Swift is awesome and I really enjoy writing in Swift. But this really is just a glance at Swift so that our demo seems a little bit more approachable. Swift came on the scene in 2014. Apple debuted it at, I believe they're WWDC. Prior to that, Objective C was the language of the land. And just to clear up any confusion or any misjudgments of what I say, Objective C has written some amazingly powerful world-class apps that have made people insanely wealthy and will continue to do that for a long time. That said, there's been a much heavier adoption to Swift in the fact that it seems, in a small way like Elixir did, to be a language that allows me to be a little bit more expressive and a little easier to really digest and reason about than the Objective C apps were in the past. And I should caveat a giant parentheses for some people. In 2015, Swift was open source which was really a watershed moment in my humble opinion because while I liked Swift even before it was open source and I have an iPhone, I enjoy, I'm fine with Apple products, but it's nice that one company is not really the shepherd of something that I'm devoting a lot of my time and resources to and ultimately my business if I'm writing my app in Swift. 2016 to day, Swift is still awesome. It would be even awesomer if I could write here that Swift is functional, but that would be a lie because it's not. I will say that there's a larger functional community in Swift than in most other languages, non-functional languages, that I have had the pleasure of encountering. There really is a lot of strong emotions and patterns around functional programming in Swift that I see kind of from a core level than some other apps. I mean, I will put a note out there, I'm in no way associated with this. There is a functional Swift book that you can look up at objc.io. It is great, it looks great, and it'll talk way more about functional patterns in Swift than I could ever think of. So I highly suggest that you check that out. So what kind of basic types do we have in Swift? Obviously, I have to, maybe not obviously, I have to declare my types in Swift. So Swift comes with very sane types, none of these are really surprising. I have an int, I have a float, I have double, bool, string, and I have a character. We'll get to the last one in a second. You'll notice that I put let in front of each one of these variables. Let implies immutability. There's no rule, but the established pattern of anything that I've ever had exposure to or anyone I've ever met is you always reach for let first and you let your compiler scream at you that you have to make something var before you make something mutable. Other than that, the last kind of odd person out, odd type out here, depending on your background, some people might have had exposure to this, some people might not as an optional. And when I'm declaring my types in Swift, an int as an int can only be an int unless it's an optional int, and then it can be nil. So if I make a type optional, that means it can be nil. And this really is pretty awesome, just kind of going along with other languages where I have to define type because as long as I'm dealing with not an optional or if I am dealing with an optional, I've unwrapped it safely, I know that my code is not nil and I know that I'm not gonna run into any unexpected nil errors. Like I said, not like world changing, but that really is a cool type and a cool feature that Swift offers. So the thing that I thought we would do today is I thought iteration was pretty sane, pretty straightforward to showcase the lecture and then showcase Swift and how they both would deal with this one programmatic principle. As a side, before someone tweets it, I am aware that they're shorthand for both of these, but I thought a little more straightforward today to showcase the non-shorthand version of this particular instance in both Elixir and Swift. So if I have my Elixir and I wanna iterate here, I have a bucket, I have an array of numbers, one, two, and three. So what do I wanna do? I wanna go over all of those numbers and I want something to give me the sum of all of the numbers that I have in my array. So I'm gonna go ahead here and reach in the enu module. I'm gonna call reduce. I'm gonna reduce over the numbers. I'm gonna start with the initial value of zero and I'm passing a function. This function takes the num variable, it takes our accumulator. The num variable is the current value of the iteration we're on and the accumulator is the return value of the last iteration. So what I wanna do here is I wanna say accumulator plus num. In the end, that will set the output of all of that to sum. When I print it out, I get six. Pretty straightforward, pretty easy. So how does Swift deal with the same exact problem? Well, here I have let numbers equal one, two, three. I have the same numbers bucket. I'm gonna define my sum variable here and I'm gonna set it to numbers.reduce. Just like before, I'm gonna give it the initial value of zero. Here's a slight difference though. In Swift, if the last argument that I'm passing in here, the last parameter is a closure. If it's an anonymous function, I can use this curly bracket syntax outside of the last parentheses. This is basically, I wanted to showcase this here today because in the Swift Phoenix client code that we'll show later, you'll see the same code used a lot for code that you wanna execute after you've joined a socket or after an event's been received over a channel. So usually in those cases, it's the last callback that you call in that function. So in this case, we're gonna do the same exact implementation. We're gonna call ACC plus num, print out the sum and the sum equals six. I'm not trying to imply here that they're apples to apples by any universal stretch from a lecture to Swift, but only if you've had no exposure to Swift as compared to some of the objective seed that came before it. It really is sane to reason about and pretty straightforward when you read it. For much more in-depth playing with Swift for demos, first of all, I would recommend you go to Apple has fantastic demos. There's also a site raywenderlick.com that is an awesome example of how to start Swift out from scratch. But one of the greatest things that I like about playing with Swift is package with Xcode, I get Swift Playgrounds. And this is just a file that I can open, gives me a place to enter my Swift on the left and a place where it'll show me the real-time response on the right. And this is pretty cool because I can do something as simple as the reduced example that I showed today and play with it or I can do things like concurrency and threading in Swift and see how that behaves. I can play with functional programming principles. And there really is a Playground where I can just play with Swift and see how the language or libraries work. There's also an iOS app coming. I don't think it's out yet, but that could be wrong. But, okay, it's iOS 10 only. It is coming then to help learning Swift on the iPad that looks fantastic. So without further ado, let's get real-time Swift with Phoenix Channels. So I need two things. I need Phoenix and I need Swift. So for my Phoenix app, like I said, I'm using Chris McCord's Phoenix Chat example on my server. That's vanilla. I didn't do anything to it. And if you're following along later at home, literally git clone mix depths.get mix phoenix.server and you've got the chat app that I'm using for this talk today on localhost 4,000. So next, I need my Swift app. So I have Xcode. I didn't want to file in a new project and I chose Swift as the language of my project. Like I said, for anybody following along later, this is just a single view app. The next section deals with a package manager called Cocopods. I had thought about delving into it a little bit, but there's many, many, many options for package managers on Swift. The new Swift 3 is coming out with Swift Package Manager, which is its own implementation. There's Cocopods, which is what this is. There's Carthage. And there's also what my client began as, which is literally just pulling the files physically into your app. So there's multiple ways of dealing with this. In this case, we're gonna deal with Cocopods. Cocopods looks like adding a dependency to your Phoenix app or Rails app, kind of RubyGems-esque. I'm gonna call pod init from my root directory here of the project. It's gonna go ahead and create a pod file more for me where I'm gonna add pod Swift Phoenix client and then I'm gonna run pod install. That'll go ahead and import all of my dependencies, Swift Phoenix client in this case. Swift Phoenix client has Starscream as a dependency. Starscream's really the underlying tool that we're gonna use to establish our WebSocket connection and get any responses from that WebSocket. And that's gonna generate for me an XC workspace file. That's what we're gonna work with. That includes the boilerplate code for my app as well as all of the pods, all of the dependencies pulled in that I need to use. So we have, so we now have a Swift app and we have a Phoenix app. We're gonna go over the code to make them talk to each other. So please hold all judgments of my world-class UI design until sometime later, but we have a chat app. And in this chat app, we have a text view. It's gonna be our chat log. I have a username UI text field and I have a message UI text field. And I also have a send UI button. And that's really it. That's all we're gonna deal with. It's a little hard to show, especially at this resolution without looking really messy and really hard to follow. But you can open up and split view my code and my UI, my storyboard that I've got here. Control click to create what are called outlets or actions in our code that allow us to interact with our UI elements inside of our code. So I've gone ahead and done that. This is a, like I said, a single view. There's only one view to this app, this chat view. And so there's only one view controller. So we're gonna pop into our view controller and see what's there. So like I said, I have these four outlets here. I have chat view, which is our chat log, that text view. I have message field, which is our message field. I have user field, which is our user field. And I have a send button, which is our UI button. Down here, there's an IB action. It's the send message action for what we wanna do when we send the message. I'm gonna wait and go over that at the end after we go over the rest of the code in the view controller. So just hold off on that for a moment. So I have a storyboard, I have my UI, I have my code, I'm ready to go. What do I need to do? Well, if I wanted to go with real-time behavior today, I have to tell it where my socket is. And so this we're gonna use phoenix.socket to accomplish this. And I'm gonna say let socket equals phoenix.socket, tell it the domain import. Mine's running locally on 4,000. Tell it the path and tell it the transport. This doesn't actually join the socket. This is just to find the address of where our socket is. This is just what we're gonna use with Starscream to actually connect directly to the web socket here in just a moment. As you saw with our channel, and as you've seen, if you go to either Christmas or the phoenix chat example itself or the guides, I need a topic. And so in this case, we're gonna do Rooms Lobby because if the default state of my app should be that you can hop in and just start chatting with everybody. So now I have my socket, now I have my topic. Inside of this view controller, there's a function that comes, a boilerplate function that it comes with called viewDidLoad. Stick with me here. This is incredibly complex iOS development. This will run when the view did load. So the first thing that I wanna do, first thing that I wanna do is I wanna join the actual socket. So I'm gonna call socket.join. I'm gonna pass it the topic, Rooms Lobby in this case. I'm gonna use this phoenix.message class here to construct a message in the manner that phoenix is expecting, saying status and joining. And then the last element here that we're dealing with is a closure and thus I can use this closed Perrin curly bracket syntax. This passes in a channel and the first thing that I do is I'm gonna confirm that that channel mirrors up with my phoenix.channel implementation. If it doesn't, horrible things happen and it explodes. So the first thing that I wanna do once I've actually connected to the socket, I've landed in here, I had a channel. I want this to do something when I've joined this channel. So I'm gonna set that chat logs output to you've joined the room. Once I do this, we've now connected to the socket, landed in, confirmed that we have a channel that we're dealing with and said, you've joined the room and the chat log and the user's ready to chat. That's really the core behind what we're dealing with here. The next couple things are events that I wanna handle once I'm connected to that chat room. So the first thing that I wanna do, much like the channel example we saw with Handelina is I want some way to deal with a new message. So here I have channel.on new message. I'm gonna pass in a message. So here I have, the next thing that I'm gonna have is a guard clause. This guard clause works about like guard clauses would in any language. It guards some expression, some kind of data. And if that doesn't match what I want, I get the option to either manipulate the data or return and say, screw it. So I have a message, that message has a user and that message has a body. So if that's all true, what I wanna do is I wanna format that message. Here I'm just gonna use square bracket, username, body, new line. You'll see the next two lines a couple places. All this does is this takes whatever the value of that chat log is, appends the new message that we've just formatted and resets the value of that chat log to what we just created by string by appending string. From a user perspective, all that does is shove whatever message we're passing through to the bottom of the chat log. So that basically is how we're gonna handle running a new message. The next two events that I've got here are what I wanna do when a user's entered my room and what I wanna do when there's an error. So these both look very, very similar to new message. For the user entered, I'm gonna pass in a message. In this case, we're not actually pulling user names off of the server just for simplicity's sake, but you could absolutely do that here. We're just gonna go ahead and preset this to anonymous. And we're gonna go ahead and append that to our chat log so it'll say anonymous has entered the room mirroring what Phoenix Chat example is doing right now for us. The last thing that I want is if my connection breaks or something else terrible goes wrong. In this case, I wanna tell the user, hey, by the way, you're not connected anymore, something terrible has gone wrong. So if I get an error coming through here, I'm gonna guard that I have a message, that message has a body. And if that's true, I'm gonna make format a square bracket error, whatever the body is, followed by a new line. I'm gonna have these same two lines again that I'm just gonna append it to the bottom of our chat log so the user can know that something terrible has happened. The last thing that I'm gonna go over here is, like I said, I'm gonna go back up and we're gonna go over this send message clause. So by creating this action, I had to identify an event that it should trigger it. So in this case, I identified touch up inside, which means that send button was tapped kind of in a traditional behavior. So once that's tapped, I wanna execute this function. So I want to construct a message. I'm gonna use Phoenix.message to construct it, like I said, in a style that Phoenix is gonna expect and pass in the text of the username field and is the body, the text of the message field. I'm gonna take that message that I've constructed and I'm gonna pass it into Phoenix.payload to construct a payload for us to send along the socket. So I'm gonna pass the topic through there, like we said before, is Rooms Lobby, an event, new message, so our channel knows how to deal with this and what it should do with this and the message that I've just created in the line above. The last thing that I wanna do now that I have the payload constructed is actually send it along the socket and reset the message field text to empty, thus allowing the user to enter their next chat message. So let's see how this all works. As with everything, I have to wait for a moment for Xcode. All right, great, so we have anonymous entered over here. We have you've joined the room over there. Phoenix is currently sending off a system ping, which we're outputting that way we can see that both are currently getting the ping. This, after this point, is pretty sane. I can send a message here and receive it on all devices that are connected, including our Swift app. Likewise, I can send a message back. So I will readily admit that this is not WhatsApp, this isn't gonna make me a billion dollars, but with about 65 to 70 lines of code, I have a running real-time chat app connected to my Phoenix instance fairly quickly and fairly easily. The other nice thing about this is it is fairly reliable, fairly stable. You can actually send this app into background mode and send messages. Come back here, reopen your app. I proceed to continue getting the messages that I missed. Also, we'd implemented that error behavior. If I either go through the tunnel or something awful happens. Yeah, that has to do with the actual implementation of the iOS app itself. There's nothing that Swift Phoenix client is doing with that. Correct, no. Sorry, the question was when the app went into background mode and came back, is there any implementation required on our end to facilitate getting the data back from our app? And the answer is no, there's not. That actually has to do with the architecture that our iOS device has when a user, when an app enters background mode that it's still able to receive messages sent along this socket. So here we have a whole bunch of bad, bad error messages. I can re-go ahead and run run our Phoenix server again. This has gone ahead and decided to reconnect to the socket because it's available again. It's told me you've rejoined the room and I proceed to see my pings again. And I can receive messages as I did before. So, like I said, what seemed cool to me when I was playing with this, when I was implementing this, is with all of 67 lines of code, of not production code, in all of 67 lines of code, I have a real-time iOS chat app that's talking to my Phoenix chat app. So to sum up, Phoenix and Swift really are a match made in heaven. What does Phoenix give me? Phoenix gives me a framework that's real-time, fault-tolerant, fast, concurrent, stable, easy to learn, and easy to maintain. And that there's some amazing real-time possibilities when you look into the future of Phoenix and Swift together. I'm sure there's many more than just this, but a few examples that I thought of were gaming, such as multiplayer games, scoreboards, chat features. I know when I was playing this, when I was first creating this, about the same amount of code as I had on this chat app, I created a little dummy app called Rockets on iOS that is not available on the App Store. It was a terrible game, but it was fun to play with. And all it was was a space scene that allowed every device that connected to the socket to control a little rocket, and you could all fly around space controlling rockets. It was a terrible game because you could not shoot each other, you could not run into each other, you could not do anything other than fly around rockets in space. So that was cool, but what seemed cooler to me was I could connect to the Phoenix chat example. I used the same back end. And in the log, I could see all of the coordinate trajectories of all of the rockets that were connected to that game and all of the moves that all of the players were making on a makeshift web kind of admin dashboard that I was looking at. It was just the log of that Phoenix web chat. That's what really seemed cool to me that theoretically I could make a canvas game, I could do whatever I could think of and allow people to interact with a, see the actions from a running Swift game on my web browser. You can do stuff like in-app notifications, set up socket-based notifications with fallbacks, in our case, APNS, which is Apple's notification system. But I could create a socket system that my web users, my Android users, and my Swift users would all get a notification at the same time. Or live content reloading, things like comments, Trello, Basecamp, think of anything like that. I know we have a client with a pretty complex dashboard and a boatload of JSON that comes with it. Well, currently that JSON is being served up via socket connection onto a dashboard that's running a web app. Once that's completed, we already have plans to create a Swift client for them and I am already thrilled that I can do something similar to this, make the connection of the web socket and I will instantly have real-time dashboard data, dashboard JSON coming to me anytime that a change is received, that a change needs to happen to that dashboard and my Swift code is gonna be very, very small to do something seemingly complex. So there's more possibilities than just this. I think there's some amazing apps that you can create with Phoenix and Swift with some really amazing real-time interactions. If you'd like to learn more, I've posted all of this on speakerdeck at speakerdeck.com slash davidstump and after this, sometimes today or tomorrow I'll post all of this to ElixirConf. I'll have the Phoenix chat example I used just for posterity in case it changes. I have my Swift app and I have all of the code examples and my slides on GitHub as well if you'd prefer there. Lastly and sincerely, thank you. I'm ecstatic that I got to talk to you today. My hope, I told you the goal of my talk as a whole was to convince you that all this is great and you could build really cool apps with Phoenix and Swift. My personal goal, to be quite honest, is to enthuse people to learn more about what's possible with Phoenix, Swift and WebSockets and for somebody here or somebody later to come up with some awesome ways of doing things that are far beyond what I can come up with and what I know and I get to learn from all of you or somebody in the future. That would be mind-blowingly amazing for me. So lastly, like I said, have a fantastic rest of your conference. I know you're running short on time so if you have any questions or want to talk, please find me or if you just want to say hi, I would love that. So thank you very much and have a great rest of your conference.