• Stars
    star
    147
  • Rank 251,347 (Top 5 %)
  • Language
    Swift
  • License
    MIT License
  • Created about 5 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

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

platforms: iOS|tvOS|watchOS|macOS SwiftPM ready 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.

Integration

Manually

Just drag Alley folder into your project.

If you prefer to use dependency managers, see below. Releases are tagged with Semantic Versioning in mind.

Swift Package Manager

Ready, just add this repo URL as Package. I recommend to link with master branch, not with specific version.

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate Alley into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'Alley', 	:git => 'https://github.com/radianttap/Alley.git'

Setting up with Carthage

Carthage is a decentralized dependency manager that automates the process of adding frameworks to your Cocoa application.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate Alley into your Xcode project using Carthage, specify it in your Cartfile:

github "radianttap/Alley"

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.performNetworkRequest(urlRequest) {
	networkResult in
	//...process networkResult
}

// -- or --

do {
	let data = try await urlSession.alleyData(for: urlRequest)
} catch let err {
	//...process NetworkError
}

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

typealias NetworkResult = 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.

Of course, with async/await, you will get Data directly.

Either way — in case of failure you will 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 you get 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.performNetworkRequest(urlRequest, allowEmptyData: true) {
	networkResult in
	//...process networkResult
}

// -- or --

let data = try await urlSession.alleyData(for: urlRequest, allowEmptyData: true)

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

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

Automatic retries

Default number of retries is 10.

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

let urlRequest = URLRequest(...)

urlSession.performNetworkRequest(urlRequest, maxRetries: 5) {
	networkResult in
	//...process networkResult
}

// -- or --

let data = try await urlSession.alleyData(for: urlRequest, maxRetries: 5)

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.

Each retry is delayed by half a second (see NetworkError.defaultRetryDelay).

You can customize the behavior by changing the implementation of shouldRetry property.


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.

Give back

If you found this code useful, please consider buying me a coffee or two. ☕️😋

More Repositories

1

CardPresentationController

Custom UIPresentationController which mimics the behavior of Apple Music UI
Swift
794
star
2

Coordinator

Implementation of Coordinators app design pattern.
Swift
721
star
3

Swift-Essentials

A set of essential Swift stuff I use in every single iOS app.
Swift
237
star
4

WatchRingGenerator

iOS app to generate series of PNG images, to be used in WatchKit apps
Objective-C
148
star
5

LanguageSwitcher

Example how to switch iOS app's language on-the-fly, instantly
Swift
90
star
6

Fields

Good, solid base to build custom forms in iOS apps, using self-sizing compositional layout.
Swift
79
star
7

HTML2PDFRenderer

Take any HTML loaded in WKWebView and make PDF out of it.
Swift
70
star
8

Avenue

Wrapper around URLSession and URLSessionTask to enable seamless integration with Operation / OperationQueue.
Swift
57
star
9

Ambar

Powerful, advanced Core Data Stack implementation, in Swift.
Swift
54
star
10

EFI-ASRock-X570-ITX-TB3

OpenCore EFI for build using ASRock X570 ITX board, Ryzen 9 5900X
45
star
11

RTFlyoutMenu

Fly-out (drop-down) menu component for iPad
Objective-C
41
star
12

EFI-B550I-Aorus

EFI for Gigabyte B550I Aorus Pro AX with 5900X and RX 6900 XT and with custom-replaced Wifi/Bt card.
23
star
13

EFI-ASRock-Z490-ITX-TB3

EFI for OpenCore bootloader, for Intel-based Hackintosh comparable to iMac (2020)
18
star
14

Coordinator-iOS13-starter-app

Template for iOS 13 app, with UIScenes and Coordinator pattern
Swift
16
star
15

RTCleanNavigationBar

UINavigationBar subclass that removes the shadow image while retaining translucency effect in iOS 7 and up
Objective-C
14
star
16

RTWalkthrough

An Objective-C clone of github/ariok/BWWalkthrough (a bit improved in the process)
Objective-C
12
star
17

Spotifier

Swift
12
star
18

NSFileManager-Utilities

Objective-C
10
star
19

UITableView-NSFetchedResultsController

UITV and NSFRC, sitting in a tree, forever happy
Objective-C
6
star
20

ryzentosh

Adventures in building hackintosh with OpenCore, running AMD Ryzen CPUs
6
star
21

RTFlowLayout

Like UICollectionViewFlowLayout, but with additional supplementary views.
Objective-C
5
star
22

ComposableUI

An example of the power of container controllers to UI driven by very complex functionality
Objective-C
4
star
23

RTCoreDataStack

Core Data stack for Objective-C apps
Objective-C
4
star
24

RTGraphLayout

UICollectionViewFlowLayout subclass acting like zoomable bar chart
Objective-C
3
star
25

FirebaseTokenReporter

Utility to convert APNS token into FCM token
Swift
2
star
26

UILabel-FontName

UIAppearance for UILabel font name
Objective-C
2
star
27

AsyncOperations

Jared Sinclair built this library a while back. Not sure why it's gone from his account, but hosting a copy until further notice.
Swift
2
star
28

RTTabBarController

Highly customizable and feature-rich replacement for UITabBarController
Objective-C
1
star
29

RTFormKit

Table View and self-sizing auto-layout based forms
Objective-C
1
star
30

EFI-Asus-ROG-Strix-B550-I

1
star
31

RTCollectionViewFlowLayout

Subclass of UICollectionViewFlowLayout, with two additional supplementary views
Objective-C
1
star