PageSourceSearch

https://socket.io/assets/js/eff5bc89.146b305c.js

js socket.io collected 2026-09-24 07:23:29 UTC 16,475 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunksample_website=self.webpackChunksample_website||[]).push([[314],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>m});var o=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function r(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,o,a=function(e,t){if(null==e)return{};var n,o,a={},i=Object.keys(e);for(o=0;o<i.length;o++)n=i[o],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o<i.length;o++)n=i[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=o.createContext({}),c=function(e){var t=o.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},d=function(e){var t=c(e.components);return o.createElement(s.Provider,{value:t},e.children)},h="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},p=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),h=c(n),p=a,m=h["".concat(s,".").concat(p)]||h[p]||u[p]||i;return n?o.createElement(m,r(r({ref:t},d),{},{components:n})):o.createElement(m,r({ref:t},d))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,r=new Array(i);r[0]=p;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[h]="string"==typeof e?e:a,r[1]=l;for(var c=2;c<i;c++)r[c]=n[c];return o.createElement.apply(null,r)}return o.createElement.apply(null,n)}p.displayName="MDXCreateElement"},5196:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var o=n(3117),a=(n(7294),n(3905));const i={title:"Socket.IO on iOS",slug:"/socket-io-on-ios/",authors:[{name:"Erik Little",title:"Maintainer of the iOS client",url:"https://twitter.com/nuclearace",image_url:"https://github.com/nuclearace.png"}],author_link:"https://twitter.com/nukeace"},r=void 0,l={permalink:"/blog/socket-io-on-ios/",editUrl:"https://github.com/socketio/socket.io-website/edit/main/blog/2015-03-09-ios.md",source:"@site/blog/2015-03-09-ios.md",title:"Socket.IO on iOS",description:"We are pleased to announce the immediate availability of the Socket.IO Swift Client! Youll now be able to write code that runs natively on iOS and OSX, while maintaining the simplicity and expressiveness of the JavaScript client!",date:"2015-03-09T00:00:00.000Z",formattedDate:"March 9, 2015",tags:[],readingTime:7,hasTruncateMarker:!0,authors:[{name:"Erik Little",title:"Maintainer of the iOS client",url:"https://twitter.com/nuclearace",image_url:"https://github.com/nuclearace.png",imageURL:"https://github.com/nuclearace.png"}],frontMatter:{title:"Socket.IO on iOS",slug:"/socket-io-on-ios/",authors:[{name:"Erik Little",title:"Maintainer of the iOS client",url:"https://twitter.com/nuclearace",image_url:"https://github.com/nuclearace.png",imageURL:"https://github.com/nuclearace.png"}],author_link:"https://twitter.com/nukeace"},prevItem:{title:"Socket.IO C++",permalink:"/blog/socket-io-cpp/"},nextItem:{title:"Socket.IO 1.3.5",permalink:"/blog/socket-io-1-3-5/"}},s={authorsImageUrls:[void 0]},c=[{value:"Overview",id:"overview",level:2},{value:"Introduction",id:"introduction",level:2},{value:"Setting up the Project",id:"setting-up-the-project",level:2},{value:"Adding Our Code",id:"adding-our-code",level:3},{value:"Handlers",id:"handlers",level:3},{value:"Emitting Events",id:"emitting-events",level:3},{value:"Sending JSON",id:"sending-json",level:3},{value:"Sending Binary",id:"sending-binary",level:3},{value:"Requesting Acks",id:"requesting-acks",level:3},{value:"A Note About Multitasking in iOS",id:"a-note-about-multitasking-in-ios",level:3}],d={toc:c},h="wrapper";
1function u(e){let{components:t,...n}=e;return(0,a.kt)(h,(0,o.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("video",{className:"gfyVidIframe",id:"gfyVid",autoPlay:"",loop:"",height:"574",width:"323"},(0,a.kt)("source",{id:"webmsource",src:"//fat.gfycat.com/EssentialBlueElectriceel.webm",type:"video/webm"}),(0,a.kt)("source",{id:"mp4source",src:"//giant.gfycat.com/EssentialBlueElectriceel.mp4",type:"video/mp4"})),(0,a.kt)("p",null,"We are pleased to announce the immediate availability of the ",(0,a.kt)("a",{href:"https://github.com/socketio/socket.io-client-swift"},"Socket.IO Swift Client"),"! Youll now be able to write code that runs natively on ",(0,a.kt)("strong",{parentName:"p"},"iOS")," and ",(0,a.kt)("strong",{parentName:"p"},"OSX"),", while maintaining the simplicity and expressiveness of the JavaScript client!"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"},'import Foundation\nlet socket = SocketIOClient(socketURL: "localhost:8880")\nsocket.on("important message") {data, ack in\n    println("Message for you! \\(data?[0])")\n    ack?("I got your message, and I\'ll send my response")\n    socket.emit("response", "Hello!")\n}\nsocket.connect()\n')),(0,a.kt)("p",null,"To show how you can use it in a real project, Ill show you how to create a small Tic Tac Toe app like the one shown above."),(0,a.kt)("h2",{id:"overview"},"Overview"),(0,a.kt)("p",null,"In this tutorial well look at creating a small iOS app that demonstrates socket.io and iOS. If you learn better from looking at code you can look at it ",(0,a.kt)("a",{href:"https://github.com/nuclearace/socket.io-client-swift-example"},"here"),". The point of the tutorial is not to explain developing an iOS app, but to demonstrate how you can incorporate ",(0,a.kt)("inlineCode",{parentName:"p"},"socket.io-client-swift")," into your projects! So it is assumed you have a basic knowledge of XCode.\nNote: This example uses Swift 1.2. However, 1.2 isnt much different from Swift 1.1, and the library has branches for Swift 1.1 and 1.2. The only difference in this guide is I use 1.2s expanded ",(0,a.kt)("inlineCode",{parentName:"p"},"if let")," construct to avoid nesting.\nNote 2: While this library is written in, and meant for, Swift applications, it can be used with Objective-C projects, but will require some extra work (youll probably need to create a Swift class that can interface with your Objective-C code, as not all methods in the client will be available to Objective-C i.e emit, onAny). See ",(0,a.kt)("a",{href:"https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//apple_ref/doc/uid/TP40014216-CH10-XID_87"},"this")," for more information."),(0,a.kt)("h2",{id:"introduction"},"Introduction"),(0,a.kt)("p",null,"I designed ",(0,a.kt)("inlineCode",{parentName:"p"},"socket.io-client-swift")," to be as close to ",(0,a.kt)("inlineCode",{parentName:"p"},"socket.io-client")," as I could. So many of the ways you do things in socket.io-client look similar here! This is not a step-by-step tutorial for making a Tic Tac Toe app, only adding the socket.io-client part of it."),(0,a.kt)("h2",{id:"setting-up-the-project"},"Setting up the Project"),(0,a.kt)("p",null,"From Xcode, create a new project with the layout of single-view iOS application. You can name it whatever you like, Ill be naming mine ",(0,a.kt)("inlineCode",{parentName:"p"},"TicTacIOiOS"),".\nThe next step is getting the code for ",(0,a.kt)("inlineCode",{parentName:"p"},"socket.io-client-swift"),", you can either use ",(0,a.kt)("inlineCode",{parentName:"p"},"git")," to clone the repo to a directory, or simply download a ",(0,a.kt)("a",{href:"https://github.com/socketio/socket.io-client-swift/releases"},"release"),". Either way you get it, the process of adding it to your project is the same. Simply drag the folder named SwiftIO to the same place you copied SocketRocket! (Again making sure you select copy.)\nAnd thats it, the hardest part of putting our app together is done! At this point, if you want to test that its setup properly, try building and running the app, it should compile."),(0,a.kt)("h3",{id:"adding-our-code"},"Adding Our Code"),(0,a.kt)("p",null,"Now, assuming youve created your user interface. Its time to add the code that will interface with our socket.io server!\nIn our demo application we have one UIViewController subclass, named ViewController. All of our code will be added there. First, we need to add a member named ",(0,a.kt)("inlineCode",{parentName:"p"},"socket")," of type ",(0,a.kt)("inlineCode",{parentName:"p"},"SocketIOClient")," to our ViewController."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"},'let socket = SocketIOClient(socketURL: "localhost:8900")\n')),(0,a.kt)("p",null,"Now, in our overridden ",(0,a.kt)("inlineCode",{parentName:"p"},"viewDidLoad")," method we want to add two things, a method call that will add our handlers to our socket, and a call to connect our socket."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"},"self.addHandlers()\nself.socket.connect()\n")),(0,a.kt)("h3",{id:"handlers"},"Handlers"),(0,a.kt)("p",null,"Now that we have our method calls, its time to implement the method that adds the handlers!"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"},"func addHandlers() {\n    // Our socket handlers go here\n}\n")),(0,a.kt)("p",null,"Since were about to add the handlers, I think its worth mentioning the syntax I use for closures in Swift. Swift has many different ways of expressing closures, and they can be found ",(0,a.kt)("a",{href:"https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html"},"here"),". But the form I use for adding handlers is a trailing closure, without explicit type annotations. You can use other closure forms if you wish.\nIm not going to show you all the handlers in our demo app here, just a few that demonstrate important things youll need to know when working with ",(0,a.kt)("inlineCode",{parentName:"p"},"socket.io-client-swift"),".\nThe first handler were going to add is one that will be called on any event, since its useful for debugging the API."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"},'// Using a shorthand parameter name for closures\nself.socket.onAny {println("Got event: \\($0.event), with items: \\($0.items)")}\n')),(0,a.kt)("p",null,"The next handler that well add is the one that tells the app that the game has started."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"},'self.socket.on("startGame") {[weak self] data, ack in\n    self?.handleStart()\n    return\n}\n')),(0,a.kt)("p",null,"Now to explain some things. ",(0,a.kt)("inlineCode",{parentName:"p"},"[weak self]")," is a capture list. It tells the compiler that the reference to self in this closure should not add to the reference count of self. This is so when the socket object goes out of scope, the capture made in the closure doesnt keep it from being deallocated. The first parameter in all ",(0,a.kt)("inlineCode",{parentName:"p"},".on")," callbacks is an optional NSArray, it will contain all the data received with the event, or nil. The second parameter in the callback is an optional with the type of AckEmitter. AckEmitter is simply a typealias of ",(0,a.kt)("inlineCode",{parentName:"p"},"(AnyObject...) -&gt; Void"),". Well see this used later.\nThe next handler well add is the one for a win."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"},'self.socket.on("win") {[weak self] data, ack in\n    if let name = data?[0] as? String, typeDict = data?[1] as? NSDictionary {\n        self?.handleWin(name, type: typeDict)\n    }\n}\n')),(0,a.kt)("p",null,"As mentioned before, this is new syntax for ",(0,a.kt)("inlineCode",{parentName:"p"},"if let")," introduced in Swift 1.2. It simplifies optional unwrapping (pyramid of doom). The important thing to gather from this handler is that you do not need to force unwrap the array to get the object. Also note that a JSON object will be exposed to Swift as an NSDictionary.\nAnother thing to note is that for almost all your handlers that have data, youll be doing some kind of optional unwrapping and type casting. This is an unfortunate consequence of working with JavaScript.\nThe final handler that Ill demonstrate here is the one that handles whether the player wants to play again."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"},'self.socket.on("gameReset") {data, ack in\n    ack?(false)\n}\n')),(0,a.kt)("p",null,"In this simplified example, we simply send an acknowledgement to the server that we dont ever want to play again. Remember that AckEmitter has a variadic definition, so you can send multiple things at once if you wanted."),(0,a.kt)("h3",{id:"emitting-events"},"Emitting Events"),(0,a.kt)("p",null,"The next thing you'll probably want to know is how to send events from the client. Youll be pleased to know that it has a form almost exactly the same as socket.io-client!\nIn our ViewController we have a method that handles when a user wants to make a move. Without going into the logic of that, well show how we send the data to the server."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"}
1,'@IBAction func btnClicked(btn:UIButton) {\n    let coord:(x:Int, y:Int)\n\n    // Long switch statement that determines what coord should be\n\n    self.socket.emit("playerMove", coord.x, coord.y)\n}\n')),(0,a.kt)("p",null,"Thats all you need to do for sending data!\nSome other examples of sending which arent covered in our demo are:"),(0,a.kt)("h3",{id:"sending-json"},"Sending JSON"),(0,a.kt)("p",null,"As mentioned before, JSON in Swift is best represent as a Dictionary. Thankfully for you, you dont need to worry about turning it into something socket.io will understand, thats all done under-the-hood."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"},'let myJSON = [\n    "name": "bob"\n]\n\nsocket.emit("jsonTest", myJSON)\n')),(0,a.kt)("h3",{id:"sending-binary"},"Sending Binary"),(0,a.kt)("p",null,"Binary data is also handled by the client, so you dont need to worry about it."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"},'let data = "Hello, ".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!\nlet data2 = "World".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!\n\nsocket.emit("dataTest", data, ["world": data2])\n')),(0,a.kt)("h3",{id:"requesting-acks"},"Requesting Acks"),(0,a.kt)("p",null,"The client can also request that the server send an ack for an event. This is done by using the ",(0,a.kt)("inlineCode",{parentName:"p"},"emitWithAck")," method which returns an object to which you can add a handler."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-swift"},'socket.emitWithAck("needsAck", "test").onAck {data in\n    println("got ack with data: (data)")\n}\n')),(0,a.kt)("h3",{id:"a-note-about-multitasking-in-ios"},"A Note About Multitasking in iOS"),(0,a.kt)("p",null,"As you probably know, iOS is very picky about what you can do in the background. As such, dont expect that your socket connection will survive in the background! Youll probably stop receiving events within seconds of the app going into the background. So its better to create a task that will gracefully close the connection when it enters the background (via AppDelegate), and then reconnect the socket when the app comes back into the foreground.\nIf you want to learn more about the client, check out the ",(0,a.kt)("a",{href:"https://github.com/socketio/socket.io-client-swift/blob/master/README.md"},"README"),"! We also invite you to contribute by submitting issues, patches, documentation and examples."))}u.isMDXComponent=!0}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.