2015-07-30 20 views
10
private let DBItemCellIdentifier = "ItemCellIdentifier" 
private let DBItemSegueIdentifier = "ItemSegueIdentifier" 

class DBItemsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, DBItemTableViewCellDelegate { 

    @IBOutlet weak var tableView: UITableView! 
    @IBOutlet weak var previousButton: UIButton! 
    @IBOutlet weak var nextButton: UIButton! 
    @IBOutlet weak var categoryNameLabel: UILabel! 

    private var elements = [Any]() 
    private var currentItemIndex = 0 
    private var isFetching = false 

    private weak var currentCategory: DBCategory? { 

     didSet { 
      updateView() 
     } 
    } 

    var categories = [DBCategory]() 
    var currentCategoryIndex = 0 

    //MARK: - Class Methods 

    //MARK: - Initialization 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     tableView.rowHeight = UITableViewAutomaticDimension 
     tableView.estimatedRowHeight = 100.0 
     tableView.tableFooterView = UIView(frame: CGRectZero) 

     setupUserAndCartButtons() 
     fetchItems() 
    } 

    deinit { 
     print("deinit") 
    } 

    //MARK: - Actions 

    @IBAction func nextButtonTapped(sender: UIButton) { 

     currentCategoryIndex = min(currentCategoryIndex + 1, categories.count - 1) 
     fetchItems() 
    } 

    @IBAction func previousButtonTapped(sender: UIButton) { 

     currentCategoryIndex = max(currentCategoryIndex - 1, 0) 
     fetchItems() 
    } 

    //MARK: - Private 

    private func fetchItems() { 

     tableView.alpha = 0 
     currentCategory = nil 

     if !categories.isEmpty && !isFetching { 
      let category = categories[currentCategoryIndex] 
      currentCategory = DBCategory.findCategoryWithIdentifier(category.identifier) 

      if currentCategory == nil { 
       SVProgressHUD.show() 
      } 

      isFetching = true 

      DBNetworkClient.sharedClient().itemsForCategory(category, completionBlock: { error in 

       defer { 
        self.isFetching = false 
        SVProgressHUD.dismiss() 
        UIAlertController.showAlertFromError(error) 
       } 

       self.currentCategory = DBCategory.findCategoryWithIdentifier(category.identifier) 
      }) 
     } 
    } 

    private func updateView() { 

     let category = categories[currentCategoryIndex] 
     title = category.menu.location.name 

     categoryNameLabel.text = category.name 
     previousButton.hidden = currentCategoryIndex == 0 ? true : false 
     nextButton.hidden = currentCategoryIndex == categories.count - 1 ? true : false 

     prepareElements() 

     tableView.reloadData() 

     UIView.animateWithDuration(0.5, animations: { 
      self.tableView.alpha = 1 
     }) 
    } 

    private func prepareElements() { 

     elements.removeAll(keepCapacity: false) 

     if let items = currentCategory?.items { 
      for item in items { 
       elements.append(item) 
      } 
     } 

     if let sets = currentCategory?.sets { 
      for set in sets { 
       elements.append(set) 
      } 
     } 

     elements.sortInPlace { 

      let left = ($0 as? DBSet)?.position ?? ($0 as? DBItem)?.position 
      let right = ($1 as? DBSet)?.position ?? ($1 as? DBItem)?.position 

      return left < right 
     } 
    } 

    //MARK: - Overridden 

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 

     let element = elements[currentItemIndex] 

     if segue.identifier == DBItemSegueIdentifier { 
      let itemViewController = segue.destinationViewController as! DBItemViewController 
      itemViewController.prepareWithElement(element) 

     } 
    } 

    //MARK: - UITableViewDataSource 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return 0 //when I change to elements.count, deinit is not called 
    } 

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

     let cell = tableView.dequeueReusableCellWithIdentifier(DBItemCellIdentifier, forIndexPath: indexPath) as! DBItemTableViewCell 
     let element = elements[indexPath.row] 

     if let item = element as? DBItem { 
      cell.configureCellWithItem(item) 
     } else if let set = element as? DBSet { 
      cell.configureCellWithSet(set) 
     } 

     cell.delegate = self 

     return cell 
    } 

    //MARK: - UITableViewDelegate 

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

     currentItemIndex = indexPath.row 
     performSegueWithIdentifier(DBItemSegueIdentifier, sender: tableView.cellForRowAtIndexPath(indexPath)) 
    } 

    //MARK: - DBItemTableViewCellDelegate 

    func itemTableViewCell(cell: DBItemTableViewCell, willPresentSetGroupsViewControllerForSet set: DBSet) { 
     presentSetOrderControllerWithOrder(DBSetOrder(set: set)) 
    } 

    func itemTableViewCell(cell: DBItemTableViewCell, willPresentItemMealSizesViewControllerForItem item: DBItem) { 
     presentItemOrderControllerWithOrder(DBItemOrder(item: item)) 
    } 
} 

