AFMotion is a thin RubyMotion wrapper for AFNetworking, the absolute best networking library on iOS.
AFMotion can be used with standalone URL requests:
AFMotion::HTTP.get("http://google.com") do |result|
p result.body
end
AFMotion::JSON.get("http://jsonip.com") do |result|
p result.object["ip"]
end
If you're interacting with a web service, you can use AFHTTPClient
with this nice wrapper:
# DSL Mapping to properties of AFHTTPClient
AFMotion::Client.build_shared("https://alpha-api.app.net/") do
header "Accept", "application/json"
operation :json
end
AFMotion::Client.shared.get("stream/0/posts/stream/global") do |result|
if result.success?
p result.object
elsif result.failure?
p result.error.localizedDescription
end
end
Loading images from the internet is pretty common. AFNetworking's existing methods aren't bad at all, but just incase you want extra Ruby:
image_view = UIImageView.alloc.initWithFrame CGRectMake(0, 0, 100, 100)
image_view.url = "http://i.imgur.com/r4uwx.jpg"
# or
placeholder = UIImage.imageNamed "placeholder-avatar"
image_view.url = {url: "http://i.imgur.com/r4uwx.jpg", placeholder: placeholder}
You can also request arbitrary images:
AFMotion::Image.get("https://www.google.com/images/srpr/logo3w.png") do |result|
image_view = UIImageView.alloc.initWithImage(result.object)
end
-
gem install afmotion
-
require 'afmotion'
or add to yourGemfile
-
In your
Rakefile
, add:
Motion::Project::App.setup do |app|
...
app.pods do
pod 'AFNetworking'
end
end
Each AFMotion wrapper callback yields an AFMotion::HTTPResult
object. This object has properties like so:
AFMotion::some_function do |result|
# result.operation is the AFURLConnectionOperation instance
p result.operation.inspect
if result.success?
# result.object depends on the type of operation.
# For JSON and PLIST, this is usually a Hash.
# For XML, this is an NSXMLParser
# For HTTP, this is an NSURLResponse
# For Image, this is a UIImage
p result.object
elsif result.failure?
# result.error is an NSError
p result.error.localizedDescription
end
end
There are wrappers for each AFURLConnectionOperation
subclass, each of the form:
AFMotion::Operation::[Operation Type].for_request(ns_url_request) do |result|
...
end
AFMotion::Operation::HTTP.for_request...
AFMotion::Operation::JSON.for_request...
AFMotion::Operation::XML.for_request...
AFMotion::Operation::PLIST.for_request...
AFMotion::Operation::Image.for_request...
There are wrappers which automatically run a URL request for a given URL and HTTP method, of the form:
AFMotion::[Operation Type].[HTTP method](url, [Parameters = {}]) do |result|
...
end
Example:
AFMotion::HTTP.get("http://google.com", q: "rubymotion") do |result|
# sends request to http://google.com?q=rubymotion
end
AFMotion::HTTP.get/post/put/patch/delete(url)...
AFMotion::JSON.get/post/put/patch/delete(url)...
AFMotion::XML.get/post/put/patch/delete(url)...
AFMotion::PLIST.get/post/put/patch/delete(url)...
AFMotion::Image.get/post/put/patch/delete(url)...
If you're constantly accesing a web service, it's a good idea to use an AFHTTPClient
. Things lets you add a common base URL and request headers to all the requests issued through it, like so:
client = AFMotion::Client.build("https://alpha-api.app.net/") do
header "Accept", "application/json"
operation :json
end
client.get("stream/0/posts/stream/global") do |result|
...
end
If you're constantly used one web service, you can use the AFMotion::Client.shared
variable have a common reference. It can be set like a normal variable or created with AFMotion::Client.build_shared
.
AFHTTPClient
supports methods of the form AFHTTPClient#get/post/put/patch/delete(url, request_parameters)
. The request_parameters
is a hash containing your parameters to attach as the request body or URL parameters, depending on request type. For example:
client.get("users", id: 1) do |result|
...
end
client.post("users", name: "@clayallsopp", library: "AFMotion") do |result|
...
end
AFHTTPClient
supports multipart form requests (i.e. for image uploading). Simply prepend multipart
to any other request method and it'll convert your parameters into properly encoded multipart data:
# an instance of UIImage
image = my_function.get_image
data = UIImagePNGRepresentation(image)
client.multipart.post("avatars") do |result, form_data|
if form_data
# Called before request runs
# see: https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-FAQ
form_data.appendPartWithFileData(data, name: "avatar", fileName:"avatar.png", mimeType: "image/png")
elsif result.success?
...
else
...
end
end
If you want to track upload progress, you can add a third callback argument which returns the upload percentage between 0.0 and 1.0:
client.multipart.post("avatars") do |result, form_data, progress|
if form_data
# Called before request runs
# see: https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-FAQ
form_data.appendPartWithFileData(data, name: "avatar", fileName:"avatar.png", mimeType: "image/png")
elsif progress
# 0.0 <= progress <= 1.0
my_widget.update_progress(progress)
...
end
The AFMotion::Client
DSL allows the following properties:
header(header, value)
authorization(username: ___, password: ____)
for HTTP Basic auth, orauthorization(token: ____)
for Token based auth.operation(operation_type)
. Allows you to set a common operation class for all your client's requests. So if your API is always going to be JSON, you should setoperation(:json)
. Accepts:json
,:plist
,:xml
, or:http
parameter_encoding(encoding)
. Allows you to set a body format for requests parameters. For example, when you send a POST request you might want the parameters to be encoding as a JSON object instead of the traditionalkey=val
format. Accepts:json
,:plist
, and:form
(normal encoding).