ios - 在 Swift 中将委托(delegate)设置为 self 抛出错误

标签 ios swift avaudioplayer fatal-error

<分区>

我目前正在编写在播放 AVAudioPlayer 时禁用 UIImageView 的代码。我要禁用的 AVAudioPlayer 和 ImageView 位于两个不同的类中。我尝试编写一个委托(delegate)来让我的两个类进行通信,但是当我尝试在我的 viewController 中分配给自己时,我不断收到错误“线程 1: fatal error :在展开可选值时意外发现 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
    }    
}

最佳答案

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

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,并将迫使您以某种方式处理它。

关于ios - 在 Swift 中将委托(delegate)设置为 self 抛出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49453402/

相关文章:

ios - ld : library not found for -lz clang: error

ios - NSURLSession dataTaskWithRequest Swift

swift - 我不断收到此错误 : "Implicit use of ' self' in closure; use 'self.' to make capture semantics explicit"

iphone - 在 iPhone 中创建虚拟音频文件

ios - 处理 Sprite Kit 中的中断 - 无法通过 [SKAction playSoundFileNamed : to work after interruption 获得音效

ios - 将千禧年媒体广告集成到 Swift 应用程序中

ios - 单元测试自定义 UITableViewCell?

ios - AVCaptureSession 和 AVAudioSession 在背景音乐播放时录制视频只能工作一次

ios - AVAudioPlayer 的 NSOSStatusErrorDomain Code=-54

objective-c - 如何提取 NSArray 的元素并将它们(parseInt)转换为整数值?