All Projects → radianttap → Alley

radianttap / Alley

Licence: mit
Essential `URLSessionDataTask` micro-wrapper for communication with HTTP(S) web services, with built-in automatic request retries.

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Alley

Fire
🔥A delightful HTTP/HTTPS networking framework for iOS/macOS/watchOS/tvOS platforms written in Swift.
Stars: ✭ 243 (+77.37%)
Mutual labels:  networking, tvos, watchos
Wwdc
You don't have the time to watch all the WWDC session videos yourself? No problem me and many contributors extracted the gist for you 🥳
Stars: ✭ 2,561 (+1769.34%)
Mutual labels:  networking, tvos, watchos
Cloudkitgdpr
Framework for allowing users to manage data stored in iCloud
Stars: ✭ 126 (-8.03%)
Mutual labels:  tvos, watchos
Diff
Simple diff library in pure Swift
Stars: ✭ 110 (-19.71%)
Mutual labels:  tvos, watchos
Mapbox Directions Swift
Traffic-aware directions and map matching in Swift on iOS, macOS, tvOS, watchOS, and Linux
Stars: ✭ 115 (-16.06%)
Mutual labels:  tvos, watchos
Sniffer
Networking activity logger for Swift
Stars: ✭ 108 (-21.17%)
Mutual labels:  tvos, watchos
Conbini
Publishers, operators, and subscribers to supplement Combine.
Stars: ✭ 109 (-20.44%)
Mutual labels:  tvos, watchos
Articles Zh Hans
Articles for NSHipster.cn
Stars: ✭ 113 (-17.52%)
Mutual labels:  tvos, watchos
Prex
🔁Unidirectional data flow architecture with MVP and Flux combination for Swift
Stars: ✭ 102 (-25.55%)
Mutual labels:  tvos, watchos
Surmagic
🚀 The better way to deal with Binary Frameworks on iOS, Mac Catalyst, tvOS, macOS, and watchOS. Create XCFrameworks with ease.
Stars: ✭ 119 (-13.14%)
Mutual labels:  tvos, watchos
Swiftui Kit
A SwiftUI system components and interactions demo app
Stars: ✭ 1,733 (+1164.96%)
Mutual labels:  tvos, watchos
Contentful.swift
A delightful Swift interface to Contentful's content delivery API.
Stars: ✭ 132 (-3.65%)
Mutual labels:  tvos, watchos
Swifterswift
A handy collection of more than 500 native Swift extensions to boost your productivity.
Stars: ✭ 10,706 (+7714.6%)
Mutual labels:  tvos, watchos
Awesome Rubymotion
A collection of awesome RubyMotion example apps, libraries, tools, frameworks, software and resources
Stars: ✭ 103 (-24.82%)
Mutual labels:  tvos, watchos
Swift Sdk
LeanCloud Swift SDK
Stars: ✭ 110 (-19.71%)
Mutual labels:  tvos, watchos
Sdwebimagewebpcoder
A WebP coder plugin for SDWebImage, use libwebp
Stars: ✭ 101 (-26.28%)
Mutual labels:  tvos, watchos
Ios Samples
Xamarin.iOS sample apps
Stars: ✭ 1,501 (+995.62%)
Mutual labels:  tvos, watchos
Persistencekit
Store and retrieve Codable objects to various persistence layers, in a couple lines of code!
Stars: ✭ 121 (-11.68%)
Mutual labels:  tvos, watchos
Egocache
Fast Caching for Objective-C (iPhone & Mac Compatible)
Stars: ✭ 1,339 (+877.37%)
Mutual labels:  tvos, watchos
Predicateflow
Write amazing, strong-typed and easy-to-read NSPredicate.
Stars: ✭ 98 (-28.47%)
Mutual labels:  tvos, watchos

platforms: iOS|tvOS|watchOS|macOS Carthage compatible CocoaPods compatible

Alley

Essential URLSessionDataTask micro-wrapper for communication with HTTP(S) web services. This is built as framework but it’s so small that I encourage you to simply copy the Alley folder into your project directly.

Why

In most cases where you need to fetch something from the internet, you:

  1. Want to get the data at the URL you are targeting, no matter what
  2. In case when it’s simply not possible, display some useful error to the end-customer and display / log what error actually happened so you can troubleshoot and debug

Second point is nice to have. First one is vastly more important since that data is the reason you are doing this at all.

Thus main feature of Alley is automatic request retries for predefined conditions.

Usage

You would already have some URLSession instance to work with. Then instead of this:

let urlRequest = URLRequest(...)

urlSession.dataTask(with: urlRequest) {
	data, urlResponse, error in
	//...process error, response, data
}

task.resume()

with Alley you will do this:

let urlRequest = URLRequest(...)

urlSession.perform(urlRequest) {
	dataResult in
	//...process dataResult
}

That’s the basic change, now let’s see what is this DataResult in the callback.

DataResult

This is your standard Swift’s Result type, defined like this:

typealias DataResult = Result<Data, NetworkError>

In case the request was successful, you would get the Data instance returned from the service which you can convert into whatever you expected it to be.

In case of failure, you get an instance of NetworkError.

NetworkError

This is custom Error (implemented by an enum) which – for starters – wraps stuff returned by URLSessionDataTask. Thus first few possible options are:

///	`URLSession` errors are passed-through, handle as appropriate.
case urlError(URLError)

///	URLSession returned an `Error` object which is not `URLError`
case generalError(Swift.Error)

Then it handles the least possible scenario to happen: no error returned by URLSessionDataTask but also no URLResponse.

case noResponse

Next, if the returned URLResponse is not HTTPURLResponse:

case invalidResponseType(URLResponse)

Now, if it is HTTPURLResponse but status code is 400 or higher, this is an error returned by the web service endpoint you are communicating with. Hence return the entire HTTPURLResponse and Data (if it exists) so caller can figure out what happened.

case endpointError(HTTPURLResponse, Data?)

In the calling object, you can use these values and try to build instances of strongly-typed custom errors related to the given specific web service.

If status code is in 2xx range, you may have a case of missing response body.

case noResponseData(HTTPURLResponse)

This may or may not be an error. If you perform PUT or DELETE or even POST requests, your service may not return any data as valid response (just 200 OK or whatever). In that case, prevent this error by calling perform like this:

let urlRequest = URLRequest(...)

urlSession.perform(urlRequest, allowEmptyData: true) {
	dataResult in
	//...process dataResult
}

where you will get empty Data() instance as DataResult.success.

There’s one more possible NetworkError value, which is related to...

Automatic retries

First of all, there’s a property in URLSession called maximumNumberOfRetries and its value is 10. Adjust it as you need.

This value is automatically used for all perform() calls but you can adjust it per call by simply supplying appropriate number to maxRetries argument:

let urlRequest = URLRequest(...)

urlSession.perform(urlRequest, maxRetries: 5) {
	dataResult in
	//...process dataResult
}

How automatic retries work?

In case of a NetworkError being raised, Alley will check its shouldRetry property and – if that’s true – it will increment retry counter by 1 and perform URLSessionDataTask again. And again. And again...until it reaches maxRetries value when it will return NetworkError.inaccessible as result.

There is currently no delay between retries, it simply tries again.

You can customize the behavior by changing the implementation of shouldRetry property. Currently it deals only with NetworkError.urlError and returns true for several obvious URLError instances.


That’s about it. Alley is intentionally simple to encourage writing as little code as possible, hiding away often-repeated boilerplate.

License

MIT License, like all my open source code.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].