Fast Websockets in Swift for iOS and OSX

Overview

 SwiftWebSocket

API Docs Swift/5.0 Build Status

Conforming WebSocket (RFC 6455) client library for iOS and Mac OSX.

SwiftWebSocket passes all 521 of the Autobahn's fuzzing tests, including strict UTF-8, and message compression.

Project Status

I'm looking for someone to help with or take over maintenance of this project.

Features

  • High performance.
  • 100% conforms to Autobahn Tests. Including base, limits, compression, etc. Test results.
  • TLS / WSS support. Self-signed certificate option.
  • The API is modeled after the Javascript API.
  • Reads compressed messages (permessage-deflate). RFC 7692
  • Send pings and receive pong events.
  • Strict UTF-8 processing.
  • binaryType property to choose between [UInt8] or NSData messages.
  • Zero asserts. All networking, stream, and protocol errors are routed through the error event.
  • iOS / Objective-C support.

Example

func echoTest(){
    var messageNum = 0
    let ws = WebSocket("wss://echo.websocket.org")
    let send : ()->() = {
        messageNum += 1
        let msg = "\(messageNum): \(NSDate().description)"
        print("send: \(msg)")
        ws.send(msg)
    }
    ws.event.open = {
        print("opened")
        send()
    }
    ws.event.close = { code, reason, clean in
        print("close")
    }
    ws.event.error = { error in
        print("error \(error)")
    }
    ws.event.message = { message in
        if let text = message as? String {
            print("recv: \(text)")
            if messageNum == 10 {
                ws.close()
            } else {
                send()
            }
        }
    }
}

Custom Headers

var request = URLRequest(url: URL(string:"ws://url")!)
request.addValue("AUTH_TOKEN", forHTTPHeaderField: "Authorization")
request.addValue("Value", forHTTPHeaderField: "X-Another-Header")
let ws = WebSocket(request: request)

Reuse and Delaying WebSocket Connections

v2.3.0+ makes available an optional open method. This will allow for a WebSocket object to be instantiated without an immediate connection to the server. It can also be used to reconnect to a server following the close event.

For example,

let ws = WebSocket()
ws.event.close = { _,_,_ in
    ws.open()                 // reopen the socket to the previous url
    ws.open("ws://otherurl")  // or, reopen the socket to a new url
}
ws.open("ws://url") // call with url

Compression

The compression flag may be used to request compressed messages from the server. If the server does not support or accept the request, then connection will continue as normal, but with uncompressed messages.

let ws = WebSocket("ws://url")
ws.compression.on = true

Self-signed SSL Certificate

let ws = WebSocket("ws://url")
ws.allowSelfSignedSSL = true

Network Services (VoIP, Video, Background, Voice)

// Allow socket to handle VoIP in the background.
ws.services = [.VoIP, .Background] 

Installation (iOS and OS X)

Carthage

Add the following to your Cartfile:

github "tidwall/SwiftWebSocket"

Then run carthage update.

Follow the current instructions in Carthage's README for up to date installation instructions.

The import SwiftWebSocket directive is required in order to access SwiftWebSocket features.

CocoaPods

Add the following to your Podfile:

use_frameworks!
pod 'SwiftWebSocket'

Then run pod install with CocoaPods 0.36 or newer.

The import SwiftWebSocket directive is required in order to access SwiftWebSocket features.

Manually

Copy the SwiftWebSocket/WebSocket.swift file into your project.
You must also add the libz.dylib library. Project -> Target -> Build Phases -> Link Binary With Libraries

There is no need for import SwiftWebSocket when manually installing.

Contact

Josh Baker @tidwall

License

SwiftWebSocket source code is available under the MIT License.

