A Swift client for Supabase

Overview

supabase-swift

Supabase client for swift. Mirrors the design of supabase-js

Installation

Swift Package Manager:

Add the following lines to your Package.swift file:

let package = Package(
    ...
    dependencies: [
        ...
        .package(name: "Supabase", url: "https://github.com/supabase/supabase-swift.git", .branch("master")), // Add the package
    ],
    targets: [
        .target(
            name: "YourTargetName",
            dependencies: ["Supabase"] // Add as a dependency
        )
    ]
)

If you're using Xcode, use this guide to add supabase-swift to your project. Use https://github.com/supabase/supabase-swift.git for the url when Xcode asks.

Usage

For all requests made for supabase, you will need to initialize a SupabaseClient object.

let client = SupabaseClient(supabaseUrl: "{ Supabase URL }", supabaseKey: "{ Supabase anonymous Key }")

This client object will be used for all the following examples.

Database

Query todo table for all completed todos.

struct Todo: Codable {
    var id: String = UUID().uuidString
    var label: String
    var isDone: Bool = false
}
let query = try client.database.from("todos")
    .select()
    .eq(column: "isDone", value: "true")
                                
query.execute { [weak self] results in
    guard let self = self else { return }

    switch results {
    case let .success(response):
        let todos = try? response.decoded(to: [Todo].self)
        print(todos)
    case let .failure(error):
        print(error.localizedDescription)
    }
}

Insert a todo into the database.

let todo = Todo(label: "Example todo!")

let jsonData: Data = try JSONEncoder().encode(todo)
let jsonDict: [String: Any] = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments))

client.database.from("todos")    
    .insert(values: jsonDict)
    .execute { results in
        // Handle response
    }

For more query examples visit the Javascript docs to learn more. The API design is a near 1:1 match.

Execute an RPC

do {
    try client.database.rpc(fn: "testFunction", parameters: nil).execute { result in
        // Handle result
    }
} catch {
   print("Error executing the RPC: \(error)")
}

Realtime

Realtime docs coming soon

Auth

Auth docs coming soon

Storage

Storage docs coming soon

Contributing

  • Fork the repo on GitHub
  • Clone the project to your own machine
  • Commit changes to your own branch
  • Push your work back up to your fork
  • Submit a Pull request so that we can review your changes and merge

Sponsors

We are building the features of Firebase using enterprise-grade, open source products. We support existing communities wherever possible, and if the products don’t exist we build them and open source them ourselves. Thanks to these sponsors who are making the OSS ecosystem better for everyone.

New Sponsor

