使用Swift从不同的类执行函数 [英] Performing function from a different class with Swift
问题描述
我有一个2个类的Xcode项目,就像2个swift文件一样。 / b>
- 包含集合视图的viewController类;
- collectionViewCell类。
在viewController类中,我有一个方法来禁用和启用collectionView的用户交互:
func collectionViewViewInteractionEnabled(boolean:Bool){
collectionView.userInteractionEnabled = boolean
}
从viewController类调用时,该方法有效。但是,当从collectionViewCell类中调用时,我得到了这个结果:
致命错误:在解包可选值时意外发现nil
Xcode强调了我的函数的内容是罪魁祸首,这让我认为collectionView不适用于collectionViewCell类,但是我的婴儿程序设计大脑真的无法按照想出来的想法来解决这个问题。
我发现的唯一解决方案是使用通知让函数执行。它可以工作,但isn还有另一种我应该知道的方式吗?是否可以从不同的类调用函数,并且仍然能够执行,就好像它是从声明函数的类中调用的一样?
编辑:尝试Patricks的建议后更新: 问号确实会阻止应用程序崩溃,但不会改变代码的行为。 该函数被调用并正确执行在 难道是因为我只是从另一个文件调用错误的函数?我正在使用: 在collectionViewCell类中, 在查看代码后,问题如下: b 当您调用 但是,这不是你真正想要的 - 你需要一个从故事板加载的引用。一个简单的方法是在你的单元和视图控制器之间建立一个委托关系。让你的视图控制器实现一个协议,并让你的单元格使用一个属性类型的视图控制器可以设置为 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. In the viewController class I have a method to disable and enable user interaction of the collectionView: 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 The function is called and performs correctly from within the Could it be that I am just calling the function wrong from the other file? I am using: In the collectionViewCell class After looking at your code, here is the problem: When you call 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
这篇关于使用Swift从不同的类执行函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
coll ectionView
确实是在连接了3个插座的故事板中创建的,引用以及数据源和委托。
viewController
类中。所以我认为它不是零。如果我试图从 collectionViewCell
类(一个不同的.swift文件)调用它,那么它显然是零。我以为 collectionView`是在其他地方创建的,因此
ViewController()。collectionViewInteractionEnabled true)
$ 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。)
}
}
func collectionViewInteractionEnabled(boolean: Bool) {
collectionView.userInteractionEnabled = boolean
}
collectionView
is indeed created in storyboard with 3 outlets connected, the reference, and the datasource and delegate.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 the
collectionView` is created somewhere else? It makes no sense to me and the more I think about it, the more I get lost.ViewController().collectionViewInteractionEnabled(true)
MemoryController().memoryCollectionViewUserInteractionEnabled(true)
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.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." )
}
}