🍯 Syntactic sugar for Moya

Overview

MoyaSugar

Swift CI CocoaPods

Syntactic sugar for Moya.

Why?

Moya is an elegant network abstraction layer which abstracts API endpoints gracefully with enum. However, it would become massive when the application is getting larger. Whenever you add an endpoint, you should write code at least 5 places: enum case, method, path, parameters and parameterEncoding property. It makes you scroll down again and again. Besides, if you would like to set different HTTP header fields, you should customize endpointClosure of MoyaProvider.

If you're as lazy as I am, MoyaSugar is for you.

At a Glance

Forget about method, path, parameters, parameterEncoding and endpointClosure. Use route, params, httpHeaderFields instead.

extension MyService: SugarTargetType {
  var route: Route {
    return .get("/me")
  }

  var params: Parameters? {
    return JSONEncoding() => [
      "username": "devxoul",
      "password": "****",
    ]
  }

  var headers: [String: String]? {
    return ["Accept": "application/json"]
  }
}

Use MoyaSugarProvider instead of MoyaProvider.

let provider = MoyaSugarProvider<MyService>()
let provider = RxMoyaSugarProvider<MyService>() // If you're using Moya/RxSwift

Complete Example

import Moya
import Moyasugar

enum GitHubAPI {
  case url(String)
  case userRepos(owner: String)
  case createIssue(owner: String, repo: String, title: String, body: String?)
  case editIssue(owner: String, repo: String, number: Int, title: String?, body: String?)
}

extension GitHubAPI : SugarTargetType {

  /// method + path
  var route: Route {
    switch self {
    case .url(let urlString):
      return .get(urlString)

    case .userRepos(let owner):
      return .get("/users/\(owner)/repos")

    case .createIssue(let owner, let repo, _, _):
      return .post("/repos/\(owner)/\(repo)/issues")

    case .editIssue(let owner, let repo, let number, _, _):
      return .patch("/repos/\(owner)/\(repo)/issues/\(number)")
    }
  }

  // override default url building behavior
  var url: URL {
    switch self {
    case .url(let urlString):
      return URL(string: urlString)!
    default:
      return self.defaultURL
    }
  }

  /// encoding + parameters
  var params: Parameters? {
    switch self {
    case .url:
      return nil

    case .userRepos:
      return nil

    case .createIssue(_, _, let title, let body):
      return JSONEncoding() => [
        "title": title,
        "body": body,
      ]

    case .editIssue(_, _, _, let title, let body):
      // Use `URLEncoding()` as default when not specified
      return [
        "title": title,
        "body": body,
      ]
    }
  }

  var headers: [String: String]? {
    return [
      "Accept": "application/json"
    ]
  }

}

APIs

  • 🔗 protocol SugarTargetType

    - extension GitHubAPI: TargetType
    + extension GitHubAPI: SugarTargetType
  • 🔗 var route: Route

    Returns Route which contains HTTP method and URL path information.

    - var method: Method { get }
    - var path: String { get }
    + var route: Route { get }

    Example:

    var route: Route {
      return .get("/me")
    }
  • 🔗 var url: URL

    Returns the request URL. It retuens defaultURL as default, which is the combination of baseURL and path. Implement this property to return custom url. See #6 for detail.

  • 🔗 var params: Parameters?

    Returns Parameters which contains parameter encoding and values.

    - var parameters: [String: Any]? { get }
    + var params: Parameters? { get }

    Example:

    var params: Parameters? {
      return JSONEncoding() => [
        "username": "devxoul",
        "password": "****",
      ]
    }

    Note: If the MoyaSugarProvider is initialized with an endpointClosure parameter, HTTP header fields of endpointClosure will be used. This is how to extend the target's HTTP header fields in endpointClosure:

    let endpointClosure: (GitHubAPI) -> Endpoint<GitHubAPI> = { target in
      let defaultEndpoint = MoyaProvider.defaultEndpointMapping(for: target)
      return defaultEndpoint
        .adding(newHTTPHeaderFields: ["Authorization": "MySecretToken"])
    }

Requirements

Same with Moya