Perché il mio deinit non viene chiamato. Offrirò una quantità di 100 una volta che sarò in grado di farlo, e assegnerò a quella, che mi aiuterà a risolvere questo problema ... Offrirò un premio anche dopo aver risolto il problema.Il deinit di Swift non viene chiamato

INFORMAZIONI MOLTO IMPORTANTE: questo codice chiamatedeinit. FUNZIONA. Perché il numero di righe è 0. Ma ho bisogno di avere lì elements.count. Quando si passa a questo, non viene chiamato deinit.

EDIT:

func itemsForCategory(category: DBCategory, completionBlock: DBErrorHandler) { 

    let query = "locations/" + category.menu.location.identifier + "/categories/" + category.identifier 

    GET(query, parameters: nil, success: { operation, response in 

     if let error = NSError(response: response) { 
      completionBlock(error) 
     } else { 
      self.coreDataAssistant.parseAndSaveItemsToPersistentStore(response as? NSDictionary, completionBlock: { error in 
       completionBlock(error) 
      }) 
     } 

     }) { operation, error in 

      let responseError = NSError(response: operation.responseObject) 
      completionBlock(responseError ?? error) 
    } 
} 
+0

Il 'completionBlock' viene mantenuto dal' D BNetworkClient'? –

+0

Ho allegato questo alla mia domanda –

+0

Il controller di visualizzazione è contenuto in 'UINavigationController' o' UITabBarController'? – Kirsteins

risposta

35

si sta assegnando self come delegato il tuo tavolo della cellula vista:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCellWithIdentifier(DBItemCellIdentifier, forIndexPath: indexPath) as! DBItemTableViewCell 
    let element = elements[indexPath.row] 

    if let item = element as? DBItem { 
     cell.configureCellWithItem(item) 
    } else if let set = element as? DBSet { 
     cell.configureCellWithSet(set) 
    } 

    // HERE 
    cell.delegate = self 

    return cell 
} 

proprietà delegato della cella è definito come segue:

var delegate: DBItemTableViewCellDelegate? 

Questo crea un forte riferimento tra la cella e il delegato (il tuo controller di visualizzazione). La cella viene inoltre mantenuta dalla vista tabella. Questo crea un ciclo di conservazione.

Sarà necessario modificare la definizione della proprietà delegato per essere weak:

weak var delegate: DBItemTableViewCellDelegate? 

Modifica sulla base di comment:

tua definizione DBItemTableViewCellDelegate dovrà essere definito come un class-only protocol

protocol DBItemTableViewCellDelegate: class { 
    ... 
} 
+0

Il problema è che quando provo ad aggiungere debole:' delegato var debole: DBItemTableViewCellDelegate? 'Poi ho un errore: debole non può essere applicato a non-class tipo DBItemTableViewCellDelegate –

+0

Risposta aggiornata :) –

+1

Funziona :-) sei un mago :-) Entro due giorni, offro una taglia, come ho detto, e te la regalo. Ok? –