AlamoRecord alternatives and similar libraries
Based on the "Networking" category.
Alternatively, view AlamoRecord alternatives based on common mentions on social networks and blogs.
-
RealReachability
We need to observe the REAL reachability of network. That's what RealReachability do. -
Networking
DISCONTINUED. Easy HTTP Networking in Swift a NSURLSession wrapper with image caching support -
XMNetworking
A lightweight but powerful network library with simplified and expressive syntax based on AFNetworking. -
Digger
Digger is a lightweight download framework that requires only one line of code to complete the file download task -
SOAPEngine
This generic SOAP client allows you to access web services using a your iOS app, Mac OS X app and AppleTV app. -
TWRDownloadManager
A modern download manager based on NSURLSession to deal with asynchronous downloading, management and persistence of multiple files. -
ws ☁️
⚠️ Deprecated - (in favour of Networking) :cloud: Elegantly connect to a JSON api. (Alamofire + Promises + JSON Parsing) -
AFNetworking+RetryPolicy
Nice category that adds the ability to set the retry interval, retry count and progressiveness. -
MultiPeer
📱📲 A wrapper for the MultipeerConnectivity framework for automatic offline data transmission between devices
CodeRabbit: AI Code Reviews for Developers
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of AlamoRecord or a related project?
README
Written in Swift 5
AlamoRecord is a powerful yet simple framework that eliminates the often complex networking layer that exists between your networking framework and your application. AlamoRecord uses the power of Alamofire and the concepts behind the ActiveRecord pattern to create a networking layer that makes interacting with your API easier than ever.
Requirements
- iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+
- Xcode 10.2+
- Swift 5.1
Installation
AlamoRecord is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'AlamoRecord'
Getting Started
The power of AlamoRecord lies within four main components.
AlamoRecordObject
These are data objects that are retrieved from an API. All data objects that inherit from this class automatically receive built in helpers such as create, find, update, and destroy. This is also known as CRUD.
RequestManager
These are the work horses of AlamoRecord. They contain all of the networking helpers that AlamoRecord needs in order to create your application's networking layer. They are responsible for each request that your AlamoRecordObject
's make. They also contain upload and download helpers.
AlamoRecordURL
These store all of the information needed in order to make a proper request through instances of RequestManager
's.
AlamoRecordError
These are errors that are returned from an API. On a failed request, the JSON returned will be mapped from the predefined fields that are setup.
Example
Let's assume we are developing an application that allows user's to interact with each other via posts.
Step 1
We first need to create a class that conforms to AlamoRecordURL
. Let's name it ApplicationURL
:
ApplicationURL
class ApplicationURL: AlamoRecordURL {
var absolute: String {
return "https://jsonplaceholder.typicode.com/\(url)"
}
private var url: String
required init(url: String) {
self.url = url
}
}
Notice how you only need to pass the path and not the domain to each instance that conforms to AlamoRecordURL
. That's because you set the domain of each instance in the absolute
variable.
Step 2
This step can be ignored if your server does not return back custom error messages. If this is the case, then base AlamoRecordError
objects can be used in return.
Let's assume our API returns custom error messages. Let's create a class that inherits from AlamoRecordError
and name it ApplicationError
. Let's also assume our JSON structure looks similar to this on failed requests:
{
"status_code": 401,
"message": "You are not authorized to make this request.",
}
Our class structure would then look very similar to this:
ApplicationError
class ApplicationError: AlamoRecordError {
let statusCode: Int?
let message: String?
private enum CodingKeys: String, CodingKey {
case statusCode = "status_code"
case message
}
}
Step 3
We next need to create an instance of a RequestManager
and pass in the ApplicationURL
and ApplicationError
we just created to the inheritance structure to satisfy the generic requirements. Let's name it ApplicationRequestManager
.
ApplicationRequestManager
// IDType should be of type String or Int
class ApplicationRequestManager: RequestManager<ApplicationURL, ApplicationError, IDType> {
static var `default`: ApplicationRequestManager = ApplicationRequestManager()
init() {
// See the Configuration documentation for all possible options
super.init(configuration: Configuration())
}
}
Step 4
The final step is to create data objects inheriting from AlamoRecordObject
that our application needs from our API. In this example, we only have one object named Post
.
Post
// IDType should be of type String or Int
class Post: AlamoRecordObject<ApplicationURL, ApplicationError, IDType> {
let userId: Int
let title: String
let body: String
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
title = try container.decode(String.self, forKey: .title)
body = try container.decode(String.self, forKey: .body)
try super.init(from: decoder)
}
override class var root: String {
return "post"
}
override class var requestManager: RequestManager<ApplicationURL, ApplicationError, IDType> {
return ApplicationRequestManager
}
private enum CodingKeys: String, CodingKey {
case userId
case title
case body
}
}
With this class definition, we would expect each Post
json to look like this:
{
"userId": 1,
"id": 1,
"title": "This is a post's title",
"body": "This is the post's body"
}
If our Post
object was encapsulated in an object like this:
{
"post": {
"userId": 1,
"id": 1,
"title": "This is a post's title",
"body": "This is the post's body"
}
}
we would only simply need to override the keyPath
in the class declaration:
override class var keyPath: String? {
return "post"
}
Notice how the requestManager
class variable is overrided and returns the ApplicationRequestManager
just created in step 3. Also notice how the root
class variable is overrided. Both of these overrides are required for each instance that directly inherits from AlamoRecordObject
.
That's it! With just a few lines of code, your networking layer to your application is ready to be used. In the next section, we see all the built in helpers we get by using AlamoRecord.
Getting all instances of Post
GET
https://jsonplaceholder.typicode.com/posts
Post.all(success: { (posts: [Post]) in
// Do something with the posts
}) { (error) in
// Handle the error
}
Creating an instance of Post
POST
https://jsonplaceholder.typicode.com/posts
let parameters: [String: Any] = ["userId": user.id,
"title": title,
"body": body]
Post.create(parameters: parameters, success: { (post: Post) in
// Do something with the post
}) { (error) in
// Handle the error
}
Finding an instance of Post
GET
https://jsonplaceholder.typicode.com/posts/1
Post.find(id: 1, success: { (post: Post) in
// Do something with the post
}) { (error) in
// Handle the error
}
Updating an instance of Post
PUT
https://jsonplaceholder.typicode.com/posts/1
let parameters: [String: Any] = ["userId": user.id,
"title": title,
"body": body]
post.update(parameters: parameters, success: { (post: Post) in
// Do something with the post
}) { (error) in
// Handle the error
}
This can also be done at the class level:
Post.update(id: 1, parameters: parameters, success: { (post: Post) in
// Do something with the post
}) { (error) in
// Handle the error
}
Destroying an instance of Post
DELETE
https://jsonplaceholder.typicode.com/posts/1
post.destroy(id: 1, success: {
// The post is now destroyed
}) { (error) in
// Handle the error
}
This can also be done at the class level:
Post.destroy(id: 1, success: {
// The post is now destroyed
}) { (error) in
// Handle the error
}
Uploading a file
requestManager.upload(url: url,
multipartFormData: data,
multipartFormDataName: dataName,
success: { (any: Any?) in
// Upload was successful
}) { (error) in
// Handle the error
}
Downloading a file
requestManager.download(url: url,
destination: destination,
progress: { (progress) in
// Check the progress
}, success: { (url) in
// Do something with the url
}) { (error) in
// Handle the error
}
Providing a destination is optional. If a destination is not provided, then the file will be saved to a temporary location. This file will be overwritten if another download request is made without providing a destination.
Download the example project to see just how easy creating an application that interacts with an API is when using AlamoRecord!
Author
Original concept designed by Rick Pernikoff. AlamoRecord implementation by Dalton Hinterscher.
License
AlamoRecord is available under the MIT license. See the LICENSE file for more info.
*Note that all licence references and agreements mentioned in the AlamoRecord README section above
are relevant to that project's source code only.