afmotion 0.9.0 → 2.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,74 +1,25 @@
1
- module AFMotion
2
- class ClientDSL
3
- def initialize(client)
4
- @client = client
5
- end
6
-
7
- def header(header, value)
8
- @client.setDefaultHeader(header, value: value)
9
- end
10
-
11
- def authorization(options = {})
12
- @client.authorization = options
13
- end
14
-
15
- def operation(operation)
16
- klass = operation
17
- if operation.is_a?(Symbol) or operation.is_a?(String)
18
- klass = case operation.to_s
19
- when "json"
20
- AFJSONRequestOperation
21
- when "plist"
22
- AFPropertyListRequestOperation
23
- when "xml"
24
- AFXMLRequestOperation
25
- when "http"
26
- AFHTTPRequestOperation
27
- else
28
- raise "Not a valid operation: #{operation.inspect}"
29
- end
30
- end
31
-
32
- @client.registerHTTPOperationClass(klass)
33
- end
34
-
35
- def parameter_encoding(encoding)
36
- enc = encoding
37
- if encoding.is_a?(Symbol) or encoding.is_a?(String)
38
- enc = case encoding.to_s
39
- when "json"
40
- AFJSONParameterEncoding
41
- when "plist"
42
- AFPropertyListParameterEncoding
43
- when "form"
44
- AFFormURLParameterEncoding
45
- else
46
- p "Not a valid parameter encoding: #{encoding.inspect}; using AFFormURLParameterEncoding"
47
- AFFormURLParameterEncoding
48
- end
49
- end
50
- @client.parameterEncoding = enc
51
- end
52
- end
53
- end
1
+ motion_require 'version'
2
+ motion_require 'client_shared'
54
3
 
55
4
  module AFMotion
56
5
  class Client
57
6
  class << self
58
7
  attr_accessor :shared
59
8
 
60
- # Returns an instance of AFHTTPClient
9
+ # Returns an instance of AFHTTPRequestOperationManager
61
10
  def build(base_url, &block)
62
- client = AFHTTPClient.clientWithBaseURL(base_url.to_url)
11
+ operation_manager = AFHTTPRequestOperationManager.alloc.initWithBaseURL(base_url.to_url)
63
12
  if block
64
- dsl = AFMotion::ClientDSL.new(client)
13
+ dsl = AFMotion::ClientDSL.new(operation_manager)
65
14
  dsl.instance_eval(&block)
66
15
  end
67
- client
16
+ if !operation_manager.operationQueue
17
+ operation_manager.operationQueue = NSOperationQueue.mainQueue
18
+ end
19
+ operation_manager
68
20
  end
69
21
 
70
22
  # Sets AFMotion::Client.shared as the built client
71
- # TODO: Make sure this only happens once (dispatch_once not available)
72
23
  def build_shared(base_url, &block)
73
24
  self.shared = self.build(base_url, &block)
74
25
  end
@@ -76,135 +27,111 @@ module AFMotion
76
27
  end
77
28
  end
78
29
 
79
- class AFHTTPClient
80
- AFMotion::HTTP_METHODS.each do |method|
81
- # EX client.get('my/resource.json')
82
- define_method "#{method}", -> (path, parameters = {}, &callback) do
83
- if multipart?
84
- @operation = create_multipart_operation(method, path, parameters, &callback)
85
- self.enqueueHTTPRequestOperation(@operation)
86
- @multipart = nil
87
- else
88
- @operation = create_operation(method, path, parameters, &callback)
89
- self.enqueueHTTPRequestOperation(@operation)
90
- end
91
- @operation
30
+ module AFMotion
31
+ class ClientDSL
32
+ def initialize(operation_manager)
33
+ @operation_manager = WeakRef.new(operation_manager)
92
34
  end
93
- end
94
35
 
