【问题标题】:Performing function from a different class with Swift使用 Swift 从不同的类执行功能
【发布时间】:2015-10-21 00:55:32
【问题描述】:

大约一个月前,我开始学习 swift(主要是从书本上),之前没有任何编程经验。我仍然难以理解几个概念,主要是值类型和引用类型,以及诸如委托之类的东西。这可能是我似乎无法找到以下问题的答案的原因。

我有一个 Xcode 项目,其中包含 2 个类,如 2 个 swift 文件。

  1. 包含集合视图的 viewController 类;
  2. collectionViewCell 类。

在 viewController 类中,我有一个方法可以禁用和启用 collectionView 的用户交互:

func collectionViewInteractionEnabled(boolean: Bool) {
   collectionView.userInteractionEnabled = boolean
}

当从 viewController 类调用时,该方法有效。但是当从 collectionViewCell 类中调用时,我得到了这个:

“致命错误:在展开可选值时意外发现 nil”

Xcode 将我的函数的内容突出显示为罪魁祸首。这让我觉得collectionView 不存在collectionViewCell 类。但是我的婴儿编程大脑真的无法遵循解决这个问题所需的思维过程。

我找到的唯一解决方案是使用通知让函数执行。它有效,但没有其他我应该知道的方法吗?是否可以从不同的类调用函数,并且仍然让它像从声明函数的类调用一样执行?

编辑:在尝试 Patricks 的建议后更新:

问号确实会阻止应用程序崩溃,但不会改变代码的行为。 collectionView确实是在情节提要中创建的,其中连接了 3 个出口、引用、数据源和委托。

viewController 类中调用并正确执行该函数。所以我假设它不是零。如果我尝试从collectionViewCell 类(不同的.swift 文件)调用它,那么它显然是零。我认为collectionViewCell' class just can't see it since thecollectionView` 是在其他地方创建的?这对我来说毫无意义,我越想越迷失。

可能是我只是从另一个文件中调用了错误的函数吗?我正在使用:

collectionViewCell 类中

ViewController().collectionViewInteractionEnabled(true)

【问题讨论】:

    标签: swift function class


    【解决方案1】:

    我假设您的collectionView 属性是@IBOutlet,其类型为UICollectionView!,这是一个隐式展开的类型(如! 所示)。这意味着这个值可能是也可能不是 nil,如果你试图在它为 nil 时直接访问它,你的应用程序将崩溃并显示你收到的确切错误消息。有几种方法可以“解包”这些值,以便在它们不是 nil 时安全地使用它们。在你的情况下,我会这样做:

    collectionView?.userInteractionEnabled = boolean
    

    这称为Optional Chaining。如果在此行执行时您的collectionView 为 nil,则执行将中止并移至下一行。但是如果collectionView 被定义为一个非零值,那么userInteractionEnabled 属性将被设置为boolean 的值。现在,当然,为什么你的collectionView 为零?如果这是@IBOutlet,您可能没有在Interface Builder 中连接引用插座。如果您正在以编程方式创建集合视图,那么您会在定义它之前尝试访问它。此外,如果您在 viewDidLoad() 方法被调用拥有集合视图的视图控制器之前没有调用此函数,则在任何一种情况下您都可能会收到此错误。此时,您的视图已加载,您的 collectionView 值将被定义,您可以安全地与之交互。

    【讨论】:

    • 非常感谢帕特里克的详细回答。当然,从现在开始我要牢记viewDidLoad() 方法的顺序。但仍然没有运气。我更新了我的问题以反映您的答案,它不适合 cmets :)
    • 你能将项目发布到 GitHub 存储库中吗?我很乐意为您调试它。
    • 我需要弄清楚如何进行回购(我记得在一本书中读过它,我得查一下)。之后是否可以通过回购发送私人消息?我有点不好意思公开我的烂摊子!
    • 没关系,没有人会判断我们只是想提供帮助。发布一个 .zip 文件,一旦我们找到答案,您就可以将其删除。
    【解决方案2】:

    查看您的代码后,问题出在:

    MemoryController().memoryCollectionViewUserInteractionEnabled(true)
    

    当您调用MemoryController() 时,您正在创建该类的新实例,而不是对从情节提要加载的实例的引用,正如我假设您所期望的那样。 instantiating a view controller from a storyboard 有一个特殊的程序。如果您在没有故事板的情况下实例化,您的视图将不会被定义和链接为@IBOutlet 引用,并且将为 nil,因此会崩溃。

    但这并不是你真正想要的——你想要一个从情节提要中加载的参考。一个简单的方法是在你的单元格和视图控制器之间建立一个委托关系。让您的视图控制器实现一个协议,并让您的单元格使用类型为该协议的属性,然后视图控制器可以在创建单元格时将其设置为self

    // Define the protocol
    protocol MemoryCardCellDelegate {
        func cardDidTurnDown()
    }
    
    class MemoryCardCell: UICollectionViewCell, UICollectionViewDelegate {
        // Create property typed to the protocol
        var delegate: MemoryCardCellDelegate?
    
        func turnDownAfterTimer() {
            // Call the method on your delegate (which is really your view controller) 
            self.delegate?.cardDidTurnDown()
        }
    }
    
    // Add protocol conformance to type declaratio
    class MemoryController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, MemoryCardCellDelegate {
    
        // Implement the protocol method
        func cardDidTurnDown() {
            memoryCollectionViewUserInteractionEnabled(true)
        }
    
        func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    
            if let cell = memoryCollectionView.dequeueReusableCellWithReuseIdentifier("MemoryCardCell", forIndexPath: indexPath) as? MemoryCardCell {
                let image = UIImage(named: "Mem Card Back")
                cell.cardImageView.image = image
                cell.delegate = self  //< Set the delegate
                return cell
            }
            fatalError( "Could not dqueue MemoryCardCell." )
        }
    }
    

    【讨论】:

    • 非常感谢帕特里克,你太棒了。我很幸运你走过了我的路。我将在早上实现这个(我早上,我​​来自荷兰,因此我的英语不好,虽然不像我的代码那么坏)。希望你没有看到太多奇怪的东西。一旦我找到所有的逻辑并且一切就绪,我将开始清理并尝试找出不同且更有效的做事方式。既然您已与代表一起更正了它,我知道在哪里可以找到我的书并继续研究它。再次,非常感谢! :)
    • 不能等到早上......就像一个魅力
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多