使用Swift从不同的类执行函数 [英] Performing function from a different class with Swift

查看:111
本文介绍了使用Swift从不同的类执行函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大约一个月前,我开始快速学习(主要来自书本),没有任何编程经验。我仍然困难地围绕几个概念,主要是价值类型和参考类型,以及诸如授权等事情。这可能是我为什么似乎无法找到以下问题的答案的原因。



我有一个2个类的Xcode项目,就像2个swift文件一样。 / b>


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

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

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

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


致命错误:在解包可选值时意外发现nil


Xcode强调了我的函数的内容是罪魁祸首,这让我认为collectionView不适用于collectionViewCell类,但是我的婴儿程序设计大脑真的无法按照想出来的想法来解决这个问题。

我发现的唯一解决方案是使用通知让函数执行。它可以工作,但isn还有另一种我应该知道的方式吗?是否可以从不同的类调用函数,并且仍然能够执行,就好像它是从声明函数的类中调用的一样?



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

问号确实会阻止应用程序崩溃,但不会改变代码的行为。 coll ectionView 确实是在连接了3个插座的故事板中创建的,引用以及数据源和委托。



该函数被调用并正确执行在 viewController 类中。所以我认为它不是零。如果我试图从 collectionViewCell 类(一个不同的.swift文件)调用它,那么它显然是零。我以为 collectionView`是在其他地方创建的,因此 collectionViewCell'类看不到它?这对我来说没有任何意义,我越想越多,我就越迷失方向。



难道是因为我只是从另一个文件调用错误的函数?我正在使用:

在collectionViewCell类中,

ViewController()。collectionViewInteractionEnabled true)

解决方案

在查看代码后,问题如下: b
$ b

  MemoryController()。memoryCollectionViewUserInteractionEnabled(true)

当您调用 MemoryController()时,您正在创建该类的新实例,而不是对从故事板加载的实例的引用,因为我假设您期待。 从故事板实例化视图控制器。如果你在没有故事板的情况下进行实例化,那么你的视图将不会被定义和链接为 @IBOutlet 引用,并且将为零,因此会导致崩溃。



但是,这不是你真正想要的 - 你需要一个从故事板加载的引用。一个简单的方法是在你的单元和视图控制器之间建立一个委托关系。让你的视图控制器实现一个协议,并让你的单元格使用一个属性类型的视图控制器可以设置为 self 当它创建单元格。

  //定义协议
协议MemoryCardCellDelegate {
func cardDidTurnDown()
}

class MemoryCardCell:UICollectionViewCell,UICollectionViewDelegate {
//创建输入协议的属性
var delegate:MemoryCardCellDelegate?

func turnDownAfterTimer(){
//调用委托的方法(这真的是您的视图控制器)
self.delegate?.cardDidTurnDown()
}
}

//添加协议一致性类型declaratio
类MemoryController:UIViewController,UICollectionViewDelegate,UICollectionViewDataSource,MemoryCardCellDelegate {

//实现协议方法
func cardDidTurnDown(){
memoryCollectionViewUserInteractionEnabled(true)
}

func collectionView(collectionView:UICollectionView,cellForItemAtIndexPath indexPath:NSIndexPath) - > UICollectionViewCell {

如果let cell = memoryCollectionView.dequeueReusableCellWithReuseIdentifier(MemoryCardCell,forIndexPath:indexPath)as? MemoryCardCell {
let image = UIImage(命名为:Mem Card Back)
cell.cardImageView.image = image
cell.delegate = self //<设置委托
返回单元
}
fatalError(不能分配MemoryCardCell。)
}
}


Just about a month ago I started learning swift (mainly from books), with no prior programming experience whatsoever. I am still having trouble wrapping my head around several concepts, mainly value types and reference types, and things such as delegation. This is probably the reason why I can’t seem to find an answer for the following problem.

I have an Xcode project with 2 classes as in 2 swift files.

  1. A viewController class containing a collection view;
  2. A collectionViewCell class.

In the viewController class I have a method to disable and enable user interaction of the collectionView:

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

When called from the viewController class, the method works. But when called from the collectionViewCell class, i get this:

"fatal error: unexpectedly found nil while unwrapping an Optional value"

Xcode highlights the contents of my function as the culprit. This makes me think that the collectionView is not there for the collectionViewCell class. But my infant programming brain really can’t follow the thought process needed to figure this out.

The only solution I found was using a notification to let the function perform. It works, but isn’t there another way that I should know about? Is it possible to call a function from a different class, and still have it perform as if it was being called from the class wherein the function is declared?

Edit: Update after trying Patricks' advice:

The question mark does stop the app from crashing, but does not change the behavior of the code. The collectionViewis indeed created in storyboard with 3 outlets connected, the reference, and the datasource and delegate.

The function is called and performs correctly from within the viewController class. So I assume that it is not nil. If i try to call it from the collectionViewCell class (a different .swift file), then it aparently is nil. I thought the collectionViewCell' class just can't see it since thecollectionView` is created somewhere else? It makes no sense to me and the more I think about it, the more I get lost.

Could it be that I am just calling the function wrong from the other file? I am using:

In the collectionViewCell class

ViewController().collectionViewInteractionEnabled(true)

解决方案

After looking at your code, here is the problem:

MemoryController().memoryCollectionViewUserInteractionEnabled(true)

When you call MemoryController() you are creating a new instance of that class, not a reference to the one loaded from your storyboard as I assume you are expecting. There is a special procedure for instantiating a view controller from a storyboard. If you instantiate without a storyboard as you are doing, your views will not be defined and linked as @IBOutlet references, and will be nil, hence the crash.

But that's not what you really want anyway—you want a reference the one loaded from the storyboard. An easy way to do that is to set up a delegation relationship between your cell and the view controller. Have your view controller implement a protocol, and have your cell use a property typed to that protocol that the view controller can then set to self when it creates the cell.

// 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." )
    }
}

这篇关于使用Swift从不同的类执行函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