Comments
  • No websocket close event

    No websocket close event

    I am using the 1.2 branch and everything seems to work well except I do not receive an event when there is a server disconnection

    websocket.event.close = { (code, reason, clean) in println("web server socket close") }

    event.message, event.open are working.

    opened by zivelli 16
  • Swift 2.2 - Unknown attribute asmname

    Swift 2.2 - Unknown attribute asmname

    It seems that on Xcode 7.3b2 and the included Swift 2.2 beta version, the keyword @asmname has been removed so all those methods are generating errors and preventing the build.

    @asmname("zlibVersion") private func zlibVersion() -> COpaquePointer
    @asmname("deflateInit2_") private func deflateInit2(strm : UnsafeMutablePointer<Void>, level : CInt, method : CInt, windowBits : CInt, memLevel : CInt, strategy : CInt, version : COpaquePointer, stream_size : CInt) -> CInt
    @asmname("deflateInit_") private func deflateInit(strm : UnsafeMutablePointer<Void>, level : CInt, version : COpaquePointer, stream_size : CInt) -> CInt
    @asmname("deflateEnd") private func deflateEnd(strm : UnsafeMutablePointer<Void>) -> CInt
    @asmname("deflate") private func deflate(strm : UnsafeMutablePointer<Void>, flush : CInt) -> CInt
    @asmname("inflateInit2_") private func inflateInit2(strm : UnsafeMutablePointer<Void>, windowBits : CInt, version : COpaquePointer, stream_size : CInt) -> CInt
    @asmname("inflateInit_") private func inflateInit(strm : UnsafeMutablePointer<Void>, version : COpaquePointer, stream_size : CInt) -> CInt
    @asmname("inflate") private func inflateG(strm : UnsafeMutablePointer<Void>, flush : CInt) -> CInt
    @asmname("inflateEnd") private func inflateEndG(strm : UnsafeMutablePointer<Void>) -> CInt
    
    opened by macteo 15
  • Swift/3.0 fails to build?

    Swift/3.0 fails to build?

    I just tried using both Carthage and a manual zip download to build the swift/3.0 branch in Xcode 8b6. As soon as I invoke Build, I get this error:

    “Use Legacy Swift Language Version” (SWIFT_VERSION) is required to be configured correctly for targets which use Swift. Use the [Edit > Convert > To Current Swift Syntax…] menu to choose a Swift version or use the Build Settings editor to configure the build setting directly.

    I haven't tried to troubleshoot this at all, since it seems something's fundamentally wrong. Am I missing something? Thanks.

    opened by JetForMe 13
  • Abnormal Closure - code 1006

    Abnormal Closure - code 1006

    After a few minutes he closes the connection giving the error "Abnormal Closure" (code 1006), someone knows what can be? When I used socket rocket in objective-c worked

    opened by yvesroos 11
  • Carthage support: has bitcode disabled

    Carthage support: has bitcode disabled

    I can't build the framework with Carthage.

    Carthage version: 0.14.0 Cartfile: github "tidwall/SwiftWebSocket" ~> 2.5

    Partial log:

    /usr/bin/xcrun xcodebuild -project /Users/rp/Desktop/AblyExample/Carthage/Checkouts/SwiftWebSocket/SwiftWebSocket.xcodeproj -scheme SwiftWebSocket-tvOS -configuration Release -sdk appletvsimulator ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= clean buildBuild settings from command line:
        CODE_SIGN_IDENTITY =
        CODE_SIGNING_REQUIRED = NO
        ONLY_ACTIVE_ARCH = NO
        SDKROOT = appletvsimulator9.1
    
    === CLEAN TARGET SwiftWebSocket-tvOS OF PROJECT SwiftWebSocket WITH CONFIGURATION Release ===
    
    Check dependencies
    target 'SwiftWebSocket-tvOS' has bitcode disabled (ENABLE_BITCODE = NO), but it is required for the 'appletvos' platform
    
    === BUILD TARGET SwiftWebSocket-tvOS OF PROJECT SwiftWebSocket WITH CONFIGURATION Release ===
    
    Check dependencies
    target 'SwiftWebSocket-tvOS' has bitcode disabled (ENABLE_BITCODE = NO), but it is required for the 'appletvos' platform
    
    opened by ricardopereira 10
  • The operation couldn’t be completed. (SwiftWebSocket.WebSocketError error 4.)

    The operation couldn’t be completed. (SwiftWebSocket.WebSocketError error 4.)

    I am trying to connect to my loxone mini server via socket using your library with the following code.

               let websocketScheme = "ws"
                let host = "192.168.14.247"
                let port: NSNumber = 8888
                
                let components = NSURLComponents()
                components.scheme = websocketScheme
                components.host = host
                components.port = port
                components.path = "/"
                
                print("URL \(components.url)")
                
                var request = URLRequest(url: components.url!)
    
                request.setValue("Upgrade", forHTTPHeaderField: "WebSocket")
                request.setValue("Connection", forHTTPHeaderField: "Upgrade")
                request.setValue("Sec-WebSocket-Protocol", forHTTPHeaderField: hash as String)  
                
                socket = WebSocket(request: request as URLRequest)
                
                socket?.delegate = self
                socket?.open()
    
    

    but I am keep getting error

    The operation couldn’t be completed. (SwiftWebSocket.WebSocketError error 4.)

    what could be the issue? any directions/pointers please

    opened by qadirsuh 9
  • 2.6 Doesn't Build with Carthage

    2.6 Doesn't Build with Carthage

    GIves the laconic error message:

    ** BUILD FAILED **
    
    
    The following build commands failed:
        CompileSwift normal arm64 /Users/peter/Dropbox/Development/Programming/Swift/SwiftDDP/Carthage/Checkouts/SwiftWebSocket/Source/WebSocket.swift
        CompileSwiftSources normal arm64 com.apple.xcode.tools.swift.compiler
    (2 failures)
    A shell task failed with exit code 65:
    ** BUILD FAILED **
    
    
    The following build commands failed:
        CompileSwift normal arm64 /Users/peter/Dropbox/Development/Programming/Swift/SwiftDDP/Carthage/Checkouts/SwiftWebSocket/Source/WebSocket.swift
        CompileSwiftSources normal arm64 com.apple.xcode.tools.swift.compiler
    (2 failures)
    
    
    opened by siegesmund 9
  • Migrating to Swift 4

    Migrating to Swift 4

    key = trim(line.substring(to: r.lowerBound)) value = trim(line.substring(from: r.upperBound))

    'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range upto' operator.

    Any solutions for swift 4 version?

    opened by romanbaitaliuk 7
  • Cannot use my own origin for websocket

    Cannot use my own origin for websocket

    Hi @tidwall

    Thanks a lot for such a great library. But I have an issue.

    I want to use my own custom origin for connection request like this:

    let mutableRequest = NSMutableURLRequest(URL: "my socket url")
    mutableRequest.addValue("my value", forHTTPHeaderField: "cookie")
    mutableRequest.addValue("my value", forHTTPHeaderField: "origin")
    
    socket.open(request: mutableRequest)
    

    It's important for test purpose. We have dev and production servers.

    But as I can see in private InnerWebSocket class:

    req.setValue(req.URL!.absoluteString, forHTTPHeaderField: "Origin")

    you always use Origin from the request that I've provided to make a connection.

    So in that case we just can't organise our test environment. It would be great if you add some if statement for the Origin http field, if there is something that user provided, otherwise set Origin from the request url.

    Thanks a lot!

    bug 
    opened by maxsokolov 7
  • Crash when resuming app from background

    Crash when resuming app from background

    Hello I have a crash each time the user is on a socket related view and the App is on the background for a long time. When the App resumes it crashes. Any idea what causes this? I'm using Python for Backend with wss protocol.

    libsystem_kernel​.dylib   
    __psynch_cvwait
    1   WebSocket.swift ​Line ​1616
    (Manager in _A42D883B1EA5865CEB62599B0B6EDEEA).(init() -> (Manager in _A42D883B1EA5865CEB62599B0B6EDEEA)).(closure #1)
    
            let v1 = Int(tv.tv_usec * 1000)
            let v2 = Int(1000 * 1000 * Int(timeInMs % 1000))
            ts.tv_nsec = v1 + v2;
            ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
            ts.tv_nsec %= (1000 * 1000 * 1000);
            return pthread_cond_timedwait(&self.cond, &self.mutex, &ts)
        }
        func signal(){
            pthread_mutex_lock(&mutex)
            pthread_cond_signal(&cond)
            pthread_mutex_unlock(&mutex)
    
    2   libdispatch​.dylib    
    _dispatch_call_block_and_release
    3   libdispatch​.dylib    
    _dispatch_client_callout
    4   libdispatch​.dylib    
    _dispatch_queue_drain
    5   libdispatch​.dylib    
    _dispatch_queue_invoke
    6   libdispatch​.dylib    
    _dispatch_client_callout
    7   libdispatch​.dylib    
    _dispatch_root_queue_drain
    8   libdispatch​.dylib    
    _dispatch_worker_thread3
    9   libsystem_pthread​.dylib  
    _pthread_wqthread
    10  libsystem_pthread​.dylib  
    start_wqthread
    
    opened by netgfx 7
  • Can't get close code

    Can't get close code

    Hi there,

    Many thanks for writing such a great library!

    We were using the swift 1.2 version of your library and have recently updated to swift 2.1. I am using your swift 2.1 library but when our server sends a certain close code (4000-4016) your library seems to spit out 0. Is this normal?

    Any help would be greatly appreciated.

    Cheers, Gavin

    opened by GavinPacini 7
  • Initialization of 'UnsafePointer<UInt8>' results in a dangling pointer

    Initialization of 'UnsafePointer' results in a dangling pointer

    Line 440 of WebSocket.swift causes a warning in Xcode. The warning is "Initialization of 'UnsafePointer' results in a dangling pointer".

    strm.next_in = UnsafePointer(inflateEnd)

    It is just a warning, but it would be nice to update it with the preferred syntax to eliminate the warning.

    opened by tethridge 0
  • Data race

    Data race

    Number 1

    Screenshot 2021-04-19 at 19 23 47 Screenshot 2021-04-19 at 19 24 04
    WARNING: ThreadSanitizer: Swift access race (pid=97366)
      Modifying access of Swift variable at 0x7b2800038ce0 by thread T3:
        #0 closure #1 in Manager.init() <null>:2 (App:x86_64+0x10212d834)
        #1 partial apply for closure #1 in Manager.init() <null>:2 (App:x86_64+0x102131a8d)
        #2 thunk for @escaping @callee_guaranteed () -> () <null>:2 (App:x86_64+0x1000d8ea3)
        #3 __tsan::invoke_and_release_block(void*) <null>:2 (libclang_rt.tsan_iossim_dynamic.dylib:x86_64+0x70ebb)
        #4 _dispatch_client_callout <null>:2 (libdispatch.dylib:x86_64+0x39c7)
    
      Previous modifying access of Swift variable at 0x7b2800038ce0 by thread T13 (mutexes: write M2419):
        #0 Manager.nextId() <null>:2 (App:x86_64+0x10212fb11)
        #1 WebSocket.init(request:subProtocols:) <null>:2 (App:x86_64+0x102134676)
        #2 @objc WebSocket.init(request:subProtocols:) <null>:2 (App:x86_64+0x102135129)
        #3 WebSocket.init() <null>:2 (App:x86_64+0x102135613)
        #4 @objc WebSocket.init() <null>:2 (App:x86_64+0x1021356fb)
        #5 WebSocket.__allocating_init() <null>:2 (App:x86_64+0x1021351cd)
        #6 WebSocketFactoryImpl.makeWebSocket() <null>:2 (App:x86_64+0x101725335)
    

    Number 2

    Screenshot 2021-04-19 at 19 28 14 Screenshot 2021-04-19 at 19 28 36
    WARNING: ThreadSanitizer: Swift access race (pid=97366)
      Modifying access of Swift variable at 0x7b5400099498 by main thread:
        #0 InnerWebSocket.lock() <null>:2 (App:x86_64+0x1020ef405)
        #1 InnerWebSocket.privateReadyState.getter <null>:2 (App:x86_64+0x1020ea7ab)
        #2 InnerWebSocket.readyState.getter <null>:2 (App:x86_64+0x1020ea718)
        #3 WebSocket.readyState.getter <null>:2 (App:x86_64+0x102137137)
    
      Previous modifying access of Swift variable at 0x7b5400099498 by thread T3 (mutexes: write M50187, write M50210):
        #0 InnerWebSocket.unlock() <null>:2 (App:x86_64+0x1020ef4e5)
        #1 $defer #1 () in InnerWebSocket.dirty.getter <null>:2 (App:x86_64+0x1020f0f4d)
        #2 InnerWebSocket.dirty.getter <null>:2 (App:x86_64+0x1020f0eb6)
        #3 closure #1 in Manager.init() <null>:2 (App:x86_64+0x10212dbc4)
        #4 partial apply for closure #1 in Manager.init() <null>:2 (App:x86_64+0x102131a8d)
        #5 thunk for @escaping @callee_guaranteed () -> () <null>:2 (App:x86_64+0x1000d8ea3)
        #6 __tsan::invoke_and_release_block(void*) <null>:2 (libclang_rt.tsan_iossim_dynamic.dylib:x86_64+0x70ebb)
        #7 _dispatch_client_callout <null>:2 (libdispatch.dylib:x86_64+0x39c7)
    
    
    opened by Usipov 0
  • The

    The "Autobahn Test" link doesn't work...

    404 Not Found Code: NoSuchKey Message: The specified key does not exist. Key: autobahn/testsuite/index.html RequestId: EQCZ5J9BKBY99JK0 HostId: 9n8GSuSLe8xZd4YkoW17aTcSFOJCfcAR6ZlL8496Jt5a+ps6G3MY8Rdkp3vfPERW+rN1rFq16zo=

    opened by WilliamAllenTalia 0
  • Doesn't compile on Xcode 11.3.1

    Doesn't compile on Xcode 11.3.1

    Hey... My project stopped compiling with the following errors:

    Undefined symbol: _inflate Undefined symbol: _zlibVersion Undefined symbol: deflateInit2 Undefined symbol: _inflateEnd Undefined symbol: _deflateEnd Undefined symbol: inflateInit2

    Undefined symbols for architecture x86_64:
      "_inflate", referenced from:
          chatapp.(Inflater in _9BC240083F71E5BF5B19CC359CE4C292).inflate(_: Swift.UnsafePointer<Swift.UInt8>, length: Swift.Int, final: Swift.Bool) throws -> (p: Swift.UnsafeMutablePointer<Swift.UInt8>, n: Swift.Int) in WebSocket.o
      "_zlibVersion", referenced from:
          chatapp.(Inflater in _9BC240083F71E5BF5B19CC359CE4C292).init(windowBits: Swift.Int) -> chatapp.(Inflater in _9BC240083F71E5BF5B19CC359CE4C292)? in WebSocket.o
          chatapp.(Deflater in _9BC240083F71E5BF5B19CC359CE4C292).init(windowBits: Swift.Int, memLevel: Swift.Int) -> chatapp.(Deflater in _9BC240083F71E5BF5B19CC359CE4C292)? in WebSocket.o
      "_deflateInit2_", referenced from:
          chatapp.(Deflater in _9BC240083F71E5BF5B19CC359CE4C292).init(windowBits: Swift.Int, memLevel: Swift.Int) -> chatapp.(Deflater in _9BC240083F71E5BF5B19CC359CE4C292)? in WebSocket.o
      "_inflateEnd", referenced from:
          chatapp.(Inflater in _9BC240083F71E5BF5B19CC359CE4C292).deinit in WebSocket.o
      "_deflateEnd", referenced from:
          chatapp.(Deflater in _9BC240083F71E5BF5B19CC359CE4C292).deinit in WebSocket.o
      "_inflateInit2_", referenced from:
          chatapp.(Inflater in _9BC240083F71E5BF5B19CC359CE4C292).init(windowBits: Swift.Int) -> chatapp.(Inflater in _9BC240083F71E5BF5B19CC359CE4C292)? in WebSocket.o
    ld: symbol(s) not found for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    
    
    opened by kronik 2
  • Update SPM package description & SemVer tag for version

    Update SPM package description & SemVer tag for version

    Xcode 11 now supports Swift Package Manager, but so far it is not possible to add SwiftWebSocket to project via Xcode 11 SPM without proper repository version tag that follows Semantic Versioning (should be "2.8.0" without "v", but latest tag is "v2.8.0"). Pull request updates SPM package description for SwiftWebSocket.

    opened by T2SoftDev 1
Releases(2.6.0)
Owner
Josh
Josh
Reactive WebSockets

RxWebSocket Reactive extensions for websockets. A lightweight abstraction layer over Starscream to make it reactive. Installation RxWebSocket is avail

Flávio Caetano 57 Jul 22, 2022
Socket.io iOS and OSX Client compatible with v1.0 and later

SocketIO-Kit ⚠️ This project is no longer maintained. Please use the official framework Socket.IO-Client-Swift. SocketIO-Kit is a Socket.io iOS client

Ricardo Pereira 140 Mar 9, 2022
Easy-to-use ICMP Ping for iOS (and maybe OSX)

CDZPinger Easy-to-use ICMP ping for iOS - just create a CDZPinger and you delegate gets a callback every second with the average ping time. Installati

Chris Dzombak 48 Feb 2, 2022
Conforming WebSocket (RFC 6455) client library for iOS and Mac OSX

SwiftWebSocket Conforming WebSocket (RFC 6455) client library for iOS and Mac OS

null 0 Dec 24, 2021
A lightweight, one line setup, iOS / OSX network debugging library! 🦊

Netfox provides a quick look on all executed network requests performed by your iOS or OSX app. It grabs all requests - of course yours, requests from

Christos Kasketis 3.4k Dec 28, 2022
WKZombie is an iOS/OSX web-browser without a graphical user interface.

WKZombie is a Swift framework for iOS/OSX to navigate within websites and collect data without the need of User Interface or API, also known as Headless browser. It can be used to run automated tests / snapshots and manipulate websites using Javascript.

Mathias Köhnke 1.1k Dec 16, 2022
A minimal, fast and unopinionated web framework for Swift

![Fire Image] (http://i.imgur.com/1qR6Nl4.png) Blackfire An extremely fast Swift web framework ?? Getting Started If you're familiar with express.js t

Elliott Minns 908 Dec 2, 2022
A super fast & convenient object mapper tailored for your needs

A super fast & convenient object mapper tailored for your needs. Mapping objects to arrays or dictionaries can be a really cumbersome task, but those

Christoffer Winterkvist 246 Sep 9, 2022
Server-side Swift. The Perfect core toolset and framework for Swift Developers. (For mobile back-end development, website and API development, and more…)

Perfect: Server-Side Swift 简体中文 Perfect: Server-Side Swift Perfect is a complete and powerful toolbox, framework, and application server for Linux, iO

PerfectlySoft Inc. 13.9k Jan 6, 2023
Shawn Frank 2 Aug 31, 2022
Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux.

BlueSocket Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux. Prerequisites Swift Swift Open Source swift-5.1

Kitura 1.3k Dec 26, 2022
Approov Integration Examples 0 Jan 26, 2022
🌏 A zero-dependency networking solution for building modern and secure iOS, watchOS, macOS and tvOS applications.

A zero-dependency networking solution for building modern and secure iOS, watchOS, macOS and tvOS applications. ?? TermiNetwork was tested in a produc

Bill Panagiotopoulos 90 Dec 17, 2022
RestKit is a framework for consuming and modeling RESTful web resources on iOS and OS X

RestKit RestKit is a modern Objective-C framework for implementing RESTful web services clients on iOS and Mac OS X. It provides a powerful object map

The RestKit Project 10.2k Dec 29, 2022
Lightweight Networking and Parsing framework made for iOS, Mac, WatchOS and tvOS.

NetworkKit A lightweight iOS, Mac and Watch OS framework that makes networking and parsing super simple. Uses the open-sourced JSONHelper with functio

Alex Telek 30 Nov 19, 2022
Bonjour networking for discovery and connection between iOS, macOS and tvOS devices.

Merhaba Bonjour networking for discovery and connection between iOS, macOS and tvOS devices. Features Creating Service Start & Stop Service Stop Brows

Abdullah Selek 67 Dec 5, 2022
QwikHttp is a robust, yet lightweight and simple to use HTTP networking library for iOS, tvOS and watchOS

QwikHttp is a robust, yet lightweight and simple to use HTTP networking library. It allows you to customize every aspect of your http requests within a single line of code, using a Builder style syntax to keep your code super clean.

Logan Sease 2 Mar 20, 2022
OAuth2 framework for macOS and iOS, written in Swift.

OAuth2 OAuth2 frameworks for macOS, iOS and tvOS written in Swift 5.0. ⤵️ Installation ?? Usage ?? Sample macOS app (with data loader examples) ?? Tec

Pascal Pfiffner 1.1k Jan 8, 2023
SwiftSoup: Pure Swift HTML Parser, with best of DOM, CSS, and jquery (Supports Linux, iOS, Mac, tvOS, watchOS)

SwiftSoup is a pure Swift library, cross-platform (macOS, iOS, tvOS, watchOS and Linux!), for working with real-world HTML. It provides a very conveni

Nabil Chatbi 3.7k Dec 28, 2022