在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):bustoutsolutions/siesta开源软件地址(OpenSource Url):https://github.com/bustoutsolutions/siesta开源编程语言(OpenSource Language):Swift 96.6%开源软件介绍(OpenSource Introduction):The elegant way to write iOS / macOS REST clients Drastically simplifies app code by providing a client-side cache of observable models for RESTful resources.
Table of ContentsOverview
Documentation
What’s It For?The ProblemWant 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 SolutionSiesta 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:
…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
What it doesn’t do
OriginThis 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 PhilosophyMake 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:
…in that order of priority. InstallationSiesta requires Swift 5.3+ and Xcode 12+. (Use the Swift Package ManagerIn Xcode:
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). CocoaPodsIn your
If you want to use the UI helpers:
If you want to use Alamofire as your networking provider instead of Foundation’s
(You’ll also need to pass an CarthageIn your
Follow the Carthage instructions to add As of this writing, there is one additional step you need to follow that isn’t in the Carthage docs:
(In-depth discussion of Carthage in recent Xcode versions is here.) The code in Git Submodule
If you want to use the UI helpers, you will need to repeat steps 3–5 for 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 UsageMake 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 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 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 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: 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 Comparison With Other FrameworksPopular REST / networking frameworks have different primary goals:
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¹:
1. Disclaimer: table compiled by Siesta’s non-omniscient author. Corrections / additions? Please submit a PR.
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. DocumentationExamplesThis repo includes a simple example project. To download the example project, install its dependencies, and run it locally:
SupportTo ask for help, please post a question on Stack Overflow and tag it with Things that belong on Stack Overflow:
For a bug, feature request, or cool idea, please file a Github issue. Things that belong in Github issues:
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 thingsKeep 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. |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论