【问题标题】:Swift protocol function never gets calledSwift 协议函数永远不会被调用
【发布时间】:2018-09-02 14:44:49
【问题描述】:

我目前正在研究在播放 AVAudioPlayer 时禁用 UIImageView 的代码。我要禁用的 AVAudioPlayer 和 ImageView 位于两个不同的类中。我试着写一个委托让我的两个班级交流。出于某种原因,即使我的类符合协议、调用方法并将委托设置为 self,协议方法也永远不会运行。在我的 Card 类中,在 audioDidFinishPlaying 方法中,我安全地解开委托。当我运行我的代码时,每次都会调用 print 语句而不是 isOn 方法。任何人都可以就这个问题提供任何建议吗?

包含我的 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 应该为 false,直到 AVAudioPlayer 完成(调用 isOn 函数)。

import UIKit



class SecondViewController: UIViewController , UIGestureRecognizerDelegate, isOnProtocol  {



@IBAction func home(_ sender: Any) {
    performSegue(withIdentifier: "home", sender: self)
}

@IBOutlet weak var imgPhoto: UIImageView!


var imageIndex: Int = 0
var itemList:[Card] = []


func addlist(list:[String])
{
    for word in list
    {
        itemList.append(Card(image: UIImage(named: word)!, soundUrl: word))
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    for i in 0..<11 {
        let list: [String]
        switch i {
        case 0: list = ["lake", "lamb", "lamp", "lark", "leaf", "leash", "left", "leg", "lime", "lion", "lips", "list", "lock", "log", "look", "love", "lunch"]
        case 1: list = ["ladder", "ladybug", "laughing", "lawnmower", "lemon", "leopard", "leprechaun", "letters", "licking", "lifesaver", "lifting", "lightbulb", "lightning",
                 "listen", "llama"]
        case 2: list = ["alligator", "balance", "ballerina", "balloon", "bowling", "cello", "colors", "curlyhair", "dollar", "dolphin", "elephant", "eyelashes", "gasoline",

                 "goalie", "hula", "jellyfish", "olive", "pillow", "pilot", "polarbear", "rollerskate", "ruler", "silly", "telephone", "television", "tulip", "umbrella", "valentine",

                 "violin", "yellow", "xylophone"] //yellow xylophone
        case 3: list = ["apple", "ball", "bell", "bubble", "castle", "fall", "fishbowl", "girl", "owl", "pail", "peel", "pool", "smile", "whale", "wheel"] //whale wheel
        case 4: list = ["planet", "plank", "plant", "plate", "play", "plum", "plumber", "plus"]
        case 5: list = ["black", "blanket", "blender", "blocks", "blond", "blood", "blow", "blue"]
        case 6: list = ["flag", "flipflop", "float", "floor", "flower", "fluffy", "flute", "fly"]
        case 7: list = ["glacier", "glad", "glasses", "glide", "glitter", "globe", "glove", "glue"]
        case 8: list = ["clam", "clamp", "clap", "claw", "clean", "climb", "clip", "cloud"]
        case 9: list = ["sled", "sleep", "sleeves", "slice", "slide", "slime", "slip", "slow"]
        case 10: list = ["belt", "cold", "dolphin", "elf", "golf", "melt", "milk", "shelf"]
        default: fatalError()

        }
        if UserDefaults.standard.value(forKey: "\(i)") as? Bool ?? true {
        addlist(list:list)
        }
    }
   print(itemList.count)


    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
    imgPhoto.isUserInteractionEnabled = true
    imgPhoto.addGestureRecognizer(tapGestureRecognizer)


    imgPhoto.image =  itemList[0].image

    // Do any additional setup after loading the view.
    //imgPhoto.isUserInteractionEnabled = true

    let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(Swiped(gesture:)))
    leftSwipe.cancelsTouchesInView = false

    let rightSwipe = UISwipeGestureRecognizer(target: self, action: #selector(Swiped(gesture:)))
    rightSwipe.cancelsTouchesInView = false

    leftSwipe.direction = .left
    rightSwipe.direction = .right

    view.addGestureRecognizer(leftSwipe)
    view.addGestureRecognizer(rightSwipe)

}



@IBAction func memoryButton(_ sender: Any) {
  performSegue(withIdentifier: "memory", sender: self)

}



func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
imgPhoto.isUserInteractionEnabled = false
let card = itemList[imageIndex]
card.delegate = self
card.playSound()
}
internal func isOn() {
    imgPhoto.isUserInteractionEnabled = true
}


func Swiped(gesture: UIGestureRecognizer) {
    imgPhoto.isUserInteractionEnabled = true

    if let swipeGesture = gesture as? UISwipeGestureRecognizer {

        switch swipeGesture.direction {

        case UISwipeGestureRecognizerDirection.right :
            print("User swiped right")

            // decrease index first

            imageIndex -= 1

            // check if index is in range

            if imageIndex < 0 {

                imageIndex = itemList.count - 1

            }
            UIImageView.transition(with: imgPhoto, duration: 0.3, options: .transitionFlipFromLeft, animations: nil, completion: nil)
            imgPhoto.image = itemList[imageIndex].image

        case UISwipeGestureRecognizerDirection.left:
            print("User swiped Left")

            // increase index first

            imageIndex += 1

            // check if index is in range

            if imageIndex > itemList.count - 1 {

                imageIndex = 0

            }
             UIImageView.transition(with: imgPhoto, duration: 0.3, options: .transitionFlipFromRight, animations: nil, completion: nil)
            imgPhoto.image = itemList[imageIndex].image
        default:


            break //stops the code/codes nothing.
        }
    }
}
}

【问题讨论】:

  • 您为什么要发布几乎same question 却在一个新帐户下?你得到和接受的答案有什么问题?此问题代码中的更改与您在其他问题的答案中给出的不同。
  • 您在 itemList[imageIndex] 上调用 .playSound 但您没有显示构建 itemList 的代码。在调用 .playSound() 之前,您是否使用调试器(和断点)检查 .delegate 是否设置为 != nil?
  • @rmaddy 我接受了另一个答案,因为它解决了我遇到的错误并且很好地解释了这个问题。现在我有这个问题。此外,我在此处发布的代码确实反映了其他答案给出的更改,不是吗?
  • itemList 中的SecondViewController 是什么?你做了什么调试?您的问题中缺少很多信息。
  • viewDidLoad 中的本地 card 变量在 viewDidLoad 末尾超出范围,因此它什么也不做。

标签: ios swift avaudioplayer delegation


【解决方案1】:

您的卡片实例不是正在播放声音的卡片,您可以在 viewDidLoad 中删除您的卡片实现,并且您必须在您从 itemList 数组中获取的卡片对象中设置委托:

func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
    imgPhoto.isUserInteractionEnabled = false
    let card = itemList[imageIndex]
    card.delegate = self
    card.playSound()
}

【讨论】:

  • 我相信这确实允许我的协议函数运行。不幸的是,我的 imgPhoto 从未被禁用,它一直处于启用状态。我已经更新了我的问题以包含您的答案,如果您可以再看一下,它现在包含了我课堂上的所有代码。
  • 没关系,我让它工作了。谢谢你的回答!
猜你喜欢
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
  • 2017-12-17
相关资源
最近更新 更多