2014-06-09 6 views
47

içinde çalışıyorum & aynı zamanda iOS dev'in temellerini öğrenmeye çalışıyorum, yani benimle kal. İlk olarak bir yerel JSON dosyasını ayrıştırma ve TableViewCell ve SectionHeaderViews içine çok basit bir veri oluşturma bir TableViewController var. Aynı TableViewController içinde, veriyi döndüren JSON uç noktasına bir çağrı yapıyorum, bu da daha sonra değişkenlere ayarlıyorum, böylece gerçekten almak istediklerime erişebiliyorum (API yapısı arzu edilenin altında değil). Sonunda, self.tableData olarak uygun verileri ayarladıktan sonra self.tableView.reloadData()'u arayın, ancak hiçbir şey olmuyor. Ne verir?self.tableView.reloadData(), Swift

import UIKit 

class BusinessTableViewController: UITableViewController { 

    var data: NSMutableData = NSMutableData() 
    var tableData: NSArray = NSArray() 

    @lazy var Business: NSArray = { 
     let pathTCT = NSBundle.mainBundle().pathForResource("TCT", ofType: "json") 
     let data = NSData.dataWithContentsOfFile(pathTCT, options: nil, error: nil) 
     return NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as NSArray 
     }() 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     navigationItem.titleView = UIImageView(image: UIImage(named: "growler")) 

     tableView.registerClass(BeerTableViewCell.self, forCellReuseIdentifier: "cell") 
     tableView.separatorStyle = .None 

     fetchKimono() 
    } 

    override func numberOfSectionsInTableView(tableView: UITableView!) -> Int { 
//  return Business.count 
     return 1 
    } 

    override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int { 
     let biz = Business[section] as NSDictionary 
     let results = biz["results"] as NSDictionary 
     let beers = results["collection1"] as NSArray 
     return beers.count 
    } 

    override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? { 
     let cell = tableView!.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath!) as BeerTableViewCell 
     if let path = indexPath { 
      let biz = Business[path.section] as NSDictionary 
      let results = biz["results"] as NSDictionary 
      let beers = results["collection1"] as NSArray 
      let beer = beers[path.row] as NSDictionary 

      cell.titleLabel.text = beer["BeerName"] as String 
     } 

     return cell 
    } 

    override func tableView(tableView: UITableView!, titleForHeaderInSection section: Int) -> String! { 
     let biz = Business[section] as NSDictionary 
     return biz["name"] as String 
    } 

    override func tableView(tableView: UITableView!, viewForHeaderInSection section: Int) -> UIView! { 
     let biz = Business[section] as NSDictionary 
     let view = LocationHeaderView() 
     view.titleLabel.text = (biz["name"] as String).uppercaseString 
     return view 
    } 

    override func tableView(tableView: UITableView!, heightForHeaderInSection section: Int) -> CGFloat { 
     return 45 
    } 

    func fetchKimono() { 
     var urlPath = "names have been changed to protect the innocent" 
     var url: NSURL = NSURL(string: urlPath) 
     var request: NSURLRequest = NSURLRequest(URL: url) 
     var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false) 

     connection.start() 
    } 

    func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) { 
     // Recieved a new request, clear out the data object 
     self.data = NSMutableData() 
    } 

    func connection(connection: NSURLConnection!, didReceiveData data: NSData!) { 
     // Append the recieved chunk of data to our data object 
     self.data.appendData(data) 
    } 

    func connectionDidFinishLoading(connection: NSURLConnection!) { 
     // Request complete, self.data should now hold the resulting info 
     // Convert the retrieved data in to an object through JSON deserialization 
     var err: NSError 
     var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary 
     var results: NSDictionary = jsonResult["results"] as NSDictionary 
     var collection: NSArray = results["collection1"] as NSArray 
     if jsonResult.count>0 && collection.count>0 { 
      var results: NSArray = collection as NSArray 
      self.tableData = results 
      self.tableView.reloadData() 
     } 
    } 
} 
+0

Swift Yani, benim ilk hata İş aslında getirilen davranıyor JSON maç için, bir NSDictionary olması gerekiyor. Bu tüm değişkenleri ortadan kaldırır. Ikinci hata ben self.tableData gerekmez, ben Business = jsonResults gerekir - ama şimdi bir bellek hatası alıyorum. Ben dealloc veya deinitialize ihtiyacım var mı? – chandlervdw

+0

Lütfen en son kodunuzu gönderin – Dash

+0

@Dash cevabımı aşağıya ekledi. – chandlervdw

cevap

1

Yani, mesele ben uygunsuz benim İş değişken esasen sabit edilir ve dolayısıyla düzenlenemez olmasını neden olan, @lazy kullanmaya çalışıyor olmasıydı. Ayrıca, yerel json'u yüklemek yerine, şimdi yalnızca API'den döndürülen verileri yüklüyorum.

import UIKit 

class BusinessTableViewController: UITableViewController { 

    var data: NSMutableData = NSMutableData() 
    var Business: NSMutableArray = NSMutableArray() 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     navigationItem.titleView = UIImageView(image: UIImage(named: "growler")) 

     tableView.registerClass(BeerTableViewCell.self, forCellReuseIdentifier: "cell") 
     tableView.separatorStyle = .None 

