我正在创建一个应用程序来解析学生信息的SQL数据库并以JSON格式返回数据。它有一个学生名称的TableView,当你点击一个名字时,它会带你到另一个有更多信息的ViewController。获得数据后,我希望用户能够在应用程序中编辑它,这是通过HTTP Post请求完成的。
然而,一旦Post请求成功,我就无法弄清楚如何“刷新”或重新加载应用程序以便显示新的/更新的数据。截至目前,我必须重新启动应用程序,以便更改显示在TableView和“更多信息”ViewController中(例如,如果我将学生的名字从“Bob”更改为“Joe”,它将会仍然会说“鲍勃”,直到下次我运行应用程序)。我有很多代码,所以我会尝试只发布重要的部分:
HandleData.swift(发生JSON解析等)
func downloadItems() {
let url:URL = URL(string: urlAddress)!
var urlSession:Foundation.URLSession!
let config = URLSessionConfiguration.default
urlSession = Foundation.URLSession(configuration: config, delegate: self, delegateQueue: nil)
let task = urlSession.dataTask(with: url)
task.resume()
}
func URLSession(_ session: Foundation.URLSession, dataTask: URLSessionDataTask, didReceiveData data: Data) {
self.data.append(data);
}
func URLSession(_ session: Foundation.URLSession, task: URLSessionTask, didCompleteWithError error: NSError?) {
if error != nil {
print("Download of data failed.")
}
else {
print("Data downloaded successfully!")
self.parseJSON()
}
}
func parseJSON() {
var jsonResult:NSMutableArray = NSMutableArray()
do {
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSMutableArray
}
catch let error as NSError {
print(error)
}
var jsonElement:NSDictionary = NSDictionary()
let locations:NSMutableArray = NSMutableArray()
for i in 0 ..< jsonResult.count {
jsonElement = jsonResult[i] as! NSDictionary
let location = StoreData()
let studentID = jsonElement["StudentId"] as? String
let lastName = jsonElement["LastName"] as? String
let firstName = jsonElement["FirstName"] as? String
let major = jsonElement["Major"] as? String
let year = jsonElement["Year"] as? String
let gpa = jsonElement["GPA"] as? Double
location.studentID = studentID
location.lastName = lastName
location.firstName = firstName
location.major = major
location.year = year
location.gpa = gpa
locations.add(location)
}
DispatchQueue.main.async(execute: { () -> Void in
self.delegate.itemsDownloaded(locations)
})
}
DetailViewController.swift(“更多信息”屏幕)
func editData() {
var request = URLRequest(url: URL(string: "http://csmadison.dhcp.bsu.edu/~vjtanksale/cs320/updatestudents.php")!)
request.httpMethod = "POST"
let postString = "StudentId=\(idTB.text!)&FirstName=\(nameTB.text!)&LastName=\(lastNameTB.text!)&Major=\(majorTB.text!)&Year=\(yearTB.text!)&GPA=\(gpaTB.text!)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("Error = \(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("The status code is \(httpStatus.statusCode)")
print("Response = \(response)")
}
let responseString = String(data: data, encoding: .utf8)
print("Response String = \(responseString!)")
}
task.resume()
}
//Below is the function for the "Done" button that the user taps when they're finished editing a particular student's information
@IBAction func donePressed(_ sender: Any) {
editData()
}
ViewController.swift
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, HandleDataProtocol {
var studentItems:NSArray = NSArray()
var storeData:StoreData = StoreData()
var handleData = HandleData()
@IBOutlet var studentsTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.studentsTable.delegate = self
self.studentsTable.dataSource = self
handleData = HandleData()
handleData.delegate = self
handleData.downloadItems()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func itemsDownloaded(_ items: NSArray) {
studentItems = items
self.studentsTable.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return studentItems.count
}
答案 0 :(得分:1)
您可以使用UITableView
重新加载整个reloadRowsAtIndexPaths
或仅重新加载所需的单元格。
到目前为止,我在您的代码中看到,您在请求完成时使用委托模式进行通知,请记住您也可以使用闭包来实现此目的。如果您未将代理引用声明为weak
,则需要谨慎使用委托并保留周期。
正如@ Tj3n在他的评论中指出的那样,正常的过程应该是在你使用CoreData,Realm,Firebase,MySQL或其他你想要的一些持久层中保存来自API的数据(NSUserDefaults
不适用于当你发出另一个更改数据的请求时,如果你在持久层中保存了数据,你需要通知每个人正在使用你的模型来更改数据。
如果您不想使用上面提到的任何库来通知模型中的更改,您可以使用委托,KVO或使用NSNotificationCenter
的观察者模式。尽管如此,Firebase和Realm可以很容易地为您实现有关模型更改的通知。
来自LinkedIn和Pinterest的这两篇文章展示了如何使用不可变模型处理它的非常好的解释。
我强烈建议您使用的另一件事是在某些服务中隔离您的请求,从而删除DetailViewController
中的依赖项。这使您的代码更难以测试。
我的解释缺乏示例代码,但我想你会发现很多关于如何在网络中使用CoreData,Realm,Firebase以及在SO中使用的示例。
我希望这对你有所帮助。