The civilized way to write REST API clients for iOS / macOS

Overview

Siesta

The elegant way to write iOS / macOS REST clients

Build Status Version Platforms Docs GitHub license Twitter: @siestaframework

Drastically simplifies app code by providing a client-side cache of observable models for RESTful resources.

  • OS: iOS 10+, macOS 10.11+, tvOS 9.0+
  • Languages: Written in Swift, supports apps in both Swift and Objective-C
  • Tool requirements: Xcode 11.3+, Swift 5.1+ (See swift-* branches for legacy support)
  • License: MIT

Table of Contents

Overview

Documentation

  • User Guide — Extensive! Thrilling! Full of examples!
  • API Docs — Lascivious detail! Hidden treasure! More examples!
  • Specs — OK, doesn’t sound glamorous, but surprisingly informative.

What’s It For?

The Problem

Want your app to talk to a remote API? Welcome to your state nightmare!

You need to display response data whenever it arrives. Unless the requesting screen is no longer visible. Unless some other currently visible bit of UI happens to need the same data. Or is about to need it.

You should show a loading indicator (but watch out for race conditions that leave it stuck spinning forever), display user-friendly errors (but not redundantly — no modal alert dogpiles!), give users a retry mechanism … and hide all of that when a subsequent request succeeds.

Be sure to avoid redundant requests — and redundant response deserialization. Deserialization should be on a background thread, of course. Oh, and remember not to retain your ViewController / model / helper thingy by accident in your callback closures. Unless you’re supposed to.

Naturally you’ll want to rewrite all of this from scratch in a slightly different ad hoc way for every project you create.

What could possibly go wrong?

The Solution

Siesta ends this headache by providing a resource-centric alternative to the familiar request-centric approach.

Siesta provides an app-wide observable model of a RESTful resource’s state. This model answers three basic questions:

  • What is the latest data for this resource, if any?
  • Did the latest request result in an error?
  • Is there a request in progress?

…and broadcasts notifications whenever the answers to these questions change.

Siesta handles all the transitions and corner cases to deliver these answers wrapped up with a pretty bow on top, letting you focus on your logic and UI.

Features

  • Decouples view, model, and controller lifecycle from network request lifecycle
  • Decouples request initiation from request configuration
  • Eliminates error-prone state tracking logic
  • Eliminates redundant network requests
  • Unified handling for all errors: encoding, network, server-side, and parsing
  • Highly extensible, multithreaded response deserialization
  • Transparent built-in parsing (which you can turn off) for JSON, text, and images
  • Smooth progress reporting that accounts for upload, download, and latency
  • Transparent Etag / If-Modified-Since handling
  • Prebaked UI helpers for loading & error handling, remote images
  • Debug-friendly, customizable logging
  • Written in Swift with a great Swift-centric API, but…
  • …also works great from Objective-C thanks to a compatibility layer.
  • Lightweight. Won’t achieve sentience and attempt to destroy you.
  • Robust regression tests
  • Documentation and more documentation

What it doesn’t do

  • It doesn’t reinvent networking. Siesta delegates network operations to your library of choice (URLSession by default, or Alamofire, or inject your own custom adapter).
  • It doesn’t hide HTTP. On the contrary, Siesta strives to expose the full richness of HTTP while providing conveniences to simplify common usage patterns. You can devise an abstraction layer to suit your own particular needs, or work directly with Siesta’s nice APIs for requests and response entities.
  • It doesn’t do automatic response model mapping. This means that Siesta doesn’t constrain your response models, or force you to have any at all. Add a response transformer to output models of whatever flavor your app prefers, or work directly with parsed JSON.

Origin

This project started as helper code we wrote out of practical need on several Bust Out Solutions projects. When we found ourselves copying the code between projects, we knew it was time to open source it.

For the open source transition, we took the time to rewrite our code in Swift — and rethink it in Swift, embracing the language to make the API as clean as the concepts.

Siesta’s code is therefore both old and new: battle-tested on the App Store, then reincarnated in a Swifty green field.

Design Philosophy

Make the default thing the right thing most of the time.

Make the right thing easy all of the time.

Build from need. Don’t invent solutions in search of problems.

Design the API with these goals:

  1. Make client code easy to read.
  2. Make client code easy to write.
  3. Keep the API clean.
  4. Keep the implementation tidy.

…in that order of priority.


Installation

Siesta requires Swift 5 and Xcode 11. (Use the swift-* branches branches if you are still on an older version.)

Swift Package Manager

In Xcode:

  • File → Swift Packages → Add Package Dependency…

  • Enter https://github.com/bustoutsolutions/siesta in the URL field and click Next.

  • The defaults for the version settings are good for most projects. Click Next.

  • Check the checkbox next to “Siesta.”

    • Also check “SiestaUI” if you want to use any of the UI helpers.
    • Also check “Siesta_Alamofire” if you want to use the Alamofire extension for Siesta.
  • Click “Finish.”

  • Siesta does not yet support resources supplied by dependencies. This means that if:

    • you included SiestaUI above
    • and you plan to use ResourceStatusOverlay
    • and you are using its default initializer instead of providing your own custom UI layout,

    …then you’ll need to copy ResourceStatusOverlay.xib into your own project.

    SwiftPM just recently added support for this, and Siesta will add it in the next release.

Please note that Xcode will show all of Siesta’s optional and test-only dependencies, including Quick, Nimble, and Alamofire. Don’t worry: these won’t actually be bundled into your app (except Alamofire, if you use it).

CocoaPods

In your Podfile:

pod 'Siesta', '~> 1.0'

If you want to use the UI helpers:

pod 'Siesta/UI', '~> 1.0'

If you want to use Alamofire as your networking provider instead of Foundation’s URLSession:

pod 'Siesta/Alamofire', '~> 1.0'

(You’ll also need to pass an Alamofire.Manager when you configure your Siesta.Service. See the API docs for more info.)

Carthage

In your Cartfile:

github "bustoutsolutions/siesta" ~> 1.0

Follow the Carthage instructions to add Siesta.framework to your project. If you want to use the UI helpers, you will also need to add SiestaUI.framework to your project as well.

As of this writing, there is one additional step you need to follow that isn’t in the Carthage docs:

  • Build settings → Framework search paths → $(PROJECT_DIR)/Carthage/Build/iOS/

(In-depth discussion of Carthage in recent Xcode versions is here.)

The code in Extensions/ is not part of the Siesta.framework that Carthage builds. (This currently includes only Alamofire support.) You will need to include those source files in your project manually if you want to use them.

Git Submodule

  1. Clone Siesta as a submodule into the directory of your choice, in this case Libraries/Siesta:

    git submodule add https://github.com/bustoutsolutions/siesta.git Libraries/Siesta
    git submodule update --init
    
  2. Drag Siesta.xcodeproj into your project tree as a subproject.

  3. Under your project's Build Phases, expand Target Dependencies. Click the + button and add Siesta.

  4. Expand the Link Binary With Libraries phase. Click the + button and add Siesta.

  5. Click the + button in the top left corner to add a Copy Files build phase. Set the directory to Frameworks. Click the + button and add Siesta.

If you want to use the UI helpers, you will need to repeat steps 3–5 for SiestaUI.

Installation troubles?

Please let us know about it, even if you eventually figure it out. Knowing where people get stuck will help improve these instructions!


Basic Usage

Make a shared service instance for the REST API you want to use:

let MyAPI = Service(baseURL: "https://api.example.com")

Now register your view controller — or view, internal glue class, reactive signal/sequence, anything you like — to receive notifications whenever a particular resource’s state changes:

override func viewDidLoad() {
    super.viewDidLoad()

    MyAPI.resource("/profile").addObserver(self)
}