     fetchKimono() 
    } 

    override func numberOfSectionsInTableView(tableView: UITableView!) -> Int { 
     return Business.count 
    } 

    override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int { 
     if (Business.count > 0) { 
      let biz = Business[section] as NSDictionary 
      let beers = biz["results"] as NSArray 
      return beers.count 
     } else { 
      return 0; 
     } 
    } 

    override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? { 
     let cell = tableView!.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath!) as BeerTableViewCell 
     if let path = indexPath { 
      let biz = Business[path.section] as NSDictionary 
      let beers = biz["results"] as NSArray 
      let beer = beers[path.row] as NSDictionary 

      cell.titleLabel.text = beer["BeerName"] as String 
     } else { 
      cell.titleLabel.text = "Loading" 
     } 

     return cell 
    } 

    override func tableView(tableView: UITableView!, viewForHeaderInSection section: Int) -> UIView! { 
     let view = LocationHeaderView() 
     let biz = Business[section] as NSDictionary 
     if (Business.count > 0) { 
      let count = "\(Business.count)" 
      view.titleLabel.text = (biz["name"] as String).uppercaseString 
     } 
     return view 
    } 

    override func tableView(tableView: UITableView!, heightForHeaderInSection section: Int) -> CGFloat { 
     return 45 
    } 

    func fetchKimono() { 
     var urlPath = "names have been removed to protect the innocent" 
     var url: NSURL = NSURL(string: urlPath) 
     var request: NSURLRequest = NSURLRequest(URL: url) 
     var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false) 

     connection.start() 
    } 

    func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) { 
     // Recieved a new request, clear out the data object 
     self.data = NSMutableData() 
    } 

    func connection(connection: NSURLConnection!, didReceiveData data: NSData!) { 
     // Append the recieved chunk of data to our data object 
     self.data.appendData(data) 
    } 

    func connectionDidFinishLoading(connection: NSURLConnection!) { 
     // Request complete, self.data should now hold the resulting info 
     // Convert the retrieved data in to an object through JSON deserialization 
     var err: NSError 
     var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary 
     var results: NSDictionary = jsonResult["results"] as NSDictionary 
     var collection: NSArray = results["collection1"] as NSArray 
     if jsonResult.count>0 && collection.count>0 { 
      Business = jsonResult 
      tableView.reloadData() 
     } 
    } 
} 

Swift Docs on @lazy: ilk değer örneği başlatma tamamlandıktan sonra kadar alınamaz çünkü

Her zaman (var anahtar sözcüğüyle) bir değişken olarak tembel bir mal beyanında gerekir. Sabit özellikler, başlatma işleminden önce her zaman bir değere sahip olmalıdır ve bu nedenle tembel olarak bildirilemez.

Önce bir IBOutlet:

20

Sadece girmek zorunda

bir Eylem fonk içinde Sonra
@IBOutlet var appsTableView : UITableView 

:

self.appsTableView.reloadData() 
145

Üzerinde tabloyu yeniden gerekir UI üzerinden gönderilen ileti:

//swift 2.3 
dispatch_async(dispatch_get_main_queue(), {() -> Void in 
    self.tableView.reloadData() 
}) 

//swift 3 
DispatchQueue.main.async{ 
    self.tableView.reloadData() 
} 

Takip: connection.start() yaklaşıma daha kolay bir alternatif Eğer ilerleme hesaplamak isteyebilirsiniz örneğin Bu, size rağmen bayt izleme esnekliğini izin vermez yerine NSURLConnection.sendAsynchronousRequest(...)

//NSOperationQueue.mainQueue() is the main thread 
NSURLConnection.sendAsynchronousRequest(NSURLRequest(URL: url), queue: NSOperationQueue.mainQueue()) { (response, data, error) -> Void in 
    //check error 
    var jsonError: NSError? 
    let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &jsonError) 
    //check jsonError 
    self.collectionView?.reloadData() 
} 

kullanmaktır bytesDownloaded aracılığıyla indirmenin/BytesNeeded

+0

Bu kod parçasını ('println' çalıştırıyorum) çağırıyor ama yine de verileri yeniden yüklemiyor mu? – Haring10

+0

Temsilcilerinizin doğru şekilde kurulduğundan ve temsilci yöntemlerinin gerçekten çağrıldığından emin olun. – noobular

+0

@noobular neden dispatch_async gerekli Tam olarak anlamıyorum. Bu cevap bana çok yardımcı oldu (2 saat boyunca). – Kyslik

3

bağlantı arka plan iş parçacığı ise o zaman bu

self.tblMainTable.performSelectorOnMainThread(Selector("reloadData"), withObject: nil, waitUntilDone: true) 
gibi ana iş parçacığı UI güncellemeniz gerekmektedir UI'dan bariz reloadData yanında

As I have mentioned here

+0

ben mi. Neden self.collectionView? .reloadData() benim için çalışmadı? NSURLSession kullanıyorum –

1

/Main Konu (Apple diyor neyse), benim durumumda, ben de SECTIONS bilgi güncellemek için unutmuştu. Bunun için yeni bölümler tespit etmedi!

2

Durumumda tablo doğru şekilde güncellendi, ancak görüntü için setNeedDisplay() çağrılmıyordu, bu yüzden yanlışlıkla verilerin yeniden yüklenmediğini düşündüm.

0

UI'ye yapılan tüm çağrılar eşzamansız olmalıdır, UI güncelleme tablosu gibi değiştirdiğiniz veya metin etiketini değiştirdiğiniz her şey ana iş parçacığından yapılmalıdır. DispatchQueue.main kullanarak , işleminizi ana iş parçacığında sıraya ekleyecektir. 4

DispatchQueue.main.async{ 
    self.tableView.reloadData() 
} 
+0

Bu daha önce söylendi. Örneğin 2014'te noobular'ın cevabı. Ve diğerleri. – Moritz