95
- def create_multipart_operation(method, path, parameters = {}, &callback)
96
- multipart_callback = callback.arity == 1 ? nil : lambda { |formData|
97
- callback.call(nil, formData)
98
- }
99
- upload_callback = callback.arity > 2 ? lambda { |bytes_written_now, total_bytes_written, total_bytes_expect|
100
- case callback.arity
101
- when 3
102
- callback.call(nil, nil, total_bytes_written.to_f / total_bytes_expect.to_f)
103
- when 5
104
- callback.call(nil, nil, bytes_written_now, total_bytes_written, total_bytes_expect)
105
- end
106
- } : nil
107
- request = self.multipartFormRequestWithMethod(method, path: path,
108
- parameters: parameters,constructingBodyWithBlock: multipart_callback)
109
- operation = self.HTTPRequestOperationWithRequest(request,
110
- success: lambda {|operation, responseObject|
111
- result = AFMotion::HTTPResult.new(operation, responseObject, nil)
112
- case callback.arity
113
- when 1
114
- callback.call(result)
115
- when 2
116
- callback.call(result, nil)
117
- when 3
118
- callback.call(result, nil, nil)
119
- when 5
120
- callback.call(result, nil, nil, nil, nil)
121
- end
122
- }, failure: lambda {|operation, error|
123
- result = AFMotion::HTTPResult.new(operation, nil, error)
124
- case callback.arity
125
- when 1
126
- callback.call(result)
127
- when 2
128
- callback.call(result, nil)
129
- when 3
130
- callback.call(result, nil, nil)
131
- when 5
132
- callback.call(result, nil, nil, nil, nil)
133
- end
134
- })
135
- if upload_callback
136
- operation.setUploadProgressBlock(upload_callback)
36
+ def header(header, value)
37
+ @operation_manager.headers[header] = value
137
38
  end
138
- operation
139
- end
140
39
 
141
- def create_operation(method, path, parameters = {}, &callback)
142
- request = self.requestWithMethod(method.upcase, path:path, parameters:parameters)
143
- self.HTTPRequestOperationWithRequest(request, success: lambda {|operation, responseObject|
144
- result = AFMotion::HTTPResult.new(operation, responseObject, nil)
145
- callback.call(result)
146
- }, failure: lambda {|operation, error|
147
- result = AFMotion::HTTPResult.new(operation, nil, error)
148
- callback.call(result)
149
- })
150
- end
40
+ def authorization(options = {})
41
+ @operation_manager.requestSerializer.authorization = options
42
+ end
151
43
 
152
- def multipart!
153
- @multipart = true
154
- self
155
- end
44
+ def operation_queue(operation_queue)
45
+ @operation_manager.operationQueue = operation_queue
46
+ end
156
47
 
157
- def multipart?
158
- !!@multipart
159
- end
48
+ OPERATION_TO_REQUEST_SERIALIZER = {
49
+ json: AFJSONRequestSerializer,
50
+ plist: AFPropertyListRequestSerializer
51
+ }
52
+ def request_serializer(serializer)
53
+ if serializer.is_a?(Symbol) || serializer.is_a?(String)
54
+ @operation_manager.requestSerializer = OPERATION_TO_REQUEST_SERIALIZER[serializer.to_sym].serializer
55
+ elsif serializer.is_a?(Class)
56
+ @operation_manager.requestSerializer = serializer.serializer
57
+ else
58
+ @operation_manager.requestSerializer = serializer
59
+ end
60
+ end
160
61
 
161
- # options can be
162
- # - {username: ___, password: ____}
163
- # or
164
- # - {token: ___ }
165
- def authorization=(options = {})
166
- if options.nil?
167
- clearAuthorizationHeader
168
- elsif options[:username] && options[:password]
169
- setAuthorizationHeaderWithUsername(options[:username], password: options[:password])
170
- elsif options[:token]
171
- setAuthorizationHeaderWithToken(options[:token])
172
- else
173
- raise "Not a valid authorization hash: #{options.inspect}"
62
+ OPERATION_TO_RESPONSE_SERIALIZER = {
63
+ json: AFJSONResponseSerializer,
64
+ xml: AFXMLParserResponseSerializer,
65
+ plist: AFPropertyListResponseSerializer,
66
+ image: AFImageResponseSerializer,
67
+ http: AFHTTPResponseSerializer,
68
+ form: AFHTTPResponseSerializer
69
+ }
70
+ def response_serializer(serializer)
71
+ if serializer.is_a?(Symbol) || serializer.is_a?(String)
72
+ @operation_manager.responseSerializer = OPERATION_TO_RESPONSE_SERIALIZER[serializer.to_sym].serializer
73
+ elsif serializer.is_a?(Class)
74
+ @operation_manager.responseSerializer = serializer.serializer
75
+ else
76
+ @operation_manager.responseSerializer = serializer
77
+ end
174
78
  end
