2016-11-15 15 views
1

私は学生情報のSQLデータベースを解析し、JSON形式でデータを返すアプリケーションを作成しています。これには学生名のTableViewがあり、名前をタップすると詳細情報を持つ別のViewControllerに移動します。データを取得したら、ユーザーがアプリ内で編集できるようにしたいと思っています。これはHTTP Postリクエストで行います。スウィフトでのHTTP投稿要求後のアプリケーションの「更新」?

しかし、一度Postリクエストが成功すると、新しい/更新されたデータが表示されるようにアプリを「リフレッシュ」またはリロードする方法がわかりません。現在のところ、変更をTableViewと "詳細情報" ViewControllerに表示するには、アプリを再起動する必要があります(例:学生の名前を「Bob」から「Joe」に変更すると次回アプリを実行するまでは "Bob"と言います)。私は多くのコードを持っているので、私は重要な部分のみ投稿しようとするでしょう:(パースJSONなどが発生した)

HandleData.swift

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

'UITableView'全体、または' reloadRowsAtIndexPaths'を使って必要なセルだけをリロードすることができます。 –

+0

@VictorSigler残念ながら、それはまだ同じJSONからデータを取得しているので機能しませんので、どうにかして編集したものを「再解析」する必要があります。 –

+0

'NSUserDefault'や' CoreData'や 'Realm'を使ってデータを永続化する方法を学んでください – Tj3n

答えて

1

あなたは全体をリロードすることができます0を使用するか、reloadRowsAtIndexPathsを使用してほしいセルだけを選択します。

あなたがコードで見たところでは、依頼が完了したときに通知するためにデリゲートパターンを使用していますが、クロージャを使用することもできます。デリゲート参照をweakと宣言していない場合は、デリゲートの使用に注意してサイクルを保持する必要があります。

@ Tj3nは彼のコメントで、CoreData、Realm、Firebase、MySQLなどを使用しているいくつかの永続化層にAPIからのデータを保存する必要があることを指摘しています(NSUserDefaultsはその種のストレージ).aデータを変更する要求をしたときに、パーシスタンス層にデータを保存したら、誰もが変更をモデルにしてデータを読み込んでいることを通知する必要があります。

モデルの変更について通知するために上記のライブラリを使用しない場合は、代理人、KVO、またはNSNotificationCenterを使用するオブザーバパターンを使用できます。それにもかかわらず、FirebaseとRealmはモデルの変更に関する通知を簡単に実装します。

LinkedInとPinterestのこれらの2つの記事は、不変モデルを使用してそれを処理する方法の非常に良い説明を示しています。

私は強くあなたをお勧めしますもう一つは、あなたのDetailViewControllerに依存関係を削除するいくつかのサービスであなたの要求を隔離です。これにより、コードをテストするのが難しくなります。

私の説明にはサンプルコードがありませんが、WebでCoreData、Realm、Firebaseを使用する方法のサンプルがたくさんあると思います。

私はこれがあなたに役立つことを願っています。

+0

詳細な答えをありがとう!私はCoreDataを使ってみましたが、それは必要ではないことが判明しました。私がしなければならなかったのは、いくつかのコードを切り替えて、代わりに 'viewDidAppear()'メソッドに入れたことでした。情報が適切に更新されるようになりました。とにかくありがとう、私はそれを感謝します!あなたは私に新しいものを学ぶのを手伝った。 –

+0

@JustinWithamあなたの問題を解決し、新しいことを学んだことを知ってうれしいです:) –

関連する問題