如何使用 Alamofire 和 SwiftyJSON 保存来自 Json 的数据?
How to save data from Json with Alamofire and SwiftyJSON?
我正在尝试使用这两个库将 "author" 数据从 json(Link:"https://learnappmaking.com/ex/books.json") 保存到名为 "authors" 的全局变量.但它仅适用于 func Alamofire.request(url).responseJSON
的尾随闭包。当我从除尾随闭包之外的某处访问名为 "authors" 的全局变量时,我得到的是一个空字符串数组。
有人能解释一下这种奇怪情况背后的原因吗?
非常感谢。
class ViewController: UIViewController {
var authors = [String]()
let url = "https://learnappmaking.com/ex/books.json"
func getAuthorsCount() {
print("the number of authors : \(authors.count)") // I hope that here, the number of authors should be 3 too! actually, it is 0. Why?
// this for loop doesn't get excuted
for author in authors {
print(author)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
Alamofire.request(url).responseJSON { response in
if let data = response.data {
if let json = try? JSON(data: data) {
for item in json["books"].arrayValue {
var outputString: String
print(item["author"])
outputString = item["author"].stringValue
//urlOfProjectAsset.append(outputString)
self.authors.append(outputString)
print("authors.count: \(self.authors.count)")
}
}
}
}
getAuthorsCount()
print("-------------")
}
}
实际输出为:
更新:
我调整了我的代码:
class ViewController: UIViewController {
var authors = [String]()
let url = "https://learnappmaking.com/ex/books.json"
func getAuthorsCount() {
print("the number of authors : \(authors.count)")
// this for loop doesn't get excuted
for author in authors {
print(author)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
Alamofire.request(url).responseJSON { response in
if let data = response.data {
if let json = try? JSON(data: data) {
for item in json["books"].arrayValue {
var outputString: String
//print(item["author"])
outputString = item["author"].stringValue
//urlOfProjectAsset.append(outputString)
self.authors.append(outputString)
//print("authors.count: \(self.authors.count)")
}
self.getAuthorsCount() // I added this line of code.
}
}
}
getAuthorsCount()
print("-------------")
}
}
但是为什么 func getAuthorsCount()
(不是 self.version)仍然打印一个空的字符串数组?我认为结果应该与结果相同
func self.getAuthorsCount()
已打印。
我现在很迷茫...
同样,我想使用保存在名为 "authors" 的变量中的数据,但我只得到一个空字符串数组。
我会尽力回答您的所有问题:
数据持久化
您正在执行以下操作:Alamo.request(网络调用)-> getAuthors(打印结果 - 空)->
response(接收响应)-> self.authors.append(保存响应)-> self.authors(打印结果)
你需要做:Alamo.request(网络调用)->response(接收响应)->self.authors.append(保存响应)->self.getAuthors或者getAuthors(same)(在响应 {} 内)
得到结果后,您需要在响应回调中调用 getAuthors :
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
Alamofire.request(url).responseJSON { response in
if let data = response.data {
if let json = try? JSON(data: data) {
for item in json["books"].arrayValue {
var outputString: String
print(item["author"])
outputString = item["author"].stringValue
//urlOfProjectAsset.append(outputString)
self.authors.append(outputString)
print("authors.count: \(self.authors.count)")
}
self.getAuthorsCount()
print("-------------")
//Do whatever you want from here : present/push
}
}
}
然后你就可以使用保存的数据了:
- 要将数据发送到另一个 ViewController,您可以使用各种方法(present/push、closure/callback、...)
- 通常你会有一个加载旋转器来等待网络
回答然后你将显示你的下一个控制器
根据直接消息的要求:Swift-only 方法。只需将其粘贴到空白的 Playground 中即可:
import Foundation
final class NetworkService {
enum ServiceError: LocalizedError {
case invalidUrl
case networkingError(error: Error)
case parsingError
var localizedDescription: String? { return String(describing: self) }
}
func request(completion: @escaping (Result<[UserObject], Error>) -> Void ) {
guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else {
completion(.failure(ServiceError.invalidUrl))
return
}
let dataTask = URLSession.shared.dataTask(with: url) { (jsonData, response, error) in
if let jsonData = jsonData {
let jsonDecoder = JSONDecoder()
do {
let users = try jsonDecoder.decode([UserObject].self, from: jsonData)
completion(.success(users))
} catch {
completion(.failure(ServiceError.parsingError))
}
} else if let error = error {
completion(.failure(ServiceError.networkingError(error: error)))
}
}
dataTask.resume()
}
}
struct UserObject: Codable {
let id: Int
let name: String
let username: String
let email: String?
let website: String?
}
let networkService = NetworkService()
networkService.request { result in
switch result {
case .success(let users):
debugPrint("Received \(users.count) users from REST API")
debugPrint(users)
case .failure(let error):
debugPrint(error.localizedDescription)
}
}
我正在尝试使用这两个库将 "author" 数据从 json(Link:"https://learnappmaking.com/ex/books.json") 保存到名为 "authors" 的全局变量.但它仅适用于 func Alamofire.request(url).responseJSON
的尾随闭包。当我从除尾随闭包之外的某处访问名为 "authors" 的全局变量时,我得到的是一个空字符串数组。
有人能解释一下这种奇怪情况背后的原因吗? 非常感谢。
class ViewController: UIViewController {
var authors = [String]()
let url = "https://learnappmaking.com/ex/books.json"
func getAuthorsCount() {
print("the number of authors : \(authors.count)") // I hope that here, the number of authors should be 3 too! actually, it is 0. Why?
// this for loop doesn't get excuted
for author in authors {
print(author)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
Alamofire.request(url).responseJSON { response in
if let data = response.data {
if let json = try? JSON(data: data) {
for item in json["books"].arrayValue {
var outputString: String
print(item["author"])
outputString = item["author"].stringValue
//urlOfProjectAsset.append(outputString)
self.authors.append(outputString)
print("authors.count: \(self.authors.count)")
}
}
}
}
getAuthorsCount()
print("-------------")
}
}
实际输出为:
更新: 我调整了我的代码:
class ViewController: UIViewController {
var authors = [String]()
let url = "https://learnappmaking.com/ex/books.json"
func getAuthorsCount() {
print("the number of authors : \(authors.count)")
// this for loop doesn't get excuted
for author in authors {
print(author)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
Alamofire.request(url).responseJSON { response in
if let data = response.data {
if let json = try? JSON(data: data) {
for item in json["books"].arrayValue {
var outputString: String
//print(item["author"])
outputString = item["author"].stringValue
//urlOfProjectAsset.append(outputString)
self.authors.append(outputString)
//print("authors.count: \(self.authors.count)")
}
self.getAuthorsCount() // I added this line of code.
}
}
}
getAuthorsCount()
print("-------------")
}
}
但是为什么 func getAuthorsCount()
(不是 self.version)仍然打印一个空的字符串数组?我认为结果应该与结果相同
func self.getAuthorsCount()
已打印。
我现在很迷茫...
同样,我想使用保存在名为 "authors" 的变量中的数据,但我只得到一个空字符串数组。
我会尽力回答您的所有问题:
数据持久化
您正在执行以下操作:Alamo.request(网络调用)-> getAuthors(打印结果 - 空)-> response(接收响应)-> self.authors.append(保存响应)-> self.authors(打印结果)
你需要做:Alamo.request(网络调用)->response(接收响应)->self.authors.append(保存响应)->self.getAuthors或者getAuthors(same)(在响应 {} 内)
得到结果后,您需要在响应回调中调用 getAuthors :
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
Alamofire.request(url).responseJSON { response in
if let data = response.data {
if let json = try? JSON(data: data) {
for item in json["books"].arrayValue {
var outputString: String
print(item["author"])
outputString = item["author"].stringValue
//urlOfProjectAsset.append(outputString)
self.authors.append(outputString)
print("authors.count: \(self.authors.count)")
}
self.getAuthorsCount()
print("-------------")
//Do whatever you want from here : present/push
}
}
}
然后你就可以使用保存的数据了:
- 要将数据发送到另一个 ViewController,您可以使用各种方法(present/push、closure/callback、...)
- 通常你会有一个加载旋转器来等待网络 回答然后你将显示你的下一个控制器
根据直接消息的要求:Swift-only 方法。只需将其粘贴到空白的 Playground 中即可:
import Foundation
final class NetworkService {
enum ServiceError: LocalizedError {
case invalidUrl
case networkingError(error: Error)
case parsingError
var localizedDescription: String? { return String(describing: self) }
}
func request(completion: @escaping (Result<[UserObject], Error>) -> Void ) {
guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else {
completion(.failure(ServiceError.invalidUrl))
return
}
let dataTask = URLSession.shared.dataTask(with: url) { (jsonData, response, error) in
if let jsonData = jsonData {
let jsonDecoder = JSONDecoder()
do {
let users = try jsonDecoder.decode([UserObject].self, from: jsonData)
completion(.success(users))
} catch {
completion(.failure(ServiceError.parsingError))
}
} else if let error = error {
completion(.failure(ServiceError.networkingError(error: error)))
}
}
dataTask.resume()
}
}
struct UserObject: Codable {
let id: Int
let name: String
let username: String
let email: String?
let website: String?
}
let networkService = NetworkService()
networkService.request { result in
switch result {
case .success(let users):
debugPrint("Received \(users.count) users from REST API")
debugPrint(users)
case .failure(let error):
debugPrint(error.localizedDescription)
}
}