175
79
  end
80
+ end
176
81
 
177
- class HeaderWrapper
178
- def initialize(client)
179
- @client = WeakRef.new(client)
180
- end
82
+ # TODO: remove this when/if https://github.com/AFNetworking/AFNetworking/issues/1388 resolved
83
+ module AFMotion
84
+ module QueryPairHelper
85
+ module_function
181
86
 
182
- def [](header)
183
- @client.defaultValueForHeader(header)
87
+ def af_QueryStringPairsFromDictionary(dictionary)
88
+ af_QueryStringPairsFromKeyAndValue(nil, dictionary)
184
89
  end
185
90
 
186
- def []=(header, value)
187
- @client.setDefaultHeader(header, value: value)
188
- end
91
+ def af_QueryStringPairsFromKeyAndValue(key, value)
92
+ mutableQueryStringComponents = []
93
+ if value.is_a?(NSDictionary)
94
+ sortDescriptor = NSSortDescriptor.sortDescriptorWithKey("description", ascending: true, selector:'caseInsensitiveCompare:')
95
+ value.allKeys.sortedArrayUsingDescriptors([sortDescriptor]).each do |nestedKey|
96
+ nestedValue = value[nestedKey]
97
+ if nestedValue
98
+ mutableQueryStringComponents += af_QueryStringPairsFromKeyAndValue(key ? "#{key}[#{nestedKey}]" : nestedKey, nestedValue)
99
+ end
100
+ end
101
+ elsif value.is_a?(NSArray)
102
+ value.each do |obj|
103
+ mutableQueryStringComponents += af_QueryStringPairsFromKeyAndValue(key, obj)
104
+ end
105
+ elsif value.is_a?(NSSet)
106
+ value.each do |obj|
107
+ mutableQueryStringComponents += af_QueryStringPairsFromKeyAndValue(key, obj)
108
+ end
109
+ else
110
+ mutableQueryStringComponents << AFQueryStringPair.alloc.initWithField(key, value: value)
111
+ end
189
112
 
190
- def delete(header)
191
- value = self[header]
192
- @client.setDefaultHeader(header, value: nil)
193
- value
113
+ mutableQueryStringComponents
194
114
  end
195
115
  end
196
116
 
197
- def headers
198
- @header_wrapper ||= HeaderWrapper.new(self)
117
+ class MultipartParametersWrapper < Hash
118
+ def initialize(parameters)
119
+ super()
120
+ query_pairs = QueryPairHelper.af_QueryStringPairsFromDictionary(parameters)
121
+ query_pairs.each do |key_pair|
122
+ self[key_pair.field] = key_pair.value
123
+ end
124
+ end
199
125
  end
126
+ end
200
127
 
201
- private
202
- # To force RubyMotion pre-compilation of these methods
203
- def dummy
204
- self.getPath("", parameters: nil, success: nil, failure: nil)
205
- self.postPath("", parameters: nil, success: nil, failure: nil)
206
- self.putPath("", parameters: nil, success: nil, failure: nil)
207
- self.deletePath("", parameters: nil, success: nil, failure: nil)
208
- self.patchPath("", parameters: nil, success: nil, failure: nil)
128
+ class AFHTTPRequestOperationManager
129
+ include AFMotion::ClientShared
130
+
131
+ AFMotion::HTTP_METHODS.each do |method|
132
+ # EX client.get('my/resource.json')
133
+ define_method "#{method}", -> (path, parameters = {}, &callback) do
134
+ create_operation(method, path, parameters, &callback)
135
+ end
209
136
  end
210
137
  end
@@ -1,9 +1,15 @@
1
1
  module AFMotion
2
2
  class HTTPResult
3
- attr_accessor :operation, :object, :error
3
+ attr_accessor :operation, :object, :error, :task
4
4
 
5
- def initialize(operation, responseObject, error)
6
- self.operation = operation
5
+ def initialize(operation_or_task, responseObject, error)
6
+ if operation_or_task.is_a?(NSURLSessionTask) ||
7
+ # cluser class ugh
8
+ operation_or_task.class.to_s.include?("Task")
9
+ self.task = operation_or_task
10
+ else
11
+ self.operation = operation_or_task
12
+ end
7
13
  self.object = responseObject