Comments
  • Realtime subscriptions don't work

    Realtime subscriptions don't work

    Socket is connected, channel is seemingly subscribed (it fires on "receive 'ok'")

    It never fires on ".all" or any other events

    Only when I unsubscribe "onClose" actually fires ("onError" never fires)

    Replication is enabled on all tables, it doesn't work even on non-RLS tables

    In API and Postgres logs I could only see "websocket" connections, didn't see any "subscription" logs if there are supposed to be any

    @grsouza please help

    I'm setting it up like Realtime Swift docs say

    opened by ooolzhas 7
  • Clarification on signed in row level security access via jwt

    Clarification on signed in row level security access via jwt

    Improve documentation

    let client = SupabaseClient(supabaseURL: SUPABASE_URL, supabaseKey: ANON_KEY)

    Describe the problem

    how can a signed in user access database with row level security? is there a way to switch in the jwt once we have it - eg. client.updateJWT( supabaseKey: authorisedJWT);

    I'm working on a sign in with apple / nodejs - native login flow - but once I have the jwt - how can I then proceed to use it.... https://github.com/johndpope/Sign-in-with-Apple-for-supabase

    documentation 
    opened by johndpope 6
  • [tvOS] Allow setting auth tokens manually

    [tvOS] Allow setting auth tokens manually

    We are developing a digital signage app for Apple TV (tvOS) and are considering to use Supabase as our backend service. While creating a proof of concept I stumbled upon a problem with authenticating. Since there is no web browser on tvOS the traditional auth flow won't work.

    Instead the user needs to sign in on another device and we need to set auth tokens manually on the SupabaseClient instance in our tvOS app. E.g. there might be a companion sign-in app on iOS that transfers auth tokens securely over to the tvOS app.
    But as of now there is no way to set auth tokens manually on the client itself.

    In supabase-js we have a method called setAuth() that lets you override the access token. Since the app basically does not have any user interaction at all, we also need to set the refresh token in order to stay authenticated while the app shows its content.

    opened by florivdg 6
  • can't seem to fetch rows.

    can't seem to fetch rows.

    Bug report

    I have this a test org and it's returning results fine using python https://gist.github.com/johndpope/4bdf87792c034fadb157766c702253d0

    Describe the bug

    When running same query I get no results in swift version.

    Screenshot 2022-11-18 at 7 43 44 am
    
    result: Optional(PostgREST.PostgrestResponse<()>(underlyingResponse: Get.Response<()>(value: (), response: <NSHTTPURLResponse: 0x600001263020> { URL: https://qfwzdkpmyzajmmvupgzy.supabase.co/rest/v1/tweets?select=* } { Status Code: 200, Headers {
        "Access-Control-Allow-Origin" =     (
            "*"
        );
        "Alt-Svc" =     (
            "h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400"
        );
        "Content-Encoding" =     (
            br
        );
        "Content-Location" =     (
            "/tweets?select=%2A"
        );
        "Content-Type" =     (
            "application/json; charset=utf-8"
        );
        Date =     (
            "Thu, 17 Nov 2022 20:43:22 GMT"
        );
        Server =     (
            cloudflare
        );
        Vary =     (
            "Accept-Encoding"
        );
        Via =     (
            "kong/2.8.1"
        );
        "cf-cache-status" =     (
            DYNAMIC
        );
        "cf-ray" =     (
            "76bb4c4babd6a97a-SYD"
        );
        "content-profile" =     (
            public
        );
        "content-range" =     (
            "0-999/*"
        );
        "sb-gateway-version" =     (
            1
        );
        "x-kong-proxy-latency" =     (
            0
        );
        "x-kong-upstream-latency" =     (
            15
        );
    } }, data: 422860 bytes, task: LocalDataTask <47B6B060-DF8F-4921-AE38-CF831D362865>.<1>, metrics: Optional((Task Interval) <_NSConcreteDateInterval: 0x60000125f3e0> (Start Date) 2022-11-17 20:43:20 +0000 + (Duration) 2.450190 seconds = (End Date) 2022-11-17 20:43:22 +0000
    (Redirect Count) 0
    (Transaction Metrics) (Request) <NSMutableURLRequest: 0x60000101c320> { URL: https://qfwzdkpmyzajmmvupgzy.supabase.co/rest/v1/tweets?select=* }
    (Response) <NSHTTPURLResponse: 0x600001262240> { URL: https://qfwzdkpmyzajmmvupgzy.supabase.co/rest/v1/tweets?select=* } { Status Code: 200, Headers {
        "Access-Control-Allow-Origin" =     (
            "*"
        );
        "Alt-Svc" =     (
            "h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400"
        );
        "Content-Encoding" =     (
            br
        );
        "Content-Location" =     (
            "/tweets?select=%2A"
        );
        "Content-Type" =     (
            "application/json; charset=utf-8"
        );
        Date =     (
            "Thu, 17 Nov 2022 20:27:54 GMT"
        );
        Server =     (
            cloudflare
        );
        Vary =     (
            "Accept-Encoding"
        );
        Via =     (
            "kong/2.8.1"
        );
        "cf-cache-status" =     (
            DYNAMIC
        );
        "cf-ray" =     (
            "76bb35a7adf3a974-SYD"
        );
        "content-profile" =     (
            public
        );
        "content-range" =     (
            "0-999/*"
        );
        "sb-gateway-version" =     (
            1
        );
        "x-kong-proxy-latency" =     (
            1
        );
        "x-kong-upstream-latency" =     (
            15
        );
    } }
    (Fetch Start) 2022-11-17 20:43:20 +0000
    (Domain Lookup Start) (null)
    (Domain Lookup End) (null)
    (Connect Start) (null)
    (Secure Connection Start) (null)
    (Secure Connection End) (null)
    (Connect End) (null)
    (Request Start) 2022-11-17 20:43:20 +0000
    (Request End) 2022-11-17 20:43:20 +0000
    (Response Start) 2022-11-17 20:43:20 +0000
    (Response End) 2022-11-17 20:43:20 +0000
    (Protocol Name) (null)
    (Proxy Connection) NO
    (Reused Connection) NO
    (Fetch Type) Local Cache
    (Request Header Bytes) 0
    (Request Body Transfer Bytes) 0
    (Request Body Bytes) 0
    (Response Header Bytes) 0
    (Response Body Transfer Bytes) 0
    (Response Body Bytes) 0
    (Local Address) (null)
    (Local Port) (null)
    (Remote Address) (null)
    (Remote Port) (null)
    (TLS Protocol Version) 0x0000
    (TLS Cipher Suite) 0x0000
    (Cellular) NO
    (Expensive) NO
    (Constrained) NO
    (Multipath) NO
    
    (Request) <NSURLRequest: 0x60000101caf0> { URL: https://qfwzdkpmyzajmmvupgzy.supabase.co/rest/v1/tweets?select=* }
    (Response) <NSHTTPURLResponse: 0x60000124e260> { URL: https://qfwzdkpmyzajmmvupgzy.supabase.co/rest/v1/tweets?select=* } { Status Code: 200, Headers {
        "Access-Control-Allow-Origin" =     (
            "*"
        );
        "Alt-Svc" =     (
            "h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400"
        );
        "Content-Encoding" =     (
            br
        );
        "Content-Location" =     (
            "/tweets?select=%2A"
        );
        "Content-Type" =     (
            "application/json; charset=utf-8"
        );
        Date =     (
            "Thu, 17 Nov 2022 20:43:22 GMT"
        );
        Server =     (
            cloudflare
        );
        Vary =     (
            "Accept-Encoding"
        );
        Via =     (
            "kong/2.8.1"
        );
        "cf-cache-status" =     (
            DYNAMIC
        );
        "cf-ray" =     (
            "76bb4c4babd6a97a-SYD"
        );
        "content-profile" =     (
            public
        );
        "content-range" =     (
            "0-999/*"
        );
        "sb-gateway-version" =     (
            1
        );
        "x-kong-proxy-latency" =     (
            0
        );
        "x-kong-upstream-latency" =     (
            15
        );
    } }
    (Fetch Start) 2022-11-17 20:43:20 +0000
    (Domain Lookup Start) 2022-11-17 20:43:20 +0000
    (Domain Lookup End) 2022-11-17 20:43:20 +0000
    (Connect Start) 2022-11-17 20:43:20 +0000
    (Secure Connection Start) 2022-11-17 20:43:20 +0000
    (Secure Connection End) 2022-11-17 20:43:20 +0000
    (Connect End) 2022-11-17 20:43:20 +0000
    (Request Start) 2022-11-17 20:43:20 +0000
    (Request End) 2022-11-17 20:43:20 +0000
    (Response Start) 2022-11-17 20:43:22 +0000
    (Response End) 2022-11-17 20:43:22 +0000
    (Protocol Name) h3
    (Proxy Connection) NO
    (Reused Connection) NO
    (Fetch Type) Network Load
    (Request Header Bytes) 998
    (Request Body Transfer Bytes) 0
    (Request Body Bytes) 0
    (Response Header Bytes) 295
    (Response Body Transfer Bytes) 110951
    (Response Body Bytes) 422860
    (Local Address) 192.168.1.100
    (Local Port) 62732
    (Remote Address) 104.18.26.135
    (Remote Port) 443
    (TLS Protocol Version) 0x0304
    (TLS Cipher Suite) 0x1301
    (Cellular) NO
    (Expensive) NO
    (Constrained) NO
    (Multipath) NO
    
    )), count: nil))
    

    To Reproduce

    
        override func viewDidLoad() {
            super.viewDidLoad()
            setupDatabase()
        }
        
        func setupDatabase() {
            let SUPABASE_URL = URL(string:"https://qfwzdkpmyzajmmvupgzy.supabase.co")!
            let ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InFmd3pka3BteXpham1tdnVwZ3p5Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2NjgxMzAzMjYsImV4cCI6MTk4MzcwNjMyNn0.kEweOMrRSJ0mtOIXnsRmbNxf4yqoZAZf398jlGgSxtQ"
            self.client = SupabaseClient(supabaseURL: SUPABASE_URL, supabaseKey: ANON_KEY)
            Task {
                await fetchRows();
            }
        }
        
    
        func fetchRows() async  {
            
            let result = try? await self.client?.database.from("tweets").select(columns: "*").execute();
            print("result:",result.debugDescription);
        }
    
    

    Steps to reproduce the behavior, please provide code snippets or a repository: I'm on release-candidate branch

    Expected behavior

    running python version - I get results back Screenshot 2022-11-18 at 7 45 15 am

    but on ios - I get results = nil

    Screenshots

    If applicable, add screenshots to help explain your problem.

    System information

    • OS: macos - ventura
    • Version of Node.js: swift release candidate branch 0.0.9

    Additional context

    I've successfully used and got data from superbase in another project - not sure what's going on here. maybe to do with async stuff?

    bug 
    opened by johndpope 5
  • Crashing On Query Execution

    Crashing On Query Execution

    MacOS: Monterey (12.2.2) XCode Version 13.3 (13E113)

    I seem to be having an issue getting this to work correctly. Trying to execute a query crashes as soon it begins. Although it could be a problem with my code as I'm fairly new to swift.

    My Environment variables are correct as I stepped through them before crash

    
    import SwiftUI
    import Supabase
    
    struct ContentView: View {
        @StateObject private var model = ContentViewModel()
        
    
        var body: some View {
            VStack {
                List(model.lessons) { lesson in
                            Text("\(lesson.title): \(lesson.description)")
                        }
            }
            .onAppear {
               model.getLessons()
            }
        }
    }
    
    class ContentViewModel: ObservableObject {
        @Published var lessons: [Lesson] = []    
        let supabaseUrl = URL(string: ProcessInfo.processInfo.environment["SUPABASE_URL"]!)
        let supabaseKey = ProcessInfo.processInfo.environment["SUPABASE_KEY"]!
        
        lazy var client = SupabaseClient(supabaseURL: supabaseUrl!,supabaseKey: supabaseKey)
        
    
        
        // Retrieve all lessons
        func getLessons() {
            print("Retrieving all todo's from database")
            
            let query = client.database.from("lessons")
                .select()
            
            query.execute { results in
                switch results {
                    case let .success(response):
                        let lessons = try? response.decoded(to: [Lesson].self)
                        self.lessons = lessons!
                    case let .failure(error):
                        print(error.localizedDescription)
                }
            }
            
        }
    
    }
    
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
    opened by DimitriMichel 5
  • consider supporting xcframworks

    consider supporting xcframworks

    had some success spitting this out

    https://github.com/mstfy/spm-to-xcframework

    /Users/johndpope/Desktop/spm-to-xcframework/.build/arm64-apple-macosx/release/spm-to-xcframework Sup abase --path /Users/johndpope/Desktop/supabase-swift --output /Users/johndpope/Desktop/xcframework

    Screen Shot 2022-08-31 at 11 23 17 am

    it's helpful for bazel builds

    opened by johndpope 4
  • URLSessionTransport is only available in iOS 13 or newer, but not constrained to that in RealtimeClient

    URLSessionTransport is only available in iOS 13 or newer, but not constrained to that in RealtimeClient

    Bug report

    Describe the bug

    URLSessionTransport is only available in iOS 13 or newer, but not constrained to that in RealtimeClient What I find interesting is that the version constraint is commented out. Is this by accident?

    Screenshots

    image

    System information

    • OS: macOS
    • Xcode 12
    • Version of supabase-swift: none, this package is based off a branch, not versions
    bug 
    opened by chFlorian 4
  • Auto-refreshing JWT randomly expires in 0.0.8

    Auto-refreshing JWT randomly expires in 0.0.8

    Auto-refresh now works, but only half the time

    It occasionally throws a PGRST301 error on query execution (401 on Supabase)

    Retrying the query multiple times fixes this, but I don't think it's a good solution long-term

    Maybe it issues a new token on query but passes only on the next one?

    opened by ooolzhas 3
  • Add PostgrestFilterBuilderSemantics

    Add PostgrestFilterBuilderSemantics

    Issue

    Issue Link

    What kind of change does this PR introduce?

    This PR introduces semantics updates for PostgrestFilterBuilder

    What is the current behavior?

    phfts(column: column, query: query, config: config)
    

    What is the new behavior?

    phrasetoFullTextSearch(column: String, query: String, config: String? = nil)
    

    Additional context

    The idea is to improve semantics by providing descriptive function names. These are implemented as an extension to PostgrestFilterBuilder, which allows to keep the existing function names (aka the mirrors of the JS library).

    opened by chFlorian 3
  • Fixed buid errors - #52

    Fixed buid errors - #52

    What kind of change does this PR introduce?

    Fixes build errors mentioned in issue #52 by:

    • Updating Package file
    • Updating SupabaseClient.swift

    What is the current behavior?

    Fails to build due to breaking changes in postgrest-swift

    What is the new behavior?

    Now builds and runs as expected

    Additional context

    Glad to help!

    opened by glowcap 2
  • Fails to build due to PostgREST master branch dependency

    Fails to build due to PostgREST master branch dependency

    Bug report

    Describe the bug

    Build attempts fail due to changes in PostgREST master branch

    • FunctionsClient init change
    • PostgrestClient init change
    • FunctionsHTTPClient removal
    • PostgrestHTTPClient removal

    To Reproduce

    1. Create new project (or have existing project)
    2. Add supabase-swift SPM dependency as described in README
    3. Attempt to build the project
    4. See errors in SupabaseClient.swift

    Expected behavior

    Should build without issue

    Screenshots

    Screenshot 2023-01-02 at 1 00 27 PM

    Additional context

    Switching to the Release Candidate #45 most recent commit solves the issue (albeit not ideal)

    .package(name: "Supabase", url: "https://github.com/supabase/supabase-swift.git", branch: "release-candidate")

    It seems like shifting the master branch to tagged dependencies from here on would avoid issues like these popping up

    bug 
    opened by glowcap 2
  • OAuth Login with Auth Provider Example

    OAuth Login with Auth Provider Example

    Feature request

    I see in the gotrue RC pr the Google OAuth example was removed - https://github.com/supabase-community/gotrue-swift/pull/37/files#diff-5040cbf573fdc1b4fc2384e97402e4a832b40b22e33b3ff33fd0568db8e35ab1

    This was referenced in a few issues - https://github.com/supabase-community/supabase-swift/issues/39#issuecomment-1237818305 https://github.com/supabase-community/supabase-swift/issues/32#issuecomment-1168798055 (FWIW, I was never able to get that example working.. it would never redirect back to my app)

    Found another request for it https://www.reddit.com/r/Supabase/comments/xbjkt5/guidance_needed_in_relation_to_supabase_auth_swift/

    It's also being talked about in the community Discord channel (#swift) for something like this (?)

    I'd also like to add that I'm new to Swift and would be interested in a full blown example app I could clone and learn from... with auth, realtime, and databasing. There's a lot of examples on the Supabase website, just none in Swift!

    enhancement 
    opened by toystorynova 0
