UITableView使用NSURLConnection - 异步装载的NSMutableArray刷新问题

时间:2015-02-20 07:46:46

标签: ios uitableview swift nsurlconnection master-detail

我目前正在接近Swift(我已经在Objective-C编写了多年)并且我正在尝试为我的视频监控系统开发一个配套应用程序。

我的应用做的是:

  1. 连接到受密码保护的网站,并获取上述三个现有ip摄像头中的任何一个上传的最新快照列表。
  2. 对于每个镜头,我创建一个带有临时图片的PicInfo对象。然后我尝试异步下载图片并将它们存储在UIImage属性中。
  3. 从那里开始,我在MasterViewController中有一些原型单元格,其中包含一些细节。触摸一个会让我在DetailViewController中看到更大的视图。
  4. 我还实现了刷新,我重新加载完整列表并替换最后100个表格单元格和NSMutable数组的内容。

    当前问题:

    1. 初始加载后,主表视图显示为空,直到我轻轻触摸它。
    2. 虽然NSLog ^ Wprintln语句显示列表已成功重新加载,但表格不会刷新,它仍会显示等待的小部件......
    3. 我得到了一些麻烦的包装和#34;将NSData放入我的UIImages中的错误(或者我认为:消息不是更明确),否则显示正常。
    4. 我做错了什么?

      PicInfo.swift

      import Foundation
      import UIKit
      
      class PicInfo {
          var index: Int = 0
          var description: String = ""
          var stamp: String = ""
          var url: String = ""
          var image: UIImage!
          var downloaded: Bool = false;
          var downloading: Bool = false;
      
          init(data: String) {
              var picInfos=data.componentsSeparatedByString("\t")
              println("found: \(picInfos[0]): [\(picInfos[2])] taken at \(picInfos[1])")
              self.index = picInfos[0].toInt()!
              self.url = baseUrlString + "/" + picInfos[2]
              self.stamp = picInfos[1]
              description = ""
              if (picInfos[2].rangeOfString("HALLCAM") != nil) {
                  description="Hall"
              } else if (picInfos[2].rangeOfString("STAIRSCAM") != nil) {
                  description="Garden"
              } else {
                  description="Cats"
              }
              self.image = UIImage(named: "nothingyet")
              self.loadImage()
          }
      
          func URL() -> NSURL {
              var URL=NSURL(string: self.url)
              return URL!
          }
      
          func loadImage() {
              if (self.downloading) {
                  return
              }
              let url = self.URL()
              let request = NSMutableURLRequest(URL: url)
              let loginString = NSString(format: "%@:%@", username, password)
              let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
              let base64LoginString = loginData.base64EncodedStringWithOptions(nil)
      
              // create the request
              request.HTTPMethod = "POST"
              request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization")
              self.downloading = true
              NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void in
                  if error == nil {
                      if let blob = data {
                          self.image = UIImage(data: data)
                          self.downloaded = true
                      }
                  }
                  else {
                      println("Error: \(error.localizedDescription)")
                  }
                  self.downloading = false
              })
          }
      }
      

      MasterViewController.swift

      import UIKit
      
      let baseUrlString = "http://my.domain.net"
      let username = "OoOoOoOoO"
      let password = "xXxXxXxXx"
      
      class MasterViewController: UITableViewController,NSURLConnectionDataDelegate{
      
          var detailViewController: DetailViewController!
          var objects = NSMutableArray()
          var loading: Bool = false;
      
          override func awakeFromNib() {
              super.awakeFromNib()
              if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
                  self.clearsSelectionOnViewWillAppear = false
                  self.preferredContentSize = CGSize(width: 320.0, height: 600.0)
              }
          }
      
          override func viewDidLoad() {
              super.viewDidLoad()
              if let split = self.splitViewController {
                  let controllers = split.viewControllers
                  self.detailViewController = controllers[controllers.count-1].topViewController as? DetailViewController
                  self.detailViewController.picInfos = self.objects;
              }
              self.refreshControl?.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
              self.loadPictureList()
          }
      
          override func didReceiveMemoryWarning() {
              super.didReceiveMemoryWarning()
              // Dispose of any resources that can be recreated.
          }
      
          func insertNewObject(data: String) {
              var picInfo=PicInfo(data: data)
              objects.insertObject(picInfo, atIndex: picInfo.index)
              let indexPath = NSIndexPath(forRow: picInfo.index, inSection: 0)
              self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
          }
      
          // MARK: - Segues
      
          override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
              if segue.identifier == "showDetail" {
                  if let indexPath = self.tableView.indexPathForSelectedRow() {
                      let object = objects[indexPath.row] as PicInfo
                      println("following segue: \(indexPath.row) => \(object.index)")
                      let controller = (segue.destinationViewController as UINavigationController).topViewController as DetailViewController
                      controller.detailItem = object
                      controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
                      controller.navigationItem.leftItemsSupplementBackButton = true
                  }
              }
          }
      
          // MARK: - Table View
      
          override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
              return 1
          }
      
          override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
              return objects.count
          }
      
          override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
      
              let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
      
              if let object = objects[indexPath.row] as? PicInfo {
                  var todo=""
                  if (object.downloading || !object.downloaded) {
                      todo="(*)"
                  }
                  cell.textLabel!.text = "\(object.index): \(object.description)\(todo)"
                  cell.detailTextLabel?.text = object.stamp
                  if (!object.downloaded) {
                      object.loadImage()
                  }
                  cell.imageView?.image = object.image
              }
              return cell
          }
      
          override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
              // Return false if you do not want the specified item to be editable.
              return false
          }
      
          // MARK: - Refresh
          func refresh(sender:AnyObject)
          {
              // Updating your data here...
              self.loadPictureList()
          }
      
          // MARK: Internet stuff
      
          func loadPictureList () {
              // set up the base64-encoded credentials
              if (self.loading) {
                  return
              }
              self.loading = true
              let config = NSURLSessionConfiguration.defaultSessionConfiguration()
              let loginString = NSString(format: "%@:%@", username, password)
              let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
              let base64LoginString = loginData.base64EncodedStringWithOptions(nil)
              let authString = "Basic \(base64LoginString)"
              config.HTTPAdditionalHeaders = ["Authorization" : authString]
              let session = NSURLSession(configuration: config)
      
              // create the request
              let url = NSURL(string: baseUrlString + "/latest.php")
              let request = NSMutableURLRequest(URL: url!)
      
              // fire off the request
              var task = session.dataTaskWithURL(url!){
                  (data, response, error) -> Void in
                  if error != nil {
                      self.handlePictureList("", encounteredProblem:"\(error.localizedDescription)\nurl:\(url)")
                  } else {
                      var result = NSString(data: data, encoding: NSASCIIStringEncoding)!
                      self.handlePictureList(result, encounteredProblem:"")
                  }
              }
              task.resume()
      
          }
      
          func handlePictureList (data: NSString, encounteredProblem error: NSString) {
              if (error.length>0) {
                  println ("Had error: [\(error)]")
              } else {
                  println ("Got data!")
                  println("Refresh will start")
                  self.tableView.beginUpdates()
                  for o in objects {
                      let p = o as PicInfo
                      var i=NSIndexPath(forRow: p.index, inSection: 0)
                      self.tableView.deleteRowsAtIndexPaths([i], withRowAnimation: UITableViewRowAnimation.Fade)
                      objects.removeObject(o)
      
                  }
                  var pixArr = data.componentsSeparatedByString("\n")
                  for unparsedPicInfo in pixArr {
                      if (unparsedPicInfo.hasPrefix("<tr>")) {
                          var picInfo=unparsedPicInfo.stringByReplacingOccurrencesOfString("<tr><td>", withString: "")
                          picInfo=picInfo.stringByReplacingOccurrencesOfString("</td></tr>", withString: "")
                          picInfo=picInfo.stringByReplacingOccurrencesOfString("</td><td>", withString: "\t")
                          self.insertNewObject(picInfo)
                      }
                  }
                  self.loading = false
                  self.tableView.endUpdates()
                  self.tableView.reloadData()
                  println("Refresh is over")
              }
              return
          }
      }
      

      DetailViewController.swift

      import UIKit
      
      class DetailViewController: UIViewController {
      
          @IBOutlet weak var detailDescriptionLabel: UILabel!
          @IBOutlet weak var pictureView: UIImageView!
          @IBOutlet weak var progressView: UIProgressView!
      
          var picInfos: NSMutableArray!
      
          var detailItem: AnyObject? {
              didSet {
                  // Update the view.
                  if let detail = detailItem as? PicInfo {
                  println("Preparing to display object#\(detail.index)")
                  } else {
                      println("Bizarre?!")
                  }
                  self.configureView()
              }
          }
      
          func configureView() {
              // Update the user interface for the detail item.
              if let detail = detailItem as? PicInfo {
                  if let label = self.detailDescriptionLabel {
                      var todo=""
                      if (detail.downloading || !detail.downloaded) {
                          todo="(*)"
                      }
                      label.text = "\(detail.index): \(detail.description)\(todo)"
                  }
                  self.title = detail.stamp
                  if let proVi = self.progressView {
                      if let pi = self.picInfos {
                      var total = pi.count
                          if ( total==0 ) {
                              total=1
                          }
                          proVi.setProgress( Float(Double(detail.index) / Double(total)), animated: true)
                      }
                  }
                  if let img = self.pictureView {
                      if (!detail.downloaded) {
                          detail.loadImage()
                      }
                      img.image = detail.image
                  }
              }
          }
      
          override func viewDidLoad() {
              super.viewDidLoad()
              // Do any additional setup after loading the view, typically from a nib.
              self.configureView()
          }
      
          override func didReceiveMemoryWarning() {
              super.didReceiveMemoryWarning()
              // Dispose of any resources that can be recreated.
          }
      }
      

      提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我切换到Core Data以获得一些灵活性。