Swift 如何在Alamofire.request()之外使用JSON?
我试图从Swift 如何在Alamofire.request()之外使用JSON?,swift,alamofire,Swift,Alamofire,我试图从Alamofire返回JSON字典。问题在于,当将JSON赋值给外部变量时,赋值会保存在Alamofire.request块内并只读,其值之外不会保存(对我来说很神奇)。我做错了什么 我第一次这样做。我尝试使用URLSession.shared.dataTask,但我也无法从任务返回值。 我注意到,首先在返回res行触发断点,然后在返回json行触发断点,然后在打印(json)行触发断点。我不知道为什么 struct resultMsg { var message: [Strin
Alamofire
返回JSON
字典。问题在于,当将JSON
赋值给外部变量时,赋值会保存在Alamofire.request
块内并只读,其值之外不会保存(对我来说很神奇)。我做错了什么
我第一次这样做。我尝试使用URLSession.shared.dataTask
,但我也无法从任务返回值。
我注意到,首先在返回res
行触发断点,然后在返回json
行触发断点,然后在打印(json)
行触发断点。我不知道为什么
struct resultMsg {
var message: [String:Any] = [:]
init() { }
init(message: [String:Any]) {
self.message = message
}
}
func sendGET(method: String, data: [String:String]) -> [String:Any] {
let resultURL: String = rootURI + method
let url = URL(string: resultURL)!
var res: [String:Any] = [:]
Alamofire.request(url, method: .post, parameters: data, encoding: JSONEncoding.default)
.responseJSON { response in
print(response)
if let status = response.response?.statusCode {
switch(status){
case 201:
print("example success")
default:
print("error with response status: \(status)")
}
}
//to get JSON return value
if let result = response.result.value {
let JSON = result as! NSDictionary
res = JSON as! [String : Any]
print(JSON) // Here res is contain actualy json
}
}
return res // Here res equal [:]
}
public func Authorize() -> resultMsg {
let data: [String:String] = ["login":login,
"pass":pass]
var json = resultMsg.init()
json.message = sendGET(method: "auth.php", data: data)
return json
}
这是因为网络请求通常是异步的。当您调用
Alamofire.request(…)
时,网络请求启动,request
立即返回。与此同时,社交活动也发生在后台。由于request
已返回,因此您的sendGET
功能将立即继续下一行
稍后,当网络请求完成时,将调用完成块。您将该值分配给res
,但为时已晚,因为sendGET
在请求启动时已返回空字典
通常这很快,但是想象一下这将需要很长的时间。毕竟,有时候它将花费很长时间。如果网络连接超时,可能需要几分钟
有不同的处理方法
- 在一种方法中,您可以将
作为该代码所在类的属性。然后,您的完成块仍然会为res
分配一个值,然后调用一些新代码来告诉您的类结果可用res
- 在另一种方法中,您可以修改完成闭包,将JSON数据传递给直接使用数据的其他函数。添加一些新函数,其参数类型为
,并从完成闭包调用此函数[String:Any]
哪一个更好取决于你的应用程序中还发生了什么,以及你在获得数据时需要如何使用这些数据。汤姆·哈林顿是对的。更好的方法是将完成块添加到 func sendGET 像 当您得到json时,调用completion,就是这样
快乐编码总的来说,我觉得现在编写
Swift
程序还为时过早。我想为用C#
编写的iOS移植我的项目,我认为本机应用程序会更好,而且这些闭包有很多陷阱。但是在C#
中,一切都很简单:只需在函数之前编写wait
,但在那里并不总是需要它
感谢所有帮助过我的人
UPD 1
我知道这可能是愚蠢的,但只有这种方法在闭包方面没有不必要的麻烦。但是重复的代码会变得很多
UPD 2
同样不幸的是,我不得不使用GET
而不是POST
,因为在POST
中,服务器没有收到任何数据。我用echo json\u encode($\u POST)检查了它代码>。但我也可能没有使用阿拉莫菲尔
UPD 3
最后,在汤姆·哈林顿的建议下,我找到了一个更好的解决方案。在我找到解决方案之前,它在DispatchQueue.main.async
中不起作用,就像Alamofire.request
(我建议Alamofire
使用main.async
)。因此,我做到了
UPD 4
我又错了。UPD 3中的溶液有时在环体中冻结。我最终决定学习使用自己的补全,我做到了:)
我会给你一个方法。在Swift 4.2的帮助下,已经启动了,因此您可以轻松地解析JSON并删除代码 示例类
public struct Faults: Decodable {
public enum CodingKeys:String,CodingKey{
case guid
case adi
}
public let guid:Int
public let adi:String
}
和json解析(获取web服务)
public func fetchFaults(投诉:@escaping(Result)->Void){
让URL字符串=”http://examples"
请求(urlString,方法:.get,编码:URLEncoding.default,头:…)
.responseData{(响应)in
开关响应。结果{
案例.成功(让数据):
做{
let faults=try Decoders.plainDateDecoder.decode([faults].self,from:data)
抱怨(.success(faults))
}抓住{
投诉(.failure(Error.serializationError(internal:Error)))
}
案例。失败(let错误):
投诉(.failure(Error.networkError(internal:Error)))
}
}
}
对于您的版本,编译器要求添加@escaping
func sendGET(方法:String,数据:[String:String],完成:@escaping([String:Any])->Void)
然后我添加sendGET
完成(res)和Authorize()sendGET(方法:“auth.php”,数据:data){dict in
json.message=dict
}
但断点按相同顺序触发
func sendGET(_ method: String,_ data: [String:String],_ instance: CommonClass, completion : @escaping (Any?)->()) {
let url = getURL(method: method, data: data)
Alamofire.request(url, method: .get).responseJSON { response in
if let status = response.response?.statusCode {
instance.manageStatus(status)
}
if let result = response.result.value {
completion(result)
}
}
}
func someFunc(_ instance: CommonClass) {
let data: [String:String] = ["id":String(id),
"route":route]
sendGET("getTaskData.php", data, instance, completion: { response in
let JSON = response as! [[String:String]]
// Do something with JSON
})
}
public struct Faults: Decodable {
public enum CodingKeys:String,CodingKey{
case guid
case adi
}
public let guid:Int
public let adi:String
}
public func fetchFaults(complation: @escaping (Result<[Faults]>) -> Void) {
let urlString = "http://examples"
request(urlString, method: .get, encoding: URLEncoding.default, headers: ...)
.responseData { (response) in
switch response.result {
case .success(let data):
do {
let faults = try Decoders.plainDateDecoder.decode([Faults].self, from: data)
complation(.success(faults))
} catch{
complation(.failure(Error.serializationError(internal: error)))
}
case .failure(let error):
complation(.failure(Error.networkError(internal: error)))
}
}
}