Releases(0.0.12)
  • 0.0.12(Jan 4, 2023)

    What's Changed

    • Fixed README code example typo. by @koffietiger in https://github.com/supabase-community/supabase-swift/pull/43
    • Implement HTTP Client protocols for sub packages by @grsouza in https://github.com/supabase-community/supabase-swift/pull/42
    • update dependency branch name by @Colgates in https://github.com/supabase-community/supabase-swift/pull/44
    • Ignore error on refreshing current session by @tmn in https://github.com/supabase-community/supabase-swift/pull/46
    • Fixed buid errors - #52 by @glowcap in https://github.com/supabase-community/supabase-swift/pull/53

    New Contributors

    • @koffietiger made their first contribution in https://github.com/supabase-community/supabase-swift/pull/43
    • @Colgates made their first contribution in https://github.com/supabase-community/supabase-swift/pull/44
    • @tmn made their first contribution in https://github.com/supabase-community/supabase-swift/pull/46
    • @glowcap made their first contribution in https://github.com/supabase-community/supabase-swift/pull/53

    Full Changelog: https://github.com/supabase-community/supabase-swift/compare/0.0.11...0.0.12

    Source code(tar.gz)
    Source code(zip)
  • 0.0.11(Oct 14, 2022)

  • 0.0.10(Oct 6, 2022)

  • 0.0.9(Aug 28, 2022)

  • 0.0.8(Jul 12, 2022)

    Chnages

    • Update postgrest-swift to 0.0.6 for fixing a bug introduced on the last version.

    Full Changelog: https://github.com/supabase-community/supabase-swift/compare/0.0.7...0.0.8

    Source code(tar.gz)
    Source code(zip)
  • 0.0.7(Jul 8, 2022)

    What's Changed

    • Refresh session before calling into Postgrest by @grsouza in https://github.com/supabase-community/supabase-swift/pull/33

    Full Changelog: https://github.com/supabase-community/supabase-swift/compare/0.0.6...0.0.7

    Source code(tar.gz)
    Source code(zip)
  • 0.0.6(Jul 2, 2022)

  • 0.0.5(Jun 13, 2022)

  • 0.0.4(Mar 27, 2022)

  • 0.0.3(Mar 19, 2022)

  • 0.0.2(Feb 22, 2022)

