在Swift中将委托设置为自我抛出错误

时间:2018-03-23 15:37:51

标签: ios swift avaudioplayer fatal-error

我目前正在处理在播放AVAudioPlayer时禁用UIImageView的代码。我要禁用的AVAudioPlayer和ImageView位于两个不同的类中。我尝试编写一个委托让我的两个类进行通信,但是当我尝试在我的viewController中分配给self时,我继续收到错误“线程1:致命错误:在解开一个Optional值时意外发现nil”。

包含我的AVAudioPlayer的类的代码在

之下
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
    }    
}

1 个答案:

答案 0 :(得分:2)

由于card被定义为强制解包的可选:

var card: Card!

行:

card.delegate = self

就像强行解开它一样:

card!.delegate = self

问题是那时cardnil。您必须先将其初始化为某个值,然后才能使用它。它与Card实现本身无关。

E.g:

override func viewDidLoad() {
    super.viewDidLoad()

    card = Card(image: UIImage(), soundUrl: "url", isActive: true)

    card.delegate = self
}

无论如何,我建议使用可选(Card?),或者从一开始就初始化card而不要使用可选项。如果你必须使用可选项,使用Card?将迫使你永远记住card可以指向nil,并会强迫你以某种方式处理它。