8
14
  self.error = error
9
15
  end
@@ -17,6 +23,9 @@ module AFMotion
17
23
  end
18
24
 
19
25
  def body
26
+ if task && task.currentRequest
27
+ raise "Cannot call result.body of a task"
28
+ end
20
29
  if operation && operation.responseString
21
30
  operation.responseString
22
31
  end
@@ -1,83 +1,69 @@
1
1
  module AFMotion
2
2
  module Operation
3
- module HTTP
4
- def self.for_request(request, &callback)
5
- operation = AFHTTPRequestOperation.alloc.initWithRequest(request)
6
- operation.setCompletionBlockWithSuccess(
7
- lambda { |operation, responseObject|
8
- result = AFMotion::HTTPResult.new(operation, responseObject, nil)
9
- callback.call(result)
10
- },
11
- failure: lambda {|operation, error|
12
- result = AFMotion::HTTPResult.new(operation, nil, error)
13
- callback.call(result)
14
- }
15
- )
16
- operation
3
+ module_function
4
+ def for_request(ns_url_request, &callback)
5
+ operation = AFHTTPRequestOperation.alloc.initWithRequest(ns_url_request)
6
+ success_block = success_block_for_http_method(ns_url_request.HTTPMethod, callback)
7
+ operation.setCompletionBlockWithSuccess(success_block, failure: failure_block(callback))
8
+ operation
9
+ end
10
+
11
+ def success_block_for_http_method(http_method, callback)
12
+ if http_method.downcase.to_sym == :head
13
+ return lambda { |operation|
14
+ AFMotion::HTTPResult.new(operation, nil, nil)
15
+ }
17
16
  end
17
+
18
+ lambda { |operation, responseObject|
19
+ result = AFMotion::HTTPResult.new(operation, responseObject, nil)
20
+ callback.call(result)
21
+ }
18
22
  end
19
23
 
20
- module JSON
21
- def self.for_request(request, &callback)
22
- operation = AFJSONRequestOperation.JSONRequestOperationWithRequest(request,
23
- success: lambda { |request, response, json|
24
- result = AFMotion::HTTPResult.new(operation, json, nil)
25
- callback.call(result)
26
- },
27
- failure: lambda { |request, response, error, json|
28
- result = AFMotion::HTTPResult.new(operation, json, error)
29
- callback.call(result)
30
- }
31
- )
32
- end
24
+ def failure_block(callback)
25
+ lambda { |operation, error|
26
+ result = AFMotion::HTTPResult.new(operation, nil, error)
27
+ callback.call(result)
28
+ }
33
29
  end
30
+ end
34
31
 
35
- module XML
36
- def self.for_request(request, &callback)
37
- operation = AFXMLRequestOperation.XMLParserRequestOperationWithRequest(request,
38
- success: lambda { |request, response, document_or_parser|
39
- result = AFMotion::HTTPResult.new(operation, document_or_parser, nil)
40
- callback.call(result)
41
- },
42
- failure: lambda { |request, response, error, document_or_parser|
43
- result = AFMotion::HTTPResult.new(operation, document_or_parser, error)
44
- callback.call(result)
45
- }
46
- )
47
- end
32
+ module Serialization
33
+ def with_request_serializer(serializer_klass)
34
+ self.requestSerializer = serializer_klass.serializer
35
+ self
48
36
  end
49
37
 
50
- module PLIST
51
- def self.for_request(request, &callback)
52
- operation = AFPropertyListRequestOperation.propertyListRequestOperationWithRequest(request,
53
- success: lambda { |request, response, propertyList|
54
- result = AFMotion::HTTPResult.new(operation, propertyList, nil)
55
- callback.call(result)
56
- },
57
- failure: lambda { |request, response, error, propertyList|
58
- result = AFMotion::HTTPResult.new(operation, propertyList, error)
59
- callback.call(result)
60
- }
61
- )
62
- end
38
+ def with_response_serializer(serializer_klass)
39
+ self.responseSerializer = serializer_klass.serializer
40
+ self
63
41
  end
64
42
 
