CollectionView IBOutlet внутри класса UIView возвращает ноль - только иногда? - PullRequest
0 голосов
/ 12 июня 2018

Поэтому я пытаюсь найти новые способы поддержания чистоты своих проектов и облегчения управления ими для себя.

Способ, которым я надеюсь это сделать, - это сохранить все отношения в своем собственном быстром файле.и затем обращаюсь к нему, когда это необходимо.

Я постараюсь сделать все возможное, чтобы разметить свою проблему, но если помогут снимки экрана или вам понадобится дополнительная информация, я сделаю все возможное, чтобы предоставить ее.

Стоит отметить: представление коллекции загружается при первом запуске приложения, как и должно быть.И выход MenuActionLabel.text имеет значение: «Привет».

Но когда я пытаюсь вызвать ShowMe (), CollectionView не перезагружается и вместо этого вылетает, потому что Collectioner вернул nil необязательно.

import UIKit

class UserMenu: UIView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    struct Variables {
        static var myName = "Hi"
    }

    @IBOutlet weak var Collectioner: UICollectionView!

Когда я вызываю следующую функцию ShowMe (), я получаю распечатку из "coll: nil".

Я вызываю функцию из ViewController.swift, через 'UserMenu (). ShowMe () '

    func ShowMe() {
        Variables.myName = "Justin"
        print("coll: \(self.Collectioner)")
        //Collectioner.reloadData()
        //^---- causes error - see didSelectItem for my problem...
        //returns nil optional...? Why?
    }

    //testing to find errors
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        if collectionView == Collectioner {
            return 1
        } else {
            return 0
        }
    }

    //testing to find errors
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            if collectionView == Collectioner {
                return 1
            } else {
                return 0
            }
        }

    //testing to find errors
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if collectionView == Collectioner {
            let Cell:UserMenuCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath) as! UserMenuCell
            Cell.MenuActionLabel.text = "\(Variables.myName)"
            return Cell
        } else {
            let Cell:UserMenuCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath) as! UserMenuCell
            return Cell
        }
    }

    //testing to find errors
    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        cell.alpha = 0
        UIView.animate(withDuration: 0.8) {
            cell.alpha = 1
        }
    }

    //testing to find errors
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if collectionView == Collectioner {
            return CGSize(width: Collectioner.frame.width, height: 50)
        } else {
            return CGSize(width: Collectioner.frame.width, height: 50)
        }
    }

    //testing to find errors
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        if collectionView == Collectioner {
            return 0
        } else {
            return 0
        }
    }

Моя путаница проявляется здесь:

    /*
    When I tap on the cell:
    1. The collection view reloads, and the updated data is shown.

    2. Yet... if I call reloadData from elsewhere,
       the Collectioner outlet returns as an optional nil?
    */

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        if collectionView == Collectioner {
            print(collectionView)
            print(" ")
            print(Collectioner)
            print(" ")
            collectionView.reloadData()
        }
    }

}

Распечатанный вывод из didSelectItemAt:

<UICollectionView: 0x7fd13103a000; frame = (0 0; 314 716); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x60c000242a00>; layer = <CALayer: 0x60c00022d140>; contentOffset: {0, 0}; contentSize: {314, 50}; adjustedContentInset: {0, 0, 0, 0}> collection view layout: <UICollectionViewFlowLayout: 0x7fd12ef1b450>

some(<UICollectionView: 0x7fd13103a000; frame = (0 0; 314 716); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x60c000242a00>; layer = <CALayer: 0x60c00022d140>; contentOffset: {0, 0}; contentSize: {314, 50}; adjustedContentInset: {0, 0, 0, 0}> collection view layout: <UICollectionViewFlowLayout: 0x7fd12ef1b450>)

Имигает представление коллекции, показывая, что оно перезагружено.

Так почему же он возвращает ноль, когда я пытаюсь перезагрузить представление коллекции из другого места?

Пожалуйста, помогите.Это сводит меня с ума.Я перепробовал все, что только мог придумать, и много занимался поиском ответов, решений, и я открыт для предложений и обучения.

Я не уверен, нужно ли мне как-то «подтверждать» IBOutlet при запускедаже если кажется, что все правильно подключено через StoryBoard.

EDIT - ViewController.swift:

import UIKit

class ViewController: UIViewController {

    let userMenu = UserMenu()

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBOutlet weak var button: UIButton!
    @IBAction func button(_ sender: Any) {
        print("Tapped Button")
        UserMenu().ShowMe()
    }

}

EDIT - Heirachy fig 1

Ура,

Джастин.

1 Ответ

0 голосов
/ 12 июня 2018

Давайте поговорим о том, что происходит, когда вы вызываете UserMenu().ShowMe()

  • Сначала вызывается UserMenu() и инициализируется новый экземпляр UserMenu с использованием метода init().
  • Во-вторых, этот экземпляр будет вызывать ShowMe() метод.

Почему вы получаете сбой?- Потому что экземпляр UserMenu инициализируется по умолчанию методом init и ничего не загружается из раскадровки.Конечно, в этом случае Collectioner будет nil, и это приведет к сбою.

Чтобы исправить это, вы должны сохранить UserMenu экземпляр внутри ViewControler как свойство (возможно, назовите его как userMenu).Каждый раз, когда вы хотите вызвать метод ShowMe(), он должен быть userMenu.ShowMe().

РЕДАКТИРОВАТЬ : подключите представление пользовательского меню из раскадровки к @IBOutlet weak var userMenu: UserMenu! и используйте мой код ниже.

class ViewController: UIViewController {

  @IBOutlet weak var userMenu: UserMenu!

  override func viewDidLoad() {
    super.viewDidLoad()
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }

  @IBOutlet weak var button: UIButton!
  @IBAction func button(_ sender: Any) {
    print("Tapped Button")
    userMenu.ShowMe()
  }
}
...