Owner
Supabase Community
Supabase Community
Swift iPhone and iPad Client for Polls API, using Hyperdrive API client

Polls Client This is a Swift iPhone and iPad client for the Polls API - a simple application allowing users to view polls and vote in them. Polls is a

Apiary 34 Jul 15, 2022
A small SwiftUI based chat client for IRC, using swift-nio-irc

NeoIRC A simple Internet Relay Chat client implemented using SwiftNIO and SwiftUI. Inspired by: For maximum NIO someone (I’m tempted) should adopt NIO

The Noze Consortium 18 Jun 22, 2022
A swift client library for GoTrue.

gotrue-swift Swift client for the GoTrue API. Using The usage should be the same as gotrue-js except: Oauth2: signIn with oauth2 provider only return

Supabase 23 Jan 7, 2023
Seaglass is a truly native macOS client for Matrix. It is written in Swift and uses the Cocoa user interface framework.

Seaglass is a truly native macOS client for Matrix. It is written in Swift and uses the Cocoa user interface framework.

null 1 Jan 17, 2022
A swift client library for GoTrue.

gotrue-swift Swift client for the GoTrue API. Using The usage should be the same as gotrue-js except: Oauth2: signIn with oauth2 provider only return

Supabase Community 23 Jan 7, 2023
iOS client for Giphy written in Swift with ReactiveCocoa

