2015-07-30 2 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)) 
    } 
} 

Почему мой deinit не вызывается. Я предложу 100 bounty однажды я смогу это сделать и присужу тому, кто поможет мне решить эту проблему ... Я принесу щедрость даже после решения проблемы.Свидетельство Swift не называется

ОЧЕНЬ ВАЖНО INFO: этот код звонкиdeinit. ЭТО РАБОТАЕТ. Потому что число строк равно 0. Но мне нужно иметь elements.count. Когда я перехожу к этому, 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

Является ли 'completionBlock' сохраненным' D BNetworkClient'? –

+0

Я приложил это к своему вопросу –

+0

Является ли ваш контроллер просмотра содержащимся в 'UINavigationController' или' UITabBarController'? – Kirsteins

ответ

35

Вы назначаете self в качестве делегата вашей Просмотр таблицы ячейки:

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 
} 

свойства Делегатой ячейки определяются следующим образом:

var delegate: DBItemTableViewCellDelegate? 

Этого создает strong Ссылка между ячейкой и делегатом (ваш контроллер просмотра). Ячейка также сохраняется в виде таблицы. Это создает цикл сохранения.

Вам нужно будет изменить определение свойства делегата быть weak:

weak var delegate: DBItemTableViewCellDelegate? 

Редактировать на основе comment:

Ваше DBItemTableViewCellDelegate определение необходимо будет определить как class-only protocol

protocol DBItemTableViewCellDelegate: class { 
    ... 
} 
+0

Проблема в том, что когда я пытаюсь добавить слабый:' слабый var delegate: DBItemTableViewCellDelegate? ', То у меня есть ошибка: слабый не может быть применен к неклассическому type DBItemTableViewCellDelegate –

+0

Обновленный ответ :) –

+1

Это работает :-) Вы волшебник :-) В течение двух дней я предлагаю щедрость, как я сказал, и присуждаю вам. ОК? –

Смежные вопросы