65
- module Image
66
- def self.for_request(request, &callback)
67
- operation = AFImageRequestOperation.imageRequestOperationWithRequest(request,
68
- imageProcessingBlock: lambda {|ui_image|
69
- return ui_image
70
- },
71
- success: lambda { |request, response, ui_image|
72
- result = AFMotion::HTTPResult.new(operation, ui_image, nil)
73
- callback.call(result)
74
- },
75
- failure: lambda { |request, response, error|
76
- result = AFMotion::HTTPResult.new(operation, nil, error)
77
- callback.call(result)
78
- }
79
- )
80
- end
43
+ def json!
44
+ with_request_serializer(AFJSONRequestSerializer).
45
+ with_response_serializer(AFJSONResponseSerializer)
46
+ end
47
+
48
+ def xml!
49
+ with_response_serializer(AFXMLParserResponseSerializer)
50
+ end
51
+
52
+ def plist!
53
+ with_request_serializer(AFPropertyListRequestSerializer).
54
+ with_response_serializer(AFPropertyListResponseSerializer)
55
+ end
56
+
57
+ def image!
58
+ with_response_serializer(AFImageResponseSerializer)
81
59
  end
82
60
  end
61
+ end
62
+
63
+ class AFHTTPRequestOperation
64
+ include AFMotion::Serialization
65
+ end
66
+
67
+ class AFHTTPRequestOperationManager
68
+ include AFMotion::Serialization
83
69
  end