Giraffe iOS client for Giphy written in Swift with ReactiveCocoa Requirements iOS 10.0 Beta Xcode 8 Beta 2 Swift 2.3 Carthage Why S

Yevhen Dubinin 43 Feb 10, 2022
A completely native Discord client for macOS built 100% in Swift and SwiftUI

Swiftcord A completely native Discord client for macOS built 100% in Swift and SwiftUI This project aims to create a fully functional native Discord c

CryptoAlgo-Dev 1.1k Jan 9, 2023
A cross-platform Reddit client built in SwiftUI

A cross-platform Reddit client created in SwiftUI. Get the Public Beta Note: This project is far from complete. It still lacks many features of your t

Carson Katri 1.2k Dec 25, 2022
An open-source SwiftUI Stack Overflow client

StackOv A SwiftUI Stackoverflow client We are currently in the developing process of the next version of StackOv app. The demo version of StackOv is a

Surf 235 Dec 17, 2022
Tutorial GraphQL + Node Express + MySQL, and sample for Android / iOS client

GraphQL-tutorial Tutorial for GraphQL + Node Express + MySQL, and sample for Android / iOS client Blog NeoRoman's GraphQL-tutorial (Korean) Materials

Henry Kim 4 Oct 20, 2022
Native Jellyfin Client for iOS and tvOS