Use those notifications to populate your UI:

func resourceChanged(_ resource: Resource, event: ResourceEvent) {
    nameLabel.text = resource.jsonDict["name"] as? String
    colorLabel.text = resource.jsonDict["favoriteColor"] as? String

    errorLabel.text = resource.latestError?.userMessage
}

Or if you don’t like delegates, Siesta supports closure observers:

MyAPI.resource("/profile").addObserver(owner: self) {
    [weak self] resource, _ in

    self?.nameLabel.text = resource.jsonDict["name"] as? String
    self?.colorLabel.text = resource.jsonDict["favoriteColor"] as? String

    self?.errorLabel.text = resource.latestError?.userMessage
}

Note that no actual JSON parsing occurs when we invoke jsonDict. The JSON has already been parsed off the main thread, in a GCD queue — and unlike other frameworks, it is only parsed once no matter how many observers there are.

Of course, you probably don’t want to work with raw JSON in all your controllers. You can configure Siesta to automatically turn raw responses into models:

MyAPI.configureTransformer("/profile") {  // Path supports wildcards
    UserProfile(json: $0.content)         // Create models however you like
}

…and now your observers see models instead of JSON:

MyAPI.resource("/profile").addObserver(owner: self) {
    [weak self] resource, _ in
    self?.showProfile(resource.typedContent())  // Response now contains UserProfile instead of JSON
}

func showProfile(profile: UserProfile?) {
    ...
}

Trigger a staleness-aware, redundant-request-suppressing load when the view appears:

override func viewWillAppear(_ animated: Bool) {
    MyAPI.resource("/profile").loadIfNeeded()
}

…and you have a networked UI.

Add a loading indicator:

MyAPI.resource("/profile").addObserver(owner: self) {
    [weak self] resource, event in

    self?.activityIndicator.isHidden = !resource.isLoading
}

…or better yet, use Siesta’s prebaked ResourceStatusOverlay view to get an activity indicator, a nicely formatted error message, and a retry button for free:

class ProfileViewController: UIViewController, ResourceObserver {
    @IBOutlet weak var nameLabel, colorLabel: UILabel!

    @IBOutlet weak var statusOverlay: ResourceStatusOverlay!

    override func viewDidLoad() {
        super.viewDidLoad()

        MyAPI.resource("/profile")
            .addObserver(self)
            .addObserver(statusOverlay)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        MyAPI.resource("/profile").loadIfNeeded()
    }

    func resourceChanged(_ resource: Resource, event: ResourceEvent) {
        nameLabel.text  = resource.jsonDict["name"] as? String
        colorLabel.text = resource.jsonDict["favoriteColor"] as? String
    }
}

Note that this example is not toy code. Together with its storyboard, this small class is a fully armed and operational REST-backed user interface.

Your socks still on?

Take a look at AFNetworking’s venerable UIImageView extension for asynchronously loading and caching remote images on demand. Seriously, go skim that code and digest all the cool things it does. Take a few minutes. I’ll wait. I’m a README. I’m not going anywhere.

Got it? Good.

Here’s how you implement the same functionality using Siesta:

class RemoteImageView: UIImageView {
  static var imageCache: Service = Service()
  
  var placeholderImage: UIImage?
  
  var imageURL: URL? {
    get { return imageResource?.url }
    set { imageResource = RemoteImageView.imageCache.resource(absoluteURL: newValue) }
  }
  
  var imageResource: Resource? {
    willSet {
      imageResource?.removeObservers(ownedBy: self)
      imageResource?.cancelLoadIfUnobserved(afterDelay: 0.05)
    }
    
    didSet {
      imageResource?.loadIfNeeded()
      imageResource?.addObserver(owner: self) { [weak self] _,_ in
        self?.image = self?.imageResource?.typedContent(
            ifNone: self?.placeholderImage)
      }
    }
  }
}

A thumbnail of both versions, for your code comparing pleasure:

Code comparison

The same functionality. Yes, really.

(Well, OK, they’re not exactly identical. The Siesta version has more robust caching behavior, and will automatically update an image everywhere it is displayed if it’s refreshed.)

There’s a more featureful version of RemoteImageView already included with Siesta — but the UI freebies aren’t the point. “Less code” isn’t even the point. The point is that Siesta gives you an elegant abstraction that solves problems you actually have, making your code simpler and less brittle.

Comparison With Other Frameworks

Popular REST / networking frameworks have different primary goals:

  • URLSession is Apple’s standard iOS HTTP library (and is all most projects need).
  • Siesta untangles state problems with an observable resource cache.
  • Alamofire provides a Swifty, modern-feeling wrapper for URLSession.
  • Moya wraps Alamofire to hide HTTP URLs and parameters.
  • RestKit couples HTTP with JSON object model Core Data mapping.
  • AFNetworking is a modern-feeling Obj-C wrapper for Apple’s network APIs, plus a suite of related utilities.

Which one is right for your project? It depends on your needs and your tastes.

Siesta has robust functionality, but does not attempt to solve everything. In particular, Moya and RestKit address complementary / alternative concerns, while Alamofire and AFNetworking provide more robust low-level HTTP support. Further complicating a comparison, some frameworks are built on top of others. When you use Moya, for example, you’re also signing up for Alamofire. Siesta uses URLSession by default, but can also stack on top of Alamofire if you want to use its SSL trust management features. Combinations abound.

With all that in mind, here is a capabilities comparison¹:

Siesta Alamofire RestKit Moya AFNetworking URLSession
HTTP requests
Async response callbacks
Observable in-memory cache
Prevents redundant requests
Prevents redundant parsing
Parsing for common formats
Route-based parsing
Content-type-based parsing
File upload/download tasks ~
Object model mapping
Core data integration
Hides HTTP
UI helpers
Primary language Swift Swift Obj-C Swift Obj-C Obj-C
Nontrivial lines of code² 2609 3980 13220 1178 3936 ?
Built on top of any (injectable) URLSession AFNetworking Alamofire NSURLSession / NSURLConnection Apple guts

1. Disclaimer: table compiled by Siesta’s non-omniscient author. Corrections / additions? Please submit a PR.
2. “Trivial” means lines containing only whitespace, comments, parens, semicolons, and braces.

Despite this capabilities list, Siesta is a relatively lean codebase — smaller than Alamofire, and 5.5x lighter than RestKit.

What sets Siesta apart?

It’s not just the features. Siesta solves a different problem than other REST frameworks.

Other frameworks essentially view HTTP as a form of RPC. New information arrives only in responses that are coupled to requests — the return values of asynchronous functions.

Siesta puts the the “ST” back in “REST”, embracing the notion of state transfer as an architectural principle, and decoupling the act of observing state from the act of transferring it.

If that approach sounds appealing, give Siesta a try.


Documentation

Examples

This repo includes a simple example project. To download the example project, install its dependencies, and run it locally:

  1. Install CocoaPods ≥ 1.0 if you haven’t already.
  2. pod try Siesta (Note that there’s no need to download/clone Siesta locally first; this command does that for you.)

Support

To ask for help, please post a question on Stack Overflow and tag it with siesta-swift. (Be sure to include that tag. It triggers a notification to the Siesta core team.) This is preferable to filing an issue because other people may have the same question as you, and Stack Overflow answers are more discoverable than closed issues.

Things that belong on Stack Overflow:

  • “How do I…?”
  • “Is there a way to…?”
  • “Is Siesta appropriate for…?”
  • “I got this error…”

For a bug, feature request, or cool idea, please file a Github issue. Things that belong in Github issues:

  • “When I do x, I expect y but get z
  • “There should be a way to…”
  • “Documentation for x is missing / confusing”