Installation

  • Using CocoaPods:

    pod 'MoyaSugar'
    pod 'MoyaSugar/RxSwift' # Use with RxSwift

MoyaSugar currently doesn't cupport Carthage.

Contributing

$ TEST=1 swift package generate-xcodeproj
$ open MoyaSugar.xcodeproj

License

MoyaSugar is under MIT license. See the LICENSE file for more info.

Comments
  • Implementation of SugarTargetType

    Implementation of SugarTargetType

    Hi,

    I need to put several http headers with my project, that's why I want to use your abstraction of Moya and have something like this :

    enum BikeTrackTestRx {
        case userLogIn(mail: String, password: String)
        case userCreate(mail: String, password: String)
    }
    extension BikeTrackTestRx: SugarTargetType {
        var url: URL {return URL(string: "https://api.herokuapp.com")!}
        
        var route: Route {
            switch self {
                case .userLogIn(_):
                    return .post("/authenticate")
                case .userCreate(_):
                    return .post("/signup")
            }
        }
        
        var params: Parameters? {
            switch self {
            case .userLogIn(let mail, let password):
                return JSONEncoding.default => [
                    "mail": "\(mail)",
                    "password": "\(password)"
                ]
            case .userCreate(let mail, let password):
                return JSONEncoding.default => [
                    "mail": "\(mail)",
                    "password": "\(password)"
                ]
            }
        }
        
        var task: Task {
            return .request
        }
        
        var sampleData: Data {
            switch self {
            case .userLogIn(_):
                return "{\"username\": \"toto\", \"password\": \"titi\"}".data(using: .utf8)!
            case .userCreate(_):
                return "{\"username\": \"toto\", \"password\": \"titi\"}".data(using: .utf8)!
            }
        }
    
        var httpHeaderFields: [String: String]? {
            switch self {
            case .userLogIn(_):
                    return ["Authorization": "MyKey",
                            "token": "randomToken"]
            default:
                return ["Authorization": "MyKey"]
            }
        }
        
    }
    

    But i got an error : Type 'BikeTrackTestRx' does not conform to protocol 'TargetType'

    Maybe I don't have the good version of Moya, so there is my podfile :

    source 'https://github.com/CocoaPods/Specs.git'
    platform :ios, '10.0'
    use_frameworks!
    
    target 'Biketrack' do
           pod 'RxCocoa', '~> 3.0.0'
           pod 'Moya-ModelMapper/RxSwift', '~> 4.1.0'
           pod 'MoyaSugar/RxSwift', '~> 0.4'
           pod 'RxOptional'
    end
    

    Thanks in advance 😃

    opened by valentinwallet 5
  • Optional parameters

    Optional parameters

      var params: Parameters? {
        switch self {
        case .cars(let offset, let sort): //here offset and sort are optionals
          if offset != nil && sort != nil { return ["offset":offset!, "sort": sort!] }
          else if offset != nil { return ["offset":offset!] }
          else if sort != nil { return ["sort": sort!] }
          else { return nil }
        }
      }
    

    I'm trying to get this variations:

    /Cars
    /Cars?offset=1
    /Cars?sort=price
    /Cars?offset=1&sort=price
    

    Is there any way to simplify this ?

    opened by dtomicAZ 4
  • Add additional parameters to params

    Add additional parameters to params

    I have two fields, most of the requests are required, but I don't want to repeat these two fields in all params. Is there any way to solve them? Sorry, my English is not very good, use Google translate, if you can solve it, thank you very much

    opened by aidevjoe 4
  • Thoughts on using private structs in the file that declares the endpoints?

    Thoughts on using private structs in the file that declares the endpoints?

    This is awesome @devxoul 😄

    I ran across https://github.com/Moya/Moya/issues/447, and it made me wonder if it made any sense to use something like it in MoyaSugar, or if it makes more sense as is?

    I'm really not sure, but the article included in the issue piqued my interest

    opened by AndrewSB 4
  • Let EndpointClosure to override Target headers

    Let EndpointClosure to override Target headers

    In my understanding, we use Endpoint closure in Moya to override some of the Target parameters. In MoyaSugar on the other hand, we override Endpoint defined headers with Target headers which to me seems wrong. For example, we have a Target that defines Content-Type and Accept headers

    var httpHeaderFields: [String : String]? {
        return ["Content-Type": "application/json",
                "Accept": "application/json"]
    }
    

    and use EndpointClosure to inject Authorization header - Target itself does not need to know, whether the user is authorized or not. So I define an EndpointClosure like so

    let endpointClosure: ((MainApi) -> Endpoint<MainApi>) = { target in
        let url = target.baseURL.appendingPathComponent(target.path).absoluteString
                
        var headers = target.httpHeaderFields ?? [:]
        headers["Authorization"] = token
                
        return Endpoint(url: url, sampleResponseClosure: { .networkResponse(200, target.sampleData) },
                            method: target.method, parameters: target.parameters, httpHeaderFields: headers)
    }
    

    but then my headers get overwritten by SugarEndpointClosure.

    So in my opinion it's reasonable to use Endpoint provided headers and if there's none (as MoyaProvider.defaultEndpointMapping does not provide any headers) use Target defined ones

    opened by marvin-yorke 3
  • How to send String JSON Array as parameter?

    How to send String JSON Array as parameter?

    I want to send json array in body of request with MoyaSugar, e.g. [1,2,3]

    Can someone provide me solution, thanks.

    Here is some examples using Moya: https://github.com/Moya/Moya/issues/467

    but I can't get it work with MoyaSugar.

    opened by dtomicAZ 2
  • Changes HTTP verbs enum to lower case (for Moya 8.0.0-beta.3)

    Changes HTTP verbs enum to lower case (for Moya 8.0.0-beta.3)

    There is an breaking change in Moya 8.0.0-beta.3 relating to HTTP verbs enum. https://github.com/Moya/Moya/commit/76886247f32ff29e55ed86ff5f9913245fa98d62

    I suggest this PR to correspond with latest tag of the Moya, so consider this if you want this repository to be up-to-date.

    opened by innocarpe 2
  • MoyaSugar behaves differently when `route` contains an empty `path`

    MoyaSugar behaves differently when `route` contains an empty `path`

    I'm designing a simple SugarTargetType to download files from arbitrary urls:

    /* ... */
    
    var baseURL: URL {
      switch self {
      case .download(let url): return url
      }
    }
      
    var route: Route {
      return .get("")
    }
    
    /* ... */
    

    Moya's previous behaviour was to always append the path to the baseURL. They changed this behaviour in Moya 8.0.4 (see: https://github.com/Moya/Moya/pull/1053) to avoid appending an extraneous / at the end of the url.

    It seems to me that the code can easily be modified to respect the new Moya behaviour. The change would happen at https://github.com/devxoul/MoyaSugar/blob/master/Sources/SugarTargetType.swift#L56

    var defaultURL: URL {
      return self.baseURL.appendingPathComponent(self.path)
    }
    

    would become

    var defaultURL: URL {
      return self.path.isEmpty ? self.baseURL : self.baseURL.appendingPathComponent(self.path)
    }
    

    I would do a pull request but I am unable to compile the project on my computer.

    opened by lowip 1
  • Add support for customizing target's url

    Add support for customizing target's url

    Summary

    This PR provides an way to customize the target's url.

    Background

    Imagine that we have an API which returns the next url path or url:

    {
      "data": [
        {...},
        {...},
        {...},
      ],
      "next": "/articles?page=2"
    }
    

    In this case, we can add a case path(String):

    enum MyAPI: SugarTargetType {
      case path(String)
      case user(Int)
    
      var route: Route {
        switch self {
        case .path(let path):
          return .get(path)
        case .user(let id):
          return .get("/user/\(id)")
        }
      }
    }
    

    Default implementation of Moya uses URL.appendingPathComponent(_:) to make URL, so the URL will become http://example.com/articles%3Fpage=2 (? becomes %3F)

    Customizing URL

    With this PR, you'll be able to customize target URLs.

    extension MyAPI: SugarTargetType {
      var url: URL {
        switch self {
        case .path:
          return URL(string: self.baseURL + self.path)! // custom url
        default:
          return self.defaultURL // default url
        }
      }
    }
    
    opened by devxoul 0
  • Bump tzinfo from 1.2.3 to 1.2.10

    Bump tzinfo from 1.2.3 to 1.2.10

    Bumps tzinfo from 1.2.3 to 1.2.10.

    Release notes

    Sourced from tzinfo's releases.

    v1.2.10

    TZInfo v1.2.10 on RubyGems.org

    v1.2.9

    • Fixed an incorrect InvalidTimezoneIdentifier exception raised when loading a zoneinfo file that includes rules specifying an additional transition to the final defined offset (for example, Africa/Casablanca in version 2018e of the Time Zone Database). #123.

    TZInfo v1.2.9 on RubyGems.org

    v1.2.8

    • Added support for handling "slim" format zoneinfo files that are produced by default by zic version 2020b and later. The POSIX-style TZ string is now used calculate DST transition times after the final defined transition in the file. The 64-bit section is now always used regardless of whether Time has support for 64-bit times. #120.
    • Rubinius is no longer supported.

    TZInfo v1.2.8 on RubyGems.org

    v1.2.7

    • Fixed 'wrong number of arguments' errors when running on JRuby 9.0. #114.
    • Fixed warnings when running on Ruby 2.8. #112.

    TZInfo v1.2.7 on RubyGems.org

    v1.2.6

    • Timezone#strftime('%s', time) will now return the correct number of seconds since the epoch. #91.
    • Removed the unused TZInfo::RubyDataSource::REQUIRE_PATH constant.
    • Fixed "SecurityError: Insecure operation - require" exceptions when loading data with recent Ruby releases in safe mode.
    • Fixed warnings when running on Ruby 2.7. #106 and #111.

    TZInfo v1.2.6 on RubyGems.org

    v1.2.5

    • Support recursively (deep) freezing Country and Timezone instances. #80.
    • Allow negative daylight savings time offsets to be derived when reading from zoneinfo files. The utc_offset and std_offset are now derived correctly for Europe/Dublin in the 2018a and 2018b releases of the Time Zone Database.

    TZInfo v1.2.5 on RubyGems.org

    v1.2.4

    • Ignore the leapseconds file that is included in zoneinfo directories installed with version 2017c and later of the Time Zone Database.

    TZInfo v1.2.4 on RubyGems.org

    Changelog

    Sourced from tzinfo's changelog.

    Version 1.2.10 - 19-Jul-2022

    Version 1.2.9 - 16-Dec-2020

    • Fixed an incorrect InvalidTimezoneIdentifier exception raised when loading a zoneinfo file that includes rules specifying an additional transition to the final defined offset (for example, Africa/Casablanca in version 2018e of the Time Zone Database). #123.

    Version 1.2.8 - 8-Nov-2020

    • Added support for handling "slim" format zoneinfo files that are produced by default by zic version 2020b and later. The POSIX-style TZ string is now used calculate DST transition times after the final defined transition in the file. The 64-bit section is now always used regardless of whether Time has support for 64-bit times. #120.
    • Rubinius is no longer supported.

    Version 1.2.7 - 2-Apr-2020

    • Fixed 'wrong number of arguments' errors when running on JRuby 9.0. #114.
    • Fixed warnings when running on Ruby 2.8. #112.

    Version 1.2.6 - 24-Dec-2019

    • Timezone#strftime('%s', time) will now return the correct number of seconds since the epoch. #91.
    • Removed the unused TZInfo::RubyDataSource::REQUIRE_PATH constant.
    • Fixed "SecurityError: Insecure operation - require" exceptions when loading data with recent Ruby releases in safe mode.
    • Fixed warnings when running on Ruby 2.7. #106 and #111.

    Version 1.2.5 - 4-Feb-2018

    • Support recursively (deep) freezing Country and Timezone instances. #80.
    • Allow negative daylight savings time offsets to be derived when reading from zoneinfo files. The utc_offset and std_offset are now derived correctly for Europe/Dublin in the 2018a and 2018b releases of the Time Zone Database.

    ... (truncated)

    Commits
    • 0814dcd Fix the release date.
    • fd05e2a Preparing v1.2.10.
    • b98c32e Merge branch 'fix-directory-traversal-1.2' into 1.2
    • ac3ee68 Remove unnecessary escaping of + within regex character classes.
    • 9d49bf9 Fix relative path loading tests.
    • 394c381 Remove private_constant for consistency and compatibility.
    • 5e9f990 Exclude Arch Linux's SECURITY file from the time zone index.
    • 17fc9e1 Workaround for 'Permission denied - NUL' errors with JRuby on Windows.
    • 6bd7a51 Update copyright years.
    • 9905ca9 Fix directory traversal in Timezone.get when using Ruby data source
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump cocoapods-downloader from 1.1.3 to 1.6.3

    Bump cocoapods-downloader from 1.1.3 to 1.6.3

    Bumps cocoapods-downloader from 1.1.3 to 1.6.3.

    Release notes

    Sourced from cocoapods-downloader's releases.

    1.6.3

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.2

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.1

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.0

    Enhancements
    • None.
    Bug Fixes
    • Adds a check for command injections in the input for hg and git.
      orta #124

    1.5.1

    Enhancements
    • None.
    Bug Fixes
    • Fix "can't modify frozen string" errors when pods are integrated using the branch option
      buju77 #10920

    1.5.0

    ... (truncated)

    Changelog

    Sourced from cocoapods-downloader's changelog.

    1.6.3 (2022-04-01)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.2 (2022-03-28)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.1 (2022-03-23)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.0 (2022-03-22)

    Enhancements
    • None.
    Bug Fixes
    • Adds a check for command injections in the input for hg and git.
      orta #124

    1.5.1 (2021-09-07)

    Enhancements
    • None.

    ... (truncated)

    Commits
    • c03e2ed Release 1.6.3
    • f75bccc Disable Bazaar tests due to macOS 12.3 not including python2
    • 52a0d54 Merge pull request #128 from CocoaPods/validate_before_dl
    • d27c983 Ensure that the git pre-processor doesn't accidentally bail also
    • 3adfe1f [CHANGELOG] Add empty Master section
    • 591167a Release 1.6.2
    • d2564c3 Merge pull request #127 from CocoaPods/validate_before_dl
    • 99fec61 Switches where we check for invalid input, to move it inside the download fun...
    • 96679f2 [CHANGELOG] Add empty Master section
    • 3a7c54b Release 1.6.1
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Build errors with new release Moya 9.0.0

    Build errors with new release Moya 9.0.0

    Are there any plans to migrate to the latest Moya release according to this guide ? Otherwise you should fix podspec file by replacing Moya dependency version 'Moya', '>= 8.0.0' to 'Moya', '~> 8.0.0'

    opened by hitman1711 3
