如何保存响应 JSON 数组并在 swift 中使用用户默认值进行检索
Posted
技术标签:
【中文标题】如何保存响应 JSON 数组并在 swift 中使用用户默认值进行检索【英文标题】:How to save response JSON array and retrieve using user default in swift 【发布时间】:2018-12-18 06:05:26 【问题描述】:我想将 kode_pelaksanaan 保存在用户默认值中,并使用 SwiftyJSON 和 Alamofire 在第二个视图控制器中检索它。 这是我的代码
class ListSelfLearningViewController: UIViewController
@IBOutlet weak var collectionView: UICollectionView!
var listSelfLearning: [ListSelfLearningModel] = []
override func viewDidLoad()
super.viewDidLoad()
fetchData()
extension ListSelfLearningViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return self.listSelfLearning.count
func numberOfSections(in collectionView: UICollectionView) -> Int
return 1
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ListSelfLearningCollectionViewCell", for: indexPath) as! ListSelfLearningCollectionViewCell
//cell.profileIv.image = listSelfLearning[indexPath.row].listImage
cell.profileIv.sd_setImage(with: URL(string: listSelfLearning[indexPath.row].listImage))
cell.title.text = listSelfLearning[indexPath.row].labelName
return cell
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
return CGSize.init(width: UIScreen.main.bounds.width - 20, height: 250)
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
let storyboard: UIStoryboard = UIStoryboard(name: "Home", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ListActivityViewController") as! ListActivityViewController
navigationController?.pushViewController(vc, animated: true)
func fetchData()
DispatchQueue.main.async
let url = URLs.listImage
guard let user = helper.getApiUser() else return
guard let token = helper.getApiToken() else return
let parameter = [
"request": "\"requestMethod\":\"list_selflearning\",\"user\":\"\(user)\""
]
let headers: HTTPHeaders = [
"Content-Type" : "application/x-www-form-urlencoded",
"Authorization" : "Bearer \(token)"
]
Alamofire.request(url, method: .post, parameters: parameter, headers: headers).responseJSON(completionHandler: (response) in
switch response.result
case .success(let value):
let json = JSON(value)
if let data = json["responseData"].array
for item in data
let images = item["image_detail"]["path_image"].string
let namaPelaksana = item["nama_pelaksanaan"].string
if let kode_pelaksanaan = item["kode_pelaksanaan"].string
helper.saveKodePelaksanaan(kode_pelaksanaan: kode_pelaksanaan)
print("nilai kode pelaksanaan: \(kode_pelaksanaan)")
let listData = ListSelfLearningModel(listImage: images!, labelName: namaPelaksana!)
self.listSelfLearning.append(listData)
self.collectionView.reloadData()
case .failure(let error):
print(error)
)
打印用户默认时的输出:
nilai kode pelaksanaan: ELR2018120005
nilai kode pelaksanaan: ELR2018120004
nilai kode pelaksanaan: ELR2018120003
nilai kode pelaksanaan: ELR2018120001
nilai kode pelaksanaan: ELR2018050004
但是当我在第二类中检索参数时,却没有像保存在 Userdefault 中那样得到输出。
这是我在第二个视图控制器中的代码:
import UIKit
import SwiftyJSON
import Alamofire
import SDWebImage
class ListActivityViewController: UIViewController
@IBOutlet weak var tableView: UITableView!
var listActivity: [ListActivity] = []
override func viewDidLoad()
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view.
let nibCell = UINib(nibName: "ListActivityTableViewCell", bundle: nil)
tableView.register(nibCell, forCellReuseIdentifier: "ListActivityTableViewCell")
fetchData()
extension ListActivityViewController: UITableViewDataSource, UITableViewDelegate
func numberOfSections(in tableView: UITableView) -> Int
return 1
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return listActivity.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "ListActivityTableViewCell", for: indexPath) as! ListActivityTableViewCell
cell.title.text = listActivity[indexPath.row].pathImage
return cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
let segueIdentifier: String
switch indexPath.section
case 0:
segueIdentifier = "webView"
case 1:
segueIdentifier = "ujian"
default:
segueIdentifier = ""
self.performSegue(withIdentifier: segueIdentifier, sender: self)
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
let indexPath = self.tableView.indexPathForSelectedRow
switch indexPath?.section
case 0:
let vc = segue.destination as! DetailPdfViewController
let user = listActivity[(indexPath?.row)!]
vc.webSite = user.pathPdf
default:
break
func fetchData()
DispatchQueue.main.async
let url = URLs.listActivity
guard let user = helper.getApiUser() else return
guard let token = helper.getApiToken() else return
guard let kodePelaksanaan = helper.getKodePelaksanaan() else return
print(kodePelaksanaan)
let parameter = [
"request" : "\"requestMethod\":\"detail_selflearning\",\"user\":\"\(user)\",\"kode_pelaksanaan\":\"\(kodePelaksanaan)\""
]
let headers: HTTPHeaders = [
"Content-Type" : "application/x-www-form-urlencoded",
"Authorization" : "Bearer \(token)"
]
Alamofire.request(url, method: .post, parameters: parameter, encoding: URLEncoding.default, headers: headers).responseJSON(completionHandler: (response) in
switch response.result
case .success(let value):
let json = JSON(value)
let data1 = json["responseData"]["data"]["materi_selflearning"]
for item in data1.array!
if (item["jenis_materi"] == "2" || item["jenis_materi"] == "3" || item["jenis_materi"] == "99")
let image_detail = item["nama_pelaksanaan"].stringValue
let pdfDetail = item["path_file"].stringValue
let listActivitied = ListActivity(pathImage: image_detail, pathPdf: pdfDetail)
self.listActivity.append(listActivitied)
self.tableView.reloadData()
case .failure(let error):
print(error)
)
这是我在第二个视图控制器中得到的输出:
nilai kode pelaksanaan: ELR2018050004
我想像这样在第二个视图控制器中获得输出:
nilai kode pelaksanaan: ELR2018120005
nilai kode pelaksanaan: ELR2018120004
nilai kode pelaksanaan: ELR2018120003
nilai kode pelaksanaan: ELR2018120001
nilai kode pelaksanaan: ELR2018050004
这是我的班级助手:
class helper: NSObject
class func saveKodePelaksanaan(kode_pelaksanaan: String)
let def = UserDefaults.standard
def.set(kode_pelaksanaan, forKey: "kode_pelaksanaan")
def.synchronize()
class func getKodePelaksanaan() -> String?
let def = UserDefaults.standard
return def.object(forKey: "kode_pelaksanaan") as? String
【问题讨论】:
您正在使用相同的key
将项目(字符串值)一一保存到UserDefaults
。因此,当您保存第二个字符串时,它会因为相同的键替换前一个字符串。因此,UserDefaults
中键 "kode_pelaksanaan"
的值是数组中的最后一个字符串。所以你需要将Array
保存为一个整体并检索Array
作为一个整体,否则你将不会得到相同的值。
那么如何将数组保存为一个整体并检索该数组整体呢?
save and retrieve array to user default using swift的可能重复
【参考方案1】:
希望这条消息能找到你
您正在尝试仅保存一个字符串,如下面的函数所示:-
class func saveKodePelaksanaan(kode_pelaksanaan: String)
let def = UserDefaults.standard
def.set(kode_pelaksanaan, forKey: "kode_pelaksanaan")
def.synchronize()
但函数参数中应该有字典或数组,如下所示
class func saveKodePelaksanaan(kode_pelaksanaan: array)
let def = UserDefaults.standard
def.set(kode_pelaksanaan, forKey: "kode_pelaksanaan")
def.synchronize()
// 或
class func saveKodePelaksanaan(kode_pelaksanaan: dictionary)
let def = UserDefaults.standard
def.set(kode_pelaksanaan, forKey: "kode_pelaksanaan")
def.synchronize()
你也应该在你的 for 循环完成时调用辅助类函数,而不是在循环执行时调用它自己,如下所示:-
func fetchData()
DispatchQueue.main.async
let url = URLs.listImage
guard let user = helper.getApiUser() else return
guard let token = helper.getApiToken() else return
let parameter = [
"request": "\"requestMethod\":\"list_selflearning\",\"user\":\"\(user)\""
]
let headers: HTTPHeaders = [
"Content-Type" : "application/x-www-form-urlencoded",
"Authorization" : "Bearer \(token)"
]
Alamofire.request(url, method: .post, parameters: parameter, headers: headers).responseJSON(completionHandler: (response) in
switch response.result
case .success(let value):
let json = JSON(value)
if let data = json["responseData"].array
for item in data
let images = item["image_detail"]["path_image"].string
let namaPelaksana = item["nama_pelaksanaan"].string
let listData = ListSelfLearningModel(listImage: images!, labelName: namaPelaksana!)
self.listSelfLearning.append(listData)
// Changes are made here
helper.saveKodePelaksanaan(kode_pelaksanaan: self.listSelfLearning)
self.collectionView.reloadData()
case .failure(let error):
print(error)
)
如果你有任何问题,请与我分享,我会尽快更新。
【讨论】:
我收到错误我像这样更改 userDefault:class func saveKodePelaksanaan(kode_pelaksanaan: Array) let def = UserDefaults.standard def.set(kode_pelaksanaan, forKey: "kode_pelaksanaan") def.synchronize () // 此处进行更改 helper.saveKodePelaksanaan(kode_pelaksanaan: self.listSelfLearning) 这个错误:作为键 kode_pelaksanaan 的 NSUserDefaults/CFPreferences 值 2018-12-18 13:57:13.124702+0700 BRISMART[4211:140578] *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序', 原因:'尝试插入非属性列表对象(“BRISMART.ListSelfLearningModel(listImage: \"1.142.17.3/edu/uploads/ms_image/brismart_logo.png\", labelName: \"SIT\")")为关键kode_pelaksanaan' 亲爱的 edo oktarifa,这是因为您传递了 Modal 数组( ListSelfLearningModel )。你能把你的项目发给我,这样我就可以做所有必要的更改并在每一行添加注释,否则你可以将你的数组传递给字典并保存该字典。 当然,我怎么能发给你。?通过电子邮件或 github? 我的邮箱是harmansjpp@gmail.com,或者你可以在github上与我分享,我的github id是harmansjpp@gmail.com,我的github用户名是harmandeep97等待项目【参考方案2】:您可以使用SwiftyUserDefaults
【讨论】:
以上是关于如何保存响应 JSON 数组并在 swift 中使用用户默认值进行检索的主要内容,如果未能解决你的问题,请参考以下文章
Swift:写入 JSON 并在本地保存到 iPhone 文件
如何将用户登录的 JSON 响应保存到 Core Data 中以跟踪 Swift 中的用户状态?
AFNetworking 和 Swift - 保存 json 响应