Unsure which to choose? If you’re proposing a change to Siesta, use Github issues. If you’re asking a question that doesn’t change the project, and thus will remain valid even after you get an answer, then use Stack Overflow.

Two big little things

Keep in mind that Siesta is maintained by volunteers. Please be patient if you don’t immediately get an answer to your question; we all have jobs, families, obligations, and lives beyond this project.

Please be excellent to one another and follow our code of conduct.

Comments
  • Update API for Apple’s newly released API design guidelines

    Update API for Apple’s newly released API design guidelines

    I reviewed Siesta’s API against Apple’s new API Design Guidelines for Swift, and identified ~27 names of concern. Of those, I recommend changing  8  14.

    Details of my review, proposed changes, and rationale are in this gist: https://gist.github.com/pcantrell/22a6564ca7d22789315b

    If anybody has opinions about these changes, or notices other places where Siesta’s naming conventions contradict the new guidelines, please comment on this issue.

    API changes will appear as deprecations in beta 6, and the deprecated methods will be removed in the subsequent release.

    opened by pcantrell 23
  • configureTransformer returns double-optional content

    configureTransformer returns double-optional content

    Checking to see if there are any examples or tips on using ObjectMapper for model mapping in Siesta.

    I think something as simple as this should work, where User is a working ObjectMapper Mappable model, and I'm using the SwiftyJSON global transformer from @pcantrell here.

        configureTransformer("/profile/") {
            Mapper<User>.map($0.content as JSON) //error: type of expression is ambiguous without more context
        }
    
    opened by andrewloyola 21
  • Adding OSX target

    Adding OSX target

    Hi,

    This PR is about adding an OSX target. After having looked around and tested various things, I think siesta is one of the best candidates for the app I am preparing. But it's an OSX app. I need an OSX target...

    This PR introduces the OSX target. Apart from all UIKit stuff, there are 0 changes (and I've merged upstream). The problem of course is UIKit's stuff. Fortunately it is fairly easy to workaround, since many many classes share the same APIs between the various platforms.

    For the cases where it is different, I've written a OSX.swift compatibility file where typealiases are defined (they allow to use the same type everywhere, mapping to the correct one depending on platform). And where I've written the little tricks necessary for the iOS siesta code to NOT change. That is, the tricks are here to adapt OSX interfaces to iOS ones, since I guess iOS remains the main ... target. :-)

    I've been able to build an OSX Test target as well. However, given the various dependencies on other thing to build tests, this makes things quite a lot more difficult. In particular, I had to create an OSX target for Nocilla (and change the file Cartfile.private to point to it)

    Anyway, I think the constraint of an OSX target is a good occasion to clearly separate class/code concerns/responsabilities. This PR is created maybe a bit toot early, but I wanted to expose/discuss it before siesta reach 1.0, to raise awareness. I am happy to discuss it for any changes and improvements necessary before merge, of course!

    Thanks anyway for the great project.

    opened by onekiloparsec 20
  • Unable to use 'Alamofire' as a networkprovider

    Unable to use 'Alamofire' as a networkprovider

    I have imported the 'Siesta' library by downloading through github. I want to add 'Alamofire; as a networkprovider. Service.init(baseURL: urlstring, useDefaultTransformers: true, networking: Alamofire.SessionManager ) I am getting error 'use of unresolved identifier 'Alamofire'. Help me to solve this.

    I want to use 'Alamofire' as a network provider for my rest api calls.

    opened by LavanayaV 14
  • ReactiveCocoa Extension

    ReactiveCocoa Extension

    Here is an initial draft for the ReactiveCocoa extension we talked about here. Some quick notes:

    • Resource class was changed to split the request(_:_:) method in two, you can see the detailed explanation in the commit message.
    • Errors in Error class are used but since default memberwise initializers are internal by default, and the ReactiveCocoa extension is not part of the framework, public initializers are added to instantiate them. However maybe that part of the code can be split like the request(_:_:) method in Resource class so that errors aren't accessed directly, but I wanted to check with you before going forward.
    • On a general note about the point above:rac_request methods duplicate the logic in request methods, so maybe request methods should be split for better reuse?
    • allowedCharsInURLEncoding variable is duplicated as well, it is private and the compiler gives an error when it is declared as public, the reason it being both final and dynamic in that case. I wanted to check with you as to how to eliminate this.
    • I opted for a glue object to do the observing and forward a ResourceState object when resourceChanged(_:_:) is called on them.

    Is there any configuration for swiftlint or anything like that for your code conventions? Do you do them manually or do you automate them?

    Needless to say, all feedback is welcome, critic feedback is more welcome :) Especially regarding method and variable names, I opted for quick names like nsreqWith but I'm open to suggestions.

    opened by akaralar 14
  • Possible memory leak in ProgressTracker

    Possible memory leak in ProgressTracker

    Hi,

    Just found a memory leak using Instruments in Siesta. Seems to be related to the timer in ProgressTracker.swift, but not the obvious thing (strong reference from within timer closure).

    Image

    opened by edwardmp 13
  • Error when trying siesta with Argo

    Error when trying siesta with Argo

    Hi Paul,

    I'm diving even deeper into siesta, and I try to make it work with Argo. But I get an error I couldn't work around. That's maybe not an issue, but merely my own failure to grasp all the details involved here, especially with the siesta blocks arguments.

    Here is the code, in my subclass of Service:

        public init(withAPIVersion version: String = "1") {
            self.APIVersion = version
            super.init(baseURL: "http://api.arcsecond.io")
    
            self.configureTransformer("/\(self.APIVersion)/objects/*") {
                decode($0.content) as AstronomicalObject
            }
        }
    

    I get the following at the line self.configureTransformer...:

    Cannot invoke 'configureTransformer' with an argument list of type '(String, (_) -> _)'

    The code for AstronomicalObject follows the exact same example given by Argo, in its simplest form:

    public struct AstronomicalObject {
        public let name: String
    }
    
    public extension AstronomicalObject: Decodable {
        public static func decode(json: JSON) -> Decoded<AstronomicalObject> {
            return curry(AstronomicalObject.init)
                <^> json <| "name"
        }
    }
    

    I don't get this error when writing a "normal" init method for my struct, taking the json as parameter and doing all the parsing myself. But my goal is to use Argo precisely for that.

    Any idea? Thanks in advance!

    opened by onekiloparsec 13
  • Adds support for watchOS and tvOS

    Adds support for watchOS and tvOS

    • Added new targets and schemes
    • Added correct Foundation class mapping for the two new OS
    • Bypasses memory warning logic for watchOS as it is not supported
    opened by victorcotap 12
  • Allow EntityCache to function at any point in the transformer pipeline

    Allow EntityCache to function at any point in the transformer pipeline

    EntityCache currently must store and return only the values at the very end of the transformer pipeline.

    This works well when the end result of the pipeline is an easily serializable type such as text or JSON:

    siesta pipeline 1

    However, it’s problematic when the transform pipeline produces a model, which can be difficult for an EntityCache to store and retrieve:

    siesta pipeline 2

    Attempts to solve this problem by keeping models in a database quickly become problematic:

    • The database needs to be able to look up models by REST URL, which mixes abstraction layers and leads to hackish workarounds.
    • The EntityCache API is not designed to work with databases. (For example, it wants to pass cached entities across threads, which Realm doesn’t like.)

    Suppose, however, that an EntityCache could insert itself at any point in the transformer pipeline and not just the end. In other words, this is currently the only supported structure:

    → JSON transformer → Model transformer → (EntityCache) →
    

    …but suppose the pipeline instead supported this:

    → JSON transformer → (EntityCache) → Model transformer →
    

    When there is a cache hit, the pipeline would pick up immediately after the cache's position in the pipeline. An EntityCache could then work only with its preferred data type:

    siesta pipeline 3

    …or even:

    siesta pipeline 4

    This would require some hard thought in the plumbing, but seems to make sense. @annicaburns, would this solve the problems you were having with EntityCache? Would you still want to use Realm even with a mechanism like this in place?

    opened by pcantrell 12
  • Update for Xcode 9.3/Swift 4.1

    Update for Xcode 9.3/Swift 4.1

    Basically I just did 2 things:

    • Automatic Xcode upgrade of the project
    • Replaced flatMap with compactMap where said map returned optionals

    Note: Travis Build shall fail until it's updated to use Xcode 9.3 image

    opened by joaomvfsantos 11
  • Specify queue on which resourceChanged to be called

    Specify queue on which resourceChanged to be called

    Currently I was not able to find an option to specify on which thread resourceChanged to be received. Such option would allow more flexibility when dealing with big responses.

    opened by richardtop 10
  • Add Combine support and RxSwift extension

    Add Combine support and RxSwift extension

    Hi Paul,

    Here's support for Combine and RxSwift as we talked about. Combine is in the main library code; RxSwift is in Extensions.

    It's influenced somewhat by the ReactiveCocoa extension and the talk around that.

    As ever, there's more than one way to skin any particular cat, and perhaps especially so in RxSwift. But I've been fairly conservative - nothing too outrageous here.

    Feedback entirely welcome of course.

    Adrian

    opened by luxmentis 14
  • [WIP] @ResourceBacked property wrapper

    [WIP] @ResourceBacked property wrapper

    A common idiom in Siesta projects is to have UI code point at some resource that can change, and whenever it changes, to:

    • stop observing the old resource,
    • add one or more observers to the new resource (the same observers every time), and
    • load if needed.

    The Siesta docs and the example project recommend doing this via didSet:

    var doodadsResource: Resource? {
        didSet {
            oldValue?.removeObservers(ownedBy: self)
    
            doodadsResource?
                .addObserver(self)
                .addObserver(statusOverlay, owner: self)
                .loadIfNeeded()
        }
    }
    
    var doodads: [Doodad] {  // convenience accessor
        return doodadsResource?.typedContent() ?? []
    }
    

    Swift 5.2’s property wrappers give us a better option. This PR adds a @ResourceBacked property wrapper that lets any variable take its value from a Siesta resource.

    The example above becomes:

    @ResourceBacked(default: [])
    var doodads: [Doodad]
    
    // during initialization, e.g. in viewDidLoad() or some such:
    $doodads.addObserver(self)
    $doodads.addObserver(statusOverlay)
    

    The doodads variable now behaves as if it is a read-only Doodad array; for example, we can do this:

    for doodad in doodads {  // just works
        print(doodad.name)
    }
    

    However, that array comes from a Siesta resource — and we can switch which resource on the fly:

    $doodads.resource = api.resource(“foo”).child(newDoodadID)
    

    Changing the resource in this way automatically:

    • removes our little flock of observers from the old resource (if any),
    • adds our flock of observers to the new resource (if any),
    • sends the appropriate events to the observers so they show the change immediately, and
    • triggers a call to loadIfNeeded().

    Future work on this feature

    • [ ] The wrapper should detect whether the resource’s value does not match the variable’s type, and report this as an error via $doodads.error. This would give better error reporting to the user if the server returns well-formed but unexpected content. (If you ask for $doodads.resource?.latestError, you still get only underlying resource errors, since resources (at least in Siesta 1.0) have freely typed content.)
    • [ ] Property wrapper should wrap response to observers to reflect the above
    • [ ] Clients should be able to opt out of automatic loadIfNeeded
    • [ ] Any facilities necessary for doing custom requests?
    • [ ] Make sure it plays nice with SwiftUI
    opened by pcantrell 0
  • File cache

    File cache

    This PR adds a file-based cache implementation to Siesta. This will give most projects offline access & fast launch for almost free.

    A word on why this is so compelling for Siesta: traditional HTTP caches (such as URLSession’s cache) exist to prevent requests for data that is still fresh (enough). This makes them good for reducing network traffic, but bad for offline access: it’s a strict choice between getting the cached data or the fresh network data. Worse yet, the API gets to make that choice for you based on (usually ill-behaved) HTTP headers!

    Siesta’s architecture, however, makes it possible for a Resource to simultaneously have data and be in the midst of requesting data. This makes it possible for your app to launch with the last data it last had — no matter how old, you decide whether you want to show it — and show that stored data even as it is requesting fresh data, even if that request fails.

    This all happens fairly transparently for Siesta apps. Called loadIfNeeded and you’ll get a newData(cache) event when the cached data arrives, then a newData(network) event if the load request succeeds. All you have to do is build your UI so that loading and network errors don’t completely obscure the UI, and bingo! offline access.

    There is still documentation work and cleanup to do here, but the code on this branch should be ready to use in your project! I encourage Siesta users to try it and report back. Please give it a whirl! 🙏

    To try it out:

    service.configure {
        $0.pipeline[.rawData].cacheUsing {
            try FileCache<Data>(
                poolName: “some locally unique name for your API",
                dataIsolation: .perUser(identifiedBy: someUserSpecificValue))
        }
    }
    

    …or if you are using public data that can be shared across users of the app:

                dataIsolation: .sharedByAllUsers
    

    This PR also fixes numerous subtle problems with the existing cache infrastructure. It’s long been possible roll your own persistent caching for Siesta, but it always involved a bit of per-project finagling. Improvements here should make custom caches both easier to write and easier to work with — most notably, caches now only apply to GET requests and do not apply to cross-resource requests with load(using:). These two gotchas were a common source of trouble with custom cache implementations.

    Fixes #289. Fixes #291.

    opened by pcantrell 2
  • 404 errors from a resource don't clear as expected from a resource(

    404 errors from a resource don't clear as expected from a resource("static url").load()

      My app needs to monitor the network connection to an API. After enough errors accumulate, It stops making normal requests and lazily pings the API with a static URL as follows:
    
     let userRequest = VAPI.sharedInstance.resource("").load(). // Base url is a health check for the api.
    

    When an adequate number of successful pings has occurred, the app goes back to normal operation. During testing I can inject errors into the API response and clear them as needed. For every error except 404, the system works as expected. With 404, the ping keeps getting 404 responses from the load() even after the network response has gone back to a normal 200.

    As the error clears the load() returns 1 good response and then resumes returning 404. Using URLSession I get a 200 for the success. With Alamofire, the success is a 304. A parallel direct URLSession request as follows:

    // Test code let url = URL.init(string: VAPI.VAPIBaseURL) let dataTask = self.defaultSession.dataTask(with: url!) { [weak self] data, response, error in // 5 if error != nil { print(error?.localizedDescription) } else if let data = data, let response = response as? HTTPURLResponse { print("URLSession Response =====> ", response.statusCode) } }

            dataTask.resume()
    

    Behaves as expected. I've attached a log file of the divergent responses.

    404 Clearing Log.docx

    opened by tjmorgan0 0
  • Chained request progress support

    Chained request progress support

    Chained requests currently do not support progress. If you are reading these words and want that feature, please file an issue on Github!

    It happened! How big of a deal is this?

    opened by karlshea 0