Swiftfin Swiftfin is a modern client for the Jellyfin media server. Redesigned in Swift to maximize direct play with the power of VLC and look native

Jellyfin 1.1k Jan 6, 2023
Basic Unsplash client for iOS made with SwiftUI (beta).

PapersSwiftUI Basic Unsplash client for iOS made with SwiftUI (beta). Note SwiftUI is still in beta and I'm also still learning how it works. To-Do: P

Don 19 Dec 17, 2022
💥 a modern xkcd iOS client

XKCDY / app This is the source code of the XKCDY app. I built this app primarily as a way to learn Swift and SwiftUI. Because I was learning as I buil

null 32 Oct 30, 2022
A xkcd client written in SwiftUI.

xkcd A xkcd client written in SwiftUI. Architechture: Tried to use MVVM but with CoreData... If you know, you know. Features: Supports Dark/Light mode

Sina Rabiei 10 Oct 21, 2022
Client library for making in-app purchases on iOS and macOS Automattic apps

MobilePayKit Client library for making in-app purchases on iOS and macOS Automattic apps Introduction MobilePayKit is a client library for making in-a

Automattic 8 Oct 20, 2022
The alternative last.fm client for iOS made with SwiftUI

first.fm - The alternative last.fm client for iOS (it's actually not available on the App Store... yet) Features Your profile (top artists, tracks and

Stanislas 22 Aug 22, 2022
Client that retrieves specific information about stocks.

Client that retrieves specific information about stocks. This app is used as training to develop design pattern skills, in this case: the Coordinator Pattern

Marco Marinò 1 Apr 26, 2022
Tanukis-Stash - Open source e621 client for iOS built with SwiftUI

The Tanuki's Stash The worlds first e621 client for iOS, iPadOS, and macOS built

Jay 3 Jul 29, 2022
Mastodon and Twitter client for iOS, iPadOS & macOS

Note: Mamoot! is under heavy development and is obviously far from complete at this moment. We're currently looking for more people to work with us, s

null 13 Nov 22, 2022