File without changes
@@ -0,0 +1,41 @@
1
+ class AFHTTPRequestSerializer
2
+ class HeaderWrapper
3
+ def initialize(serializer)
4
+ @serializer = WeakRef.new(serializer)
5
+ end
6
+
7
+ def [](header)
8
+ @serializer.HTTPRequestHeaders[header]
9
+ end
10
+
11
+ def []=(header, value)
12
+ @serializer.setValue(value, forHTTPHeaderField: header)
13
+ end
14
+
15
+ def delete(header)
16
+ value = self[header]
17
+ self[header] = nil
18
+ value
19
+ end
20
+ end
21
+
22
+ def headers
23
+ @header_wrapper ||= HeaderWrapper.new(self)
24
+ end
25
+
26
+ # options can be
27
+ # - {username: ___, password: ____}
28
+ # or
29
+ # - {token: ___ }
30
+ def authorization=(options = {})
31
+ if options.nil?
32
+ clearAuthorizationHeader
33
+ elsif options[:username] && options[:password]
34
+ setAuthorizationHeaderFieldWithUsername(options[:username], password: options[:password])
35
+ elsif options[:token]
36
+ setAuthorizationHeaderFieldWithToken(options[:token])
37
+ else
38
+ raise "Not a valid authorization hash: #{options.inspect}"
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,128 @@
1
+ motion_require 'http_client'
2
+ motion_require 'version'
3
+
4
+ =begin
5
+ AFMotion::SessionClient.build("http://google.com") do |client|
6
+ client.session_configuration :default # :ephemeral
7
+ client.session_configuration :background, "com.usepropeller.afmotion"
8
+ client.session_configuration my_session_configuration
9
+
10
+ response_serializer
11
+
12
+ request_serializer
13
+ end
14
+ =end
15
+ module AFMotion
16
+ class SessionClient
17
+ class << self
18
+
19
+ attr_accessor :shared
20
+
21
+ # Returns an instance of AFHTTPRequestOperationManager
22
+ def build(base_url, &block)
23
+ dsl = AFMotion::SessionClientDSL.new(base_url)
24
+ case block.arity
25
+ when 0
26
+ dsl.instance_eval(&block)
27
+ when 1
28
+ block.call(dsl)
29
+ end
30
+
31
+ dsl.to_session_manager
32
+ end
33
+
34
+ # Sets AFMotion::Client.shared as the built client
35
+ def build_shared(base_url, &block)
36
+ self.shared = self.build(base_url, &block)
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ module AFMotion
43
+ class SessionClientDSL < ClientDSL
44
+ class Config
45
+ attr_accessor :responseSerializer, :operationQueue, :requestSerializer, :sessionConfiguration
46
+
47
+ class MockRequestSerializer
48
+ attr_accessor :authorization
49
+ end
50
+
51
+ def requestSerializer
52
+ @requestSerializer ||= MockRequestSerializer.new
53
+ end
54
+
55
+ def requestSerializer=(requestSerializer)
56
+ if @requestSerializer && @requestSerializer.is_a?(MockRequestSerializer)
57
+ requestSerializer.authorization = @requestSerializer.authorization
58
+ end
59
+ @requestSerializer = requestSerializer
60
+ end
61
+
62
+ def headers
63
+ @headers ||= {}
64
+ end
65
+ end
66
+
67
+ attr_accessor :operation_manager
68
+ alias_method :config, :operation_manager
69
+
70
+ def initialize(base_url)
71
+ @base_url = base_url
72
+ @operation_manager = Config.new
73
+ end
74
+
75
+ def to_session_manager
76
+ session_manager = AFHTTPSessionManager.alloc.initWithBaseURL(@base_url.to_url,
77
+ sessionConfiguration: config.sessionConfiguration)
78
+ session_manager.responseSerializer = config.responseSerializer if config.responseSerializer
79
+ if !config.requestSerializer.is_a?(Config::MockRequestSerializer)
80
+ session_manager.requestSerializer = config.requestSerializer
81
+ elsif config.requestSerializer.authorization
82
+ session_manager.requestSerializer.authorization = config.requestSerializer.authorization
83
+ end
84
+ config.headers.each do |key, value|
85
+ session_manager.requestSerializer.headers[key] = value
86
+ end
87
+ session_manager.operationQueue = config.operationQueue if config.operationQueue
88
+ session_manager
89
+ end
90
+
91
+ SESSION_CONFIGURATION_SHORTHAND = {
92
+ default: :defaultSessionConfiguration,
93
+ ephemeral: :ephemeralSessionConfiguration,
94
+ background: "backgroundSessionConfiguration:".to_sym
95
+ }
96
+
97
+ def session_configuration(session_configuration, identifier = nil)
98
+ if session_configuration.is_a?(Symbol) || session_configuration.is_a?(String)
99
+ method_signature = SESSION_CONFIGURATION_SHORTHAND[session_configuration.to_sym]
100
+ ns_url_session_configuration = begin
101
+ if identifier
102
+ NSURLSessionConfiguration.send(method_signature, identifier)
103
+ else
104
+ NSURLSessionConfiguration.send(method_signature)
105
+ end
106
+ end
107
+ self.config.sessionConfiguration = ns_url_session_configuration
108
+ elsif session_configuration.is_a?(NSURLSessionConfiguration) ||
109
+ # cluster class smh
110
+ session_configuration.class.to_s.include?("URLSessionConfiguration")
111
+ self.config.sessionConfiguration = session_configuration
112
+ else
113
+ raise "Invalid type for session_configuration; need Symbol, String, or NSURLSessionConfiguration, but got #{session_configuration.class}"
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ class AFHTTPSessionManager
120
+ include AFMotion::ClientShared
121
+
122
+ AFMotion::HTTP_METHODS.each do |method|
123
+ # EX client.get('my/resource.json')
124
+ define_method "#{method}", -> (path, parameters = {}, &callback) do
125
+ create_task(method, path, parameters, &callback)
126
+ end
127
+ end
128
+ end
@@ -1,5 +1,5 @@
1
1
  module AFMotion
2
- VERSION = "0.9.0"
2
+ VERSION = "2.0.0.rc1"
3
3
 
4
4
  HTTP_METHODS = [:get, :post, :put, :delete, :patch, :head]
5
5
  end
data/lib/afmotion.rb CHANGED
@@ -1,15 +1,21 @@
1
1
  require "afmotion/version"
2
2
  require 'motion-cocoapods'
3
+ require 'motion-require'
3
4
 
4
5
  unless defined?(Motion::Project::Config)
5
6
  raise "This file must be required within a RubyMotion project Rakefile."
6
7
  end
7
8
 
9
+ Motion::Require.all(Dir.glob(File.join(File.dirname(__FILE__), 'afmotion/**/*.rb')))
10
+
8
11
  Motion::Project::App.setup do |app|
9
12
  Dir.glob(File.join(File.dirname(__FILE__), 'afmotion/**/*.rb')).each do |file|
10
- app.files.unshift(file)
11
13
  if app.respond_to?("exclude_from_detect_dependencies")
12
14
  app.exclude_from_detect_dependencies << file
13
15
  end
14
16
  end
17
+
18
+ app.pods do
19
+ pod 'AFNetworking', '~> 2.0.0'
20
+ end
15
21
  end