在 Swift 中将委托设置为自我抛出错误
setting delegate to self throwing error in Swift
我目前正在研究在播放 AVAudioPlayer 时禁用 UIImageView 的代码。我要禁用的 AVAudioPlayer 和 ImageView 位于两个不同的 classes 中。我尝试编写一个委托让我的两个 classes 进行通信,但是当我尝试在我的 viewController 中分配给自己时,我一直收到错误 "Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"。
包含我的 AVAudioPlayer 的 class 的代码在
下面
import Foundation; import UIKit; import AVFoundation
protocol isOnProtocol{
func isOn()
}
class Card: NSObject
{
var delegate: isOnProtocol?
var player: AVAudioPlayer?
var image: UIImage
var soundUrl: String
init(image: UIImage, soundUrl: String, isActive:Bool = true) {
self.image = image
self.soundUrl = soundUrl
}
func playSound()
{
guard let url = Bundle.main.url(forResource: self.soundUrl, withExtension: "m4a") else { return }
do
{
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
player = try AVAudioPlayer(contentsOf: url)
//player?.delegate = self
guard let player = player else { return }
player.prepareToPlay()
player.play()
audioPlayerDidFinishPlaying(player)
print("play")
} catch let error {
print(error.localizedDescription)
}
}
}
extension Card: AVAudioPlayerDelegate {
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer){
if let del = delegate{
del.isOn()
}else{
print("the delegate is not set")
}
}
}
我尝试与之通信的 ViewController 的代码如下。当调用图像点击函数时,声音播放并且 UserInteractions 应该为假,直到 AVAudioPlayer 完成(调用 isOn 函数)。
class SecondViewController: UIViewController , UIGestureRecognizerDelegate, isOnProtocol {
@IBOutlet weak var imgPhoto: UIImageView!
var card: Card!
override func viewDidLoad() {
super.viewDidLoad()
card.delegate = self //error is thrown here
}
func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
imgPhoto.isUserInteractionEnabled = false
itemList[imageIndex].playSound()
}
func isOn() {
imgPhoto.isUserInteractionEnabled = true
}
}
由于 card
定义为 force-unwrapped 可选:
var card: Card!
行:
card.delegate = self
与强制打开它一样:
card!.delegate = self
问题是 card
在那个时候是 nil
。您必须先将其初始化为某个值,然后才能使用它。它与 Card
实现本身无关。
例如:
override func viewDidLoad() {
super.viewDidLoad()
card = Card(image: UIImage(), soundUrl: "url", isActive: true)
card.delegate = self
}
无论如何,我建议要么使用可选的 (Card?
),要么从一开始就初始化 card
而根本不使用可选的。如果你必须使用可选的,使用 Card?
将迫使你始终记住 card
可以指向 nil,并迫使你以某种方式处理它。
我目前正在研究在播放 AVAudioPlayer 时禁用 UIImageView 的代码。我要禁用的 AVAudioPlayer 和 ImageView 位于两个不同的 classes 中。我尝试编写一个委托让我的两个 classes 进行通信,但是当我尝试在我的 viewController 中分配给自己时,我一直收到错误 "Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"。
包含我的 AVAudioPlayer 的 class 的代码在
下面import Foundation; import UIKit; import AVFoundation
protocol isOnProtocol{
func isOn()
}
class Card: NSObject
{
var delegate: isOnProtocol?
var player: AVAudioPlayer?
var image: UIImage
var soundUrl: String
init(image: UIImage, soundUrl: String, isActive:Bool = true) {
self.image = image
self.soundUrl = soundUrl
}
func playSound()
{
guard let url = Bundle.main.url(forResource: self.soundUrl, withExtension: "m4a") else { return }
do
{
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
player = try AVAudioPlayer(contentsOf: url)
//player?.delegate = self
guard let player = player else { return }
player.prepareToPlay()
player.play()
audioPlayerDidFinishPlaying(player)
print("play")
} catch let error {
print(error.localizedDescription)
}
}
}
extension Card: AVAudioPlayerDelegate {
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer){
if let del = delegate{
del.isOn()
}else{
print("the delegate is not set")
}
}
}
我尝试与之通信的 ViewController 的代码如下。当调用图像点击函数时,声音播放并且 UserInteractions 应该为假,直到 AVAudioPlayer 完成(调用 isOn 函数)。
class SecondViewController: UIViewController , UIGestureRecognizerDelegate, isOnProtocol {
@IBOutlet weak var imgPhoto: UIImageView!
var card: Card!
override func viewDidLoad() {
super.viewDidLoad()
card.delegate = self //error is thrown here
}
func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
imgPhoto.isUserInteractionEnabled = false
itemList[imageIndex].playSound()
}
func isOn() {
imgPhoto.isUserInteractionEnabled = true
}
}
由于 card
定义为 force-unwrapped 可选:
var card: Card!
行:
card.delegate = self
与强制打开它一样:
card!.delegate = self
问题是 card
在那个时候是 nil
。您必须先将其初始化为某个值,然后才能使用它。它与 Card
实现本身无关。
例如:
override func viewDidLoad() {
super.viewDidLoad()
card = Card(image: UIImage(), soundUrl: "url", isActive: true)
card.delegate = self
}
无论如何,我建议要么使用可选的 (Card?
),要么从一开始就初始化 card
而根本不使用可选的。如果你必须使用可选的,使用 Card?
将迫使你始终记住 card
可以指向 nil,并迫使你以某种方式处理它。