Releases(1.3.3)
Owner
Suyeol Jeon
A lazy developer 😴 I write many code to write less code.
Suyeol Jeon
And - Syntactic sugar for Swift initializers

And Syntactic sugar for Swift initializers Usage let label = UILabel().and { $0

donggyu 4 Jun 10, 2022
Swift's Sugar. Heavily inspired on Objc Sugar

Swift's Sugar. Heavily inspired on Objc Sugar

Rui Peres 154 Jun 29, 2022
📦 KeyPath dynamicMemberLookup based syntax sugar for Swift.

DuctTape ?? KeyPath dynamicMemberLookup based syntax sugar for Swift. let label: UILabel = UILabel().ductTape .numberOfLines(0) .textColor(.re

Taiki Suzuki 171 Nov 4, 2022
Sugar is a sweetener for your Cocoa implementations.

Sugar is a sweetener for your Cocoa implementations. Table of Contents iOS Application Screen Simulator Keyboard Observer iOS Extensions UIView

HyperRedink 1.1k Dec 29, 2022
SharkUtils is a collection of Swift extensions, handy methods and syntactical sugar that we use within our iOS projects at Gymshark.

SharkUtils is a collection of Swift extensions, handy methods and syntactical sugar that we use within our iOS projects at Gymshark.

Gymshark 1 Jul 6, 2021
Synatax sugar for Measurement of Foundation.

WrappedMeasurement 2022 © Weizhong Yang a.k.a zonble Syntax sugar for NSMeasurement of Foundation. NSMeasurement and NSUnit compose a great tool to le

Weizhong Yang a.k.a zonble 8 Jan 25, 2022
HumanMeasurementSwift - Synatax sugar for Measurement of Foundation

HumanMeasurement 2022 © Weizhong Yang a.k.a zonble Syntax sugar for NSMeasuremen

Weizhong Yang a.k.a zonble 8 Jan 25, 2022
TinyConstraints is the syntactic sugar that makes Auto Layout sweeter for human use.

TinyConstraints is the syntactic sugar that makes Auto Layout sweeter for human use. Features Pure Swift 5 sweetness. Everything you can do with Auto

Robert-Hein Hooijmans 3.8k Jan 5, 2023
Syntactic sugar in Swift for asynchronous dispatches in Grand Central Dispatch

Async Now more than syntactic sugar for asynchronous dispatches in Grand Central Dispatch (GCD) in Swift Async sugar looks like this: Async.userInitia

Tobias Due Munk 4.6k Dec 27, 2022
✨ Super sweet syntactic sugar for Swift initializers

Then ✨ Super sweet syntactic sugar for Swift initializers. At a Glance Initialize UILabel then set its properties. let label = UILabel().then { $0.t

Suyeol Jeon 4k Jan 4, 2023
Syntactic sugar in Swift for asynchronous dispatches in Grand Central Dispatch (iOS7+ and OS X 10.9+ compatible)

Async.legacy Syntactic sugar in Swift for asynchronous dispatches in Grand Central Dispatch (GCD) Async rewritten for iOS7 and OS X 10.9 Compatibility

Joseph Lord 31 Jul 1, 2019
💊 Syntactic sugar for Swift do-try-catch

Fallback Syntactic sugar for Swift do-try-catch. At a Glance value = try fallback( try get("A"), try get("B"), try get("C"), try get("D") ) is

Suyeol Jeon 43 May 25, 2020
✨ Super sweet syntactic sugar for SwiftUI.View initializers.

ViewCondition ✨ Super sweet syntactic sugar for SwiftUI.View initializers. At a Glance struct BorderTextView: View { var color: Color? @ViewBuild

Yoon Joonghyun 76 Dec 17, 2022
Syntactic sugar in Swift for asynchronous dispatches in Grand Central Dispatch

Async Now more than syntactic sugar for asynchronous dispatches in Grand Central Dispatch (GCD) in Swift Async sugar looks like this: Async.userInitia

Tobias Due Munk 4.6k Dec 27, 2022
Syntactic Sugar for Accelerate/vImage and Core Image Filters

ShinpuruImage Syntactic Sugar for Accelerate/vImage and Core Image Filters ShinpuruImage offers developers a consistent and strongly typed interface t

simon gladman 100 Jan 6, 2023
Shadow - Syntactic sugar for shadows in the SwiftUI framework

Shadow Syntactic sugar for shadows in the SwiftUI framework. import SwiftUI impo

Dima Koskin 2 Jan 31, 2022
And - Syntactic sugar for Swift initializers

And Syntactic sugar for Swift initializers Usage let label = UILabel().and { $0

donggyu 4 Jun 10, 2022
Sweet-swift - Make Swift Sweet by Gracefully Introducing Syntactic Sugar, Helper Functions and Common Utilities

Sweet Swift Make Swift Sweet by Gracefully Introducing Syntactic Sugar, Helper F

Yanzhan Yang 2 Feb 6, 2022
Swift's Sugar. Heavily inspired on Objc Sugar

Swift's Sugar. Heavily inspired on Objc Sugar

Rui Peres 154 Jun 29, 2022
Reflection based (Dictionary, CKRecord, NSManagedObject, Realm, JSON and XML) object mapping with extensions for Alamofire and Moya with RxSwift or ReactiveSwift

EVReflection General information At this moment the master branch is tested with Swift 4.2 and 5.0 beta If you want to continue using EVReflection in

Edwin Vermeer 964 Dec 14, 2022