Releases(1.5.2)
  • 1.5.2(Nov 19, 2020)

  • 1.5.1(Apr 10, 2020)

  • 1.5.0(Mar 31, 2020)

    Enhacements

    • Siesta now supports Swift Package Manager. Thanks, @karlshea! (#301, #304)
      • Note that because SwiftPM does not yet support dependency-provided resources, you will need to manually copy ResourceStatusOverlay.xib into your own project if you plan to use ResourceStatusOverlay’s default UI.
    • Long an unofficial DIY option, Siesta now officially supports tvOS. Thanks, @omidontop! (#28, #293)
    • The new Resource.withParams() method lets you add many query parameters at once. (#294)
    • The Alamofire extension now supports Alamofire 5 (#303)
    • The test suite no longer uses Nocilla. This is not a user-facing enhancement, but believe me, if you are a project maintainer, you’re very happy about this. 😎🥳 (#302)

    Fixes

    • Build issues with recent Xcode / Swift versions fixed

    Breaking Changes

    • Siesta now requires Swift 5. (#296)
    • The Alamofire extension not only supports but requires Alamofire 5 (#303). Projects still using AF 4 can find the old extension in Extensions/Alamofire-4.
    Source code(tar.gz)
    Source code(zip)
  • 1.4.3(Mar 19, 2019)

    Fixed

    • Fixed a typo in a conditionally compiled code that could cause build failure on Swift 4.2
    • cancelLoadIfUnobserved(afterDelay:) now properly pays attention to its argument. Thanks, @acecilia! (#279)

    Enhacements

    • Internal cleanup and testing improvements
    • Added SwiftLint to test build

    Breaking Changes

    • Siesta now requires Swift 4.2
    Source code(tar.gz)
    Source code(zip)
  • 1.4.2(Sep 23, 2018)

    Fixes

    • Siesta now compiles with Swift 4.2 / Xcode 10. It still compiles with Swift 4.1 as well. Thanks to all who flagged this. (#274, #277)

    Important note: An issue in CocoaPods may prevent Siesta (and other pods) from building correctly in XCode 10 for some configurations. If your pod build fails with EXPANDED_CODE_SIGN_IDENTITY: unbound variable, install the CocoaPods 1.6 beta using gem install cocoapods --pre. More info here.

    Source code(tar.gz)
    Source code(zip)
  • 1.4.1(Aug 29, 2018)

    Fixes

    • Fixed a memory leak, and added a leak check to specs. Thanks to @edwardmp for uncovering this! (#268, #270)
    • Updated Swift Package Manager support for 4.1. Thanks, @Hugal31! (#269)
    Source code(tar.gz)
    Source code(zip)
  • 1.4.0(Jun 26, 2018)

    Enhancements

    • The new RequestDelegate API makes it much simpler to create custom Requests. This is useful for add third-party auth libraries and adding non-network behavior (e.g. a pause) to request chains. (#254, #152)
    • The newly tidied logging API adds conveniences for predefined Siesta category sets, and cleans up the global namespace. (#256)

    Fixes

    • All warnings fixed for Swift 4.1 / Xcode 9.4. Thanks, @joaomvfsantos and @wildthink! (#244, #250, #242, #257)
    • There is no longer a race condition between the persistent cache and initial calls to loadIfNeeded(). (#237, #255)
    • ResourceImageView now returns a nil resource after the URL is set to nil. (#249, #259)
    • Overrides for Content-Type in configuration ad request mutations now follow a well-defined order of precedence, and do not cause duplicate headers. Thanks, @massdonati! (#246, #247)

    Breaking Changes

    None.

    Source code(tar.gz)
    Source code(zip)
  • 1.3.1(Nov 19, 2017)

  • 1.2.2(Nov 19, 2017)

  • 1.3.0(Sep 18, 2017)

    Enhancements

    • Swift 4 support is here! If you want to stick with Swift 3 for now, use version 1.2.x or the swift-3 branch.
    • Swift 4’s Codable is the new, better way to handle JSON — and Siesta supports it nicely. See it in action in the example project.
    • To better support Codable, Siesta now provides a convenient way to disable its default JSON → Dictionary parsing while still preserving the built-in text and image parsing. (It was an all-or-nothing proposition before.) See https://github.com/bustoutsolutions/siesta/pull/214 for details.
    • For those not jumping to Codable just yet, the SwiftyJSON support that used to be in the example project now lives in Extensions/.
    • The example app now includes live in-app commentary on what Siesta is doing and why it’s interesting, making pod try a much more edifying experience.

    Breaking Changes

    None.

    Source code(tar.gz)
    Source code(zip)
  • 1.2.1(Sep 8, 2017)

    Fixes

    • Resource.withParam(…) no longer strips existing parameters whose value is blank. Thanks to @ligal for catching this one. (#222→#223)
    • RemoteImageView.placeholderImage was incorrectly marked as an @IBOutlet, which served no useful purpose. It is now correctly marked as @IBInspectable, which makes it possible to choose a placeholder image from the storyboard editor. Thanks to @aoge123 for pointing this out. (#220→#224)
    • Configuration patterns now correctly match : as part of a URL path segment, per the HTTP spec. Thanks to @akaralar for discovering this one. (#212→#221)
    • Assorted small typos fixed in the docs. Thanks, @brucer42. (#218)

    Breaking Changes

    None.

    Special Exciting Bonus Reminder

    A preview of Swift 4 support is available on the swift-4 branch. Please kick the tires and report any issues!

    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(Aug 7, 2017)

    Enhancements

    • Added support for watchOS and tvOS. Thanks, @victorcotap! (#187)
    • Configurable request mutations allow headers that are computed from the request body, or otherwise change with every request. Thanks, @SilverTab, for the use case. (#209, #206)
    • You can now manually trigger Siesta’s unused resource cleanup. Thanks, @jordanpwood, for the use case. (#179, #193)
    • Siesta now supports HEAD and OPTIONS requests. (#200, #208)

    Fixes

    • SiestaUI and Alamofire submodules no longer generate spurious compiler warnings when built with CocoaPods. (#195)
    • The README’s table of contents suffered from a Banner-Blindness-like invisibility. It now says “Table of Contents.” I mention this in the release notes only so I can publicly thank @zadr for pointing it out.

    Breaking Changes

    None.

    Special Exciting Bonus

    A preview of Swift 4 support is available on the swift-4 branch. Kick the tires! Check out the example project on that branch for an example of using Swift 4’s JSON coding with Siesta.

    Source code(tar.gz)
    Source code(zip)
  • 1.1.1(Mar 28, 2017)

  • 1.1.0(Feb 8, 2017)

    Enhancements

    • RemoteImageView now has a customizable per-view transform. Thanks @Alex293! (#131, #158)
    • ResourceStatusOverlay is now accessible from the outside to allow translation & customization. Thanks again, @Alex293. (#155, #158)
    • Siesta is now labeled “app extension safe.” Thanks, @leoMehlig! (#162)

    Fixes

    • Workaround for a bug in Alamofire that could cause duplicate Alamofire.DidResume notifications. Thanks to @piv199 for tracking down this deeply buried one. (#163, #167)
    • Fixed a bug that would cause ResourceStatusOverlay never to update when attached to a resource via Objective-C. (#173)
    • Siesta’s podspec now properly declares its dependency on Alamofire ≥ 4.1, not just 4.0.

    Breaking Changes

    None.

    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Nov 18, 2016)

  • 1.0.0(Nov 16, 2016)

    This is the official 1.0 release of Siesta.

    Please spread the word. You shares, stars, endorsements, and suggestions help us make Siesta better.

    Please let us know what you’re building. Hearing how Siesta is helping software teams succeed makes all the hard work worth it.

    Migrating to 1.0

    This release removes everything that was deprecated before 1.0.

    If you hit compile errors when you upgrade to this release, trying using the pre-1.0-deprecations tag first. That release will give you warnings and suggested renames that will help you migrate to 1.0.0.

    Enhancements

    • ResourceStatusOverlay now follows Swift 3 API conventions. (#143, #145)
    • Modest enhancements and refinements to the example project (#144)
    Source code(tar.gz)
    Source code(zip)
  • 1.0-rc.3(Nov 8, 2016)

    Enhancements

    • New SiestaUI helper lets resources automatically control the iOS network activity indicator in the status bar. Thanks to @Reedyuk for seeing this one through! (#132)
    • Miscellaneous internal tightening and cleanup. Yes, this release actually has less code than the previous one. (#125, #135, #139, #140)

    Fixes

    • Calling repeated() on a chained request now repeats the original request, not just the remainder of the chain. (#134)
    • Fixed numerous outdated examples and links in the docs. (#127, #136)

    Breaking Changes

    • Thanks to Swift 3, several Error.Cause members now use stronger types to report error details instead of just strings. (#138)
    • Also thanks to Swift 3, in the Obj-C API BOSEntity.content is now non-nullable just like its Swift counterpart Entity.content. (#126)
    Source code(tar.gz)
    Source code(zip)
  • 1.0-rc.2(Oct 7, 2016)

    Fixes

    • Workaround for Swift bug that sometimes caused self-owned observers to be prematurely deallocated. The workaround comes with a performance hit. Thanks to @kl for discovering this & vetting the fix. (#120, #121)

      Please vote for the underlying Swift bug if you want that performance back!

    • Siesta would sometimes not call ResourceObserver.stoppedObserving(resource:) when it should have. It now consistently calls it except in situations where it would be impossible to do so. (#122)

    Source code(tar.gz)
    Source code(zip)
  • 1.0-rc.1(Oct 2, 2016)

    Enhancements

    • Substantial performance improvements. (#117 ← includes timings)
    • Log output is now vastly more readable: better formatted, less redundant, and more focused on information that helps debug the most common problems. (#116)
    • Siesta now defers resource configuration & cache read until you actually use a resource’s data or attach an observer. This reduces overhead & log clutter when traversing resources using child(…), withParam(…), etc. (#115)
    • Resources created with nil or malformed URLs no longer generate confusing errors from the network layer; instead, a new InvalidURL error cause makes them easy to spot & diagnose. Code such as RemoteImageView that intentionally creates nil URL resources no longer generates mounds of confusing output.

    Fixes

    • The podspec incorrectly reported that Siesta requires iOS 9. This is now corrected: iOS 8 normally, iOS 9 only if you are using Alamofire. Thanks to @jordanpwood for spotting this. (#111)
    • Fixed: Objective-C observers prematurely deallocated if they are not retained outside of Siesta. (#118)
    • Fixed: Objective-C observers to sometimes do not receive stoppedObservingResource: (#118)

    Breaking Changes

    • The isEquivalentTo(…) method of ResourceObserver is superseded by observerIdentity. This is a little-known feature, but search your code for it! It is no longer part of the protocol, and you will not receive a deprecation warning if you are attempting to implement it. Instead, you’ll just start getting duplicate observers.
    • As a part of the optimizations in #117, the timing of calls to stoppedObserving(…) has changed. While the order of events reported by a Resource is still consistent — observer add & remove notifications still come in the order the observers were actually added & removed — some of those notifications are now deferred.
    Source code(tar.gz)
    Source code(zip)
  • 1.0-rc.0(Sep 17, 2016)

    Enhancements

    This release moves Siesta to Swift 3. The future is here! The flying cars are no doubt imminent.

    If your project needs to stick with Swift 2, use the swift-2.2 or swift-2.3 branch.

    Breaking Changes

    Siesta’s API has been renamed to adhere to the new Swift 3 naming guidelines (mostly, moderated by taste). You’re mostly likely to notice the lowercase enums and slight changes to parameter labels.

    Siesta now also takes advantage of new language improvements. Gone is $0.config, which was a hack to work around shortcomings in Swift 2’s inout inference. You can now just use $0 in your configuration closures. Hooray!

    For most of the renamings, you’ll see nice friendly deprecations with fixits — or at least helpful error messages. However, there are a few things the compiler will not help you with that you need to be careful of:

    • Three methods of ResourceObserver with default implementations have new names to fit the new naming guidelines. Because they have default implementations, the Swift compiler will not give you any warning if you try to implement them using the old names; they will simply never be called.

      You must search your code yourself for these old methods:

      func resourceRequestProgress(resource: Resource, progress: Double)
      func stoppedObservingResource(resource: Resource)
      func isEquivalentToObserver(other: ResourceObserver) -> Bool
      

      …and replace them with these new ones:

      func resourceRequestProgress(for resource: Resource, progress: Double)
      func stoppedObserving(resource: Resource)
      func isEquivalentTo(observer other: ResourceObserver) -> Bool
      
    • To prevent a name clash, Siesta’s Error is now called RequestError. Most Siesta apps never reference this type directly. However, if yours does, it will now point at Swift’s internal Error instead of Siesta’s, which will cause confusing error messages.

    • Entity is now a generic type, Entity<T>. You can safely change Entity to Entity<Any> to capture the old behavior. That includes your EntityCache implementation.

    Known Issues

    • You will get compiler warnings about how “Expression of type 'Request?' is unused.” This is due to a bug in Swift which is apparently already fixed, but the fix is not yet in an official release. If the warnings bother you, you can eliminate them be prefixing the offending statements with _ =; otherwise just wait for the next Swift release.

    Since this is the first release for Swift 3, it’s likely that there will be some bumps in the road. Please file issues and send pull requests for any breakages, broken doc links, or outdated sample code you find. And if things are working for you, please tweet to us at @siestaframework and let us know the nifty things you’re building!

    Source code(tar.gz)
    Source code(zip)
  • 1.0-beta.10(Aug 28, 2016)

    This release includes the last planned API changes for Swift 2.x. Barring the discovery of serious API design flaws, Swift 2 work from now on will be bug fixes only.

    A preview of Swift 3 compatibility is now available on the swift3 branch. Grab that beta and hop on the ride! A wild oscillation between delight and apoplexy awaits. See the release plans for goals & timeline, and subscribe to #103 for status updates.

    Enhancements

    • Request decorators, chains, and repeats: it is now possible to configure serivce-wide request behaviors such as automatic token renewal. See the new examples in the user guide. (#98, #104)
    • Improved content transformer type mismatch behavior. (#100)
    • UI helpers are in a separate module; directories are reorganized in anticipation of SwiftPM support. (#102)
    • Entity.headers is now public. (#107)

    Fixes

    • Updated and expanded user guide. The new host whitelisting section is of particular note.
    • Fixed minor API doc breakage. (#92)

    Breaking Changes

    • The UI helpers, ResourceStatusOverlay and RemoteImageView, are now separate from the Siesta core API:
      • If you are using Carthage or building the framework directly from the Xcode project, they are now in a separate SiestaUI framework. You will need to include that framework separately in your project, and add import SiestaUI in your code.
      • If you are using Cocoapods, the UI helpers are in a separate subspec. You will need to add pod 'Siesta/UI' to your Podfile. However, due to limitations of Cocoapods, you will still import Siesta for UI helpers and core API alike.
    • Request.onCompletion now takes a ResponeInfo struct instead of just a Response. Where your existing onCompletion hook uses $0, replace it with $0.response.
    • The skipWhenEntityMatchesOutputType: option is gone, without an exact replacement. See #100.
    Source code(tar.gz)
    Source code(zip)
  • 1.0-beta.9(Aug 15, 2016)

    Enhancements

    • Big changes to EntityCache, which should open the door to much more creative and interesting persistent local mirroring of API data. Thanks to @jordanpwood for helping think through this tricky work. (Extensive writeup in #95; see also #89, #90)
      • Caches are now responsible for generating their own keys, which are opaque to Siesta and can be of an arbitrary type.
      • Caches can now specify the GCD queue on which they work (including the main queue).
    • Experimental ReactiveCocoa integration now in Extensions/ReactiveCocoa. Kick the tires and send feedback. Thanks to @akaralar for coding this and seeing it through! (#71)
    • Service methods with baseURL and absoluteURL parameters all now accept both String and NSURL. Good idea, @jordanpwood. (#74, #77)
    • Added Service.resource(baseURL:path:) to better support APIs without a clear single baseURL. Thanks to @Reedyuk and @nikolay-dementiev for the use cases. (#94, #91, #84)
    • Improved example code in the GithubBrowser example project (#76)

    Fixes

    • ResourceStatusOverlay now correctly updates its state when it stops observing a resource. (#75)
    • ResourceStatusOverlay can now be wired up to custom views in a storyboard. (See Breaking Changes below.) (#85, #4)
    • Resource.withParam(…) now correctly escapes + in query strings. Thanks, @vvondra, for finding & fixing this. (#97, #96)

    Breaking Changes

    • The requirements of the EntityCache protocol have changed, and several defunct helper types have gone away. See #95 for migration instructions.
    • PipelineStage now has write-only cacheUsing(_:) and doNotCache() methods instead of a cache property.
    • The Objective-C name of ResourceStatusOverlay no longer has a BOS prefix. Storyboards have trouble working with classes whose Swift and Objective-C names are different. This is apparently an Apple bug; dropping the prefix is a workaround.
    Source code(tar.gz)
    Source code(zip)
  • 1.0-beta.8a(Jul 25, 2016)

  • 1.0-beta.8(Jul 20, 2016)

    Enhancements

    • The new pipeline API solves several long-standing configuration limitations, and makes service setup code more readable. Thanks to @annicaburns, @alecgorge, @VDKA and for the input. (Changes: #64, #70; Motivation: #32, #47)
    • Check out the shiny, newly expanded and edited user guide. Now with 32% more useful information!

    Fixes

    • Fixed issue building for macOS with CocoaPods. Thanks again to @onekiloparsec for driving the macOS work.
    • Cleaned up defunct file in project. Thanks, @Alex293. (#66)
    • Humorous typo removed, with some regret. Thanks, @sahandnayebaziz. (#65)

    Breaking Changes

    • Service.configureTransformer(...) now replaces any transformers for the model stage with the new one instead of appending it to the end of the entire pipeline. This means that if multiple configuration blocks for the same resource call configureTransformer(...), the last one wins. This better matches typical user needs; if you want the old behavior, pass replaceExisting: false.
    • ResponseContentTransformer no longer skips the transform when the input type already matches the output type. (For example, if the transformer returned a string but there was already a string from upstream in the pipeline, it wouldn’t run.) This behavior is useful but confusing, and shouldn’t be the default. You can enable it with skipWhenEntityMatchesOutputType: true.
    • The EntityCache protocol has changed. You will need to update your custom cache implementation to accept byte keys instead of string keys.
    Source code(tar.gz)
    Source code(zip)
  • 1.0-beta.7(Jun 13, 2016)

    Enhancements

    • Siesta now supports ~~OS X~~ macOS. Core functionality all works; UI widgets are still iOS-only. Thanks to the indefatigable @onekiloparsec for seeing this through! (#27, #56)
    • Configuration can now distinguish between different HTTP methods. This allows, for example, different model mappings for GET and POST responses. (#54)
    • Configuration pattern matching now supports ? to match single characters. This makes it easier to distinguish /items/ (with a trailing slash) from /items/1. (#55)
    • You can now pass NSRegularExpression as a pattern to Service.configure(…) methods. (#47)
    • It is now possible to create custom pre-request validation failures via Resource.failedRequest(…). This allows custom pre-validation of requests before they touch the network. Thanks, @VDKA! (#44, #50)
    • You can now limit the number of unused resources Siesta will keep in its internal cache. (#61, #31)
    • Added @warn_unused_result and @noescape where appropriate throughout the API.
    • The code GithubBrowser example project is now a bit tidier & a better Siesta example to work from.
    • Example project now uses CocoaPods instead of Carthage, and works with pod try. (#58)

    Fixes

    • Fixed #35: nil-failable blocks passed to configureTransformer no longer return double optionals.
    • Fixed #52: JSON-like content containing non-JSON data no longer causes detailed logging to crash.
    • Fixed: When a resource’s last extenernal owner was deallocated, it wasn’t deallocated until a second low memory event. It’s now deallocated on the first.
    • Fixed Swift 2.2 deprecations.

    Breaking Changes

    • The flavor of Service.configure(...) that takes a predicate closure now requires a whenURLMatches: argument label:

      // Before
      service().configure({ $0.path.hasSuffix("foo") }) { ... }
      // After
      service().configure(whenURLMatches: { $0.path.hasSuffix("foo") })  { ... }
      

      It was not possible to add a deprecation warning for this change because the deprecated form causes an ambiguous method overloading.

    • Because it only concerned calls bridged from Objective-C, Error.Cause.InvalidRequestMethod has moved out of the public Swift API and into the Objective-C bridging API.

    • API elements deprecated in 1.0 beta 6 have now been removed.

    Source code(tar.gz)
    Source code(zip)
  • 1.0-beta.6(Jan 11, 2016)

    As with all 1.0 beta releases of Siesta, this code is suitable for production use, but is marked “beta” in order to reserve the right to make API adjustments before the official 1.0 release.

    • Prompted by the upcoming 1.0 API freeze and the release of Apple’s new guidelines for Swift APIs, we undertook a complete review of naming choices in Siesta’s API. These will show up as deprecations in your Swift code; the deprecated methods will be removed in the next release. For details, see:

      Unfortunately, the Objective-C migration path is not so smooth: because Xcode does not properly copy Swift deprecations to Obj-C header files, the methods that are deprecated in Swift will either silently continue to work from Obj-C code in some cases, and immediately break in others.

    • Methods that should only be called on the main thread now validate this as a precondition.

    • Methods are now marked with @warn_unused_result whenever appropriate.

    • The user guide has a new section on threading, and there are numerous improvements to the API docs.

    • The internals of Request and friends, which had become monolithic and unwieldy, are now broken into several small pieces. (There are no API changes associated with this refactoring.)

    Source code(tar.gz)
    Source code(zip)
  • 1.0-beta.5(Dec 11, 2015)

    As with all 1.0 beta releases of Siesta, this code is suitable for production use, but is marked “beta” in order to reserve the right to make API adjustments before the official 1.0 release.

    • ephemeralSessionConfiguration is now the default for Service instances that use NSURLSession. This is the more secure choice, and thus the better default; it also is more likely to give the desired behavior for 304s.
    • ResourceStatusOverlay improvements:
      • Customizable display priority logic (#10)
      • Positioning bug fixes
      • API docs. Wheee!
    • Fixed bug when working with ResourceEvent.NewData(.Wipe) from Objective-C

    Breaking Changes

    • Because of ongoing build issues encountered by several users when using Siesta without the optional Alamofire integration, the Alamofire integration is now in a separate Extensions directory, and is not included in Siesta.framework. You will need to add that source file manually if you want to use the Alamofire integration when including Siesta via Carthage, the binary release, or a git submodule. (CocoaPods users are unaffected by this change.)

    API Changes Coming

    Beta 6 will include API changes to bring Siesta into better conformance with Apple’s new Swift API guidelines. Please review the proposed changes and give your feedback.

    Source code(tar.gz)
    Source code(zip)
    Siesta.framework.zip(7.15 MB)
  • 1.0-beta.4(Nov 16, 2015)

    • Alamofire is now truly optional when using Siesta as a .framework, thanks to Apple (apparently?) fixing problems with optional framework dependencies:
      • If you have not explicitly configure your Siesta Service to use Alamofire and you are using a binary version of Siesta, you can remove it from your Cartfile.
      • If you are building Siesta from source (via Carthage or via Xcode), you still need Alamofire (for the build only).
      • If you are using Alamofire with Carthage, you must include it in your Cartfile yourself.
      • If you are using Cocoapods, continue to use pod 'Siesta/Alamofire' to include Alamofire support.
    • Fixed: Configuration patterns match whole string instead of substring (e.g. http://foo.com/** no longer matches http://bar.com/http://foo.com/)
    • Fixed: Configuration patterns cause crash when Service.baseURL is nil
    • Fixed: Invalid request methods and unencodable JSON passed to the Objective-C API now cause request failures instead of crashes
    • Code cleanup and refinement (There are now only two forced unwraps in the entire library)
    • Clarifications & corrections throughout docs
    Source code(tar.gz)
    Source code(zip)
    Siesta.framework.zip(7.10 MB)
  • 1.0-beta.3(Oct 28, 2015)

    • It is now much easier to attach ad hoc content transformation to resources. Use this to inflate models just once, instead of once per observer:

        myService.configureTransformer("/widgets/*") { Widget(json: $0.content) }
      

      See Service.configureTransformer(…) and ResponseContentTransformer for more info. Big thanks to @radex for helping think this through!

    • Cleaned up error handling:

      • Siesta now uses publishes programmatically useful values in Error.cause.
      • Siesta no longer narrows any errors to NSError in any of its APIs or internal processing.
      • Siesta.Error now implements ErrorType, so you can throw it.
      • All userMessage values generated by Siesta are now localizable.
      • Error.isCancellation removed favor of new error causes (i.e. error.cause is Error.Cause.RequestCancelled).
    • New ConfigurationPatternConvertible lets Service.wipeResources(…) do glob-based path matching, and lets you write your own matching mechanisms for configure(…) and wipeResources(…).

    • Removed deprecated CFURLCreateStringByAddingPercentEscapes call. Thanks @paddlefish!

    • Siesta now gives empty NSData content instead of a request error when the network layer returns a nil response body.

    • Fixed: crash when trying to URL-encode strings with unpaired UTF-16 surrogate chars.

    • Fixed: crash when trying to use entity content with struct type from Obj-C. (It now shows up as nil.)

    • Fixed: leaking low memory event observer blocks.

    • Improved GithubBrowser example project.

    Source code(tar.gz)
    Source code(zip)
    Siesta.framework.zip(4.05 MB)
  • 1.0-beta.2(Oct 5, 2015)

    • Awesome progress reporting!
      • Integrates upload, download, and latency into one beautiful number
      • Gracefully handles unknown body sizes — even when they suddenly become known
      • Makes your app feel faster and your users feel at one with the universe
    • Logging improvements: better JSON formatting when dumps enabled, more readable messages
    • Entity.content now Any instead of AnyObject
    • Siesta.Error now implements ErrorType
    • contentAsType default value is now @autoclosure
    Source code(tar.gz)
    Source code(zip)
    Siesta.framework.zip(4.11 MB)
Owner
Bust Out
We build web and mobile apps
Bust Out
FreeRDP is a free remote desktop protocol library and clients

FreeRDP: A Remote Desktop Protocol Implementation FreeRDP is a free implementation of the Remote Desktop Protocol (RDP), released under the Apache lic

null 7.8k Jan 8, 2023
TheraForge's Client REST API framework to connect to TheraForge's secure CloudBox Backend-as-a-Service (BaaS)

OTFCloudClientAPI TheraForge's Client REST API Framework to Connect to TheraForg

TheraForge 0 Dec 23, 2021
Lightweight REST library for iOS and watchOS. Available on cococapods

RMHttp RMHttp is a Lightweight REST library for iOS and watchOS. Features Chainable Request URL / JSON Parameter Encoding HTTP Methods GET/POST/DELETE

Roger Molas 7 Nov 19, 2022
Swift/Obj-C HTTP framework with a focus on REST and JSON

Now Archived and Forked PMHTTP will not be maintained in this repository going forward. Please use, create issues on, and make PRs to the fork of PHMT

Postmates Inc. 509 Sep 4, 2022
Lightweight REST and JSON library for Swift.

RestEssentials is an extremely lightweight REST and JSON library for Swift and can be used on iOS, iPadOS, macOS, tvOS, and watchOS. Features Easily p

null 37 Nov 2, 2022
Simple REST Client based on RxSwift and Alamofire.

RxRestClient Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements iOS 10.0+ tvOS 10.

STDev 16 Nov 19, 2022
Simple REST Client based on RxSwift and Alamofire.

RxRestClient Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements iOS 10.0+ tvOS 10.

STDev 16 Nov 19, 2022
Write clean, concise and declarative network code relying on URLSession, with the power of RxSwift. Inspired by Retrofit.

ReactiveAPI Reactive API library allows you to write clean, concise and declarative network code, with the power of RxSwift and URLSession! iOS Demo A

Sky UK Ltd 79 Nov 19, 2022
APIProvider - API Provider Package for easier API management inspired by abstraction

APIProvider Using APIProvider you can easily communicate with all API endpoints

null 1 Apr 21, 2022
macOS VM for Apple Silicon using Virtualization API

MacVM macOS Monterey added support for virtualizing macOS with Apple silicon host. This project provides an example project for the setup. Currently o

Khaos Tian 1.2k Jan 4, 2023
EasyImplementationAlamoFire - An iOS project to demonstrate the usage of Alamofire in an efficient and organised way.

EasyImplementationAlamoFire Tutorial to demonstrate an efficient way of handling the APIs structure for your iOS Applications. Prerequisites Swift 5 X

null 0 Jan 3, 2022
This package is meant to make http request of an easy way inspiren in the architecture of Moya package

NetworkAgent This package is meant to make http request of an easy way inspiren in the architecture of Moya package. This package is 100% free of depe

Angel Rada 19 Sep 8, 2022
The easy way to use sockets on Apple platforms

SwiftSocket SwiftSocket library provides as easy to use interface for socket based connections on server or client side. Supports both TCP and UDP soc

null 1.6k Dec 21, 2022
Music Room: a mobile app that offers a new way of experiencing music

?? Music Room - 42 School Project ?? ???? Music Room is a mobile app that offers

Marie-Lise Picard 3 Feb 18, 2022
Real-time Apps the SwiftUI way

Sync Sync is a proof of concept for expanding on the Magic of ObservableObject, and making it work over the network. This let's you create real-time A

Mathias Quintero 138 Dec 14, 2022
Deal with query items, HTTP headers, request body and more in an easy, declarative way

Reusable system for complex URL requests with Swift. Deal with query items, HTTP headers, request body and more in an easy, declarative way. Check out our engineering blog to learn more!

Parable Health 19 Sep 5, 2022
Approov Integration Examples 0 Jan 26, 2022
🌸 Powerful Codable API requests builder and manager for iOS.

This lib is about network requests with blackjack, roulette and craps! Using it you will be able to convert your massive API layer code into an awesom

CodyFire 251 Jan 8, 2023
An iOS library to route API paths to objects on client side with request, mapping, routing and auth layers

WANetworkRouting Developed and Maintained by ipodishima Founder & CTO at Wasappli Inc. Sponsored by Wisembly A routing library to fetch objects from a

null 10 Nov 20, 2022