Swift 协议函数永远不会被调用
Swift protocol function never gets called
我目前正在研究在播放 AVAudioPlayer 时禁用 UIImageView 的代码。我要禁用的 AVAudioPlayer 和 ImageView 位于两个不同的 classes 中。我尝试编写一个委托让我的两个 classes 进行通信。出于某种原因,协议方法永远不会 运行 即使我的 class 符合协议,调用方法并将委托设置为 self。在我的 Card class 中,在 audioDidFinishPlaying 方法中,我安全地打开了委托。当我 运行 我的代码时,每次都会调用 print 语句而不是 isOn 方法。任何人都可以就此问题提供任何建议吗?
包含我的 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 函数)。
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.
}
}
}
}
您的卡片实例不是播放声音的卡片,您可以在 viewDidLoad 中删除您的卡片实现,并且您必须在从 itemList 数组获取的卡片对象中设置委托:
func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
imgPhoto.isUserInteractionEnabled = false
let card = itemList[imageIndex]
card.delegate = self
card.playSound()
}
我目前正在研究在播放 AVAudioPlayer 时禁用 UIImageView 的代码。我要禁用的 AVAudioPlayer 和 ImageView 位于两个不同的 classes 中。我尝试编写一个委托让我的两个 classes 进行通信。出于某种原因,协议方法永远不会 运行 即使我的 class 符合协议,调用方法并将委托设置为 self。在我的 Card class 中,在 audioDidFinishPlaying 方法中,我安全地打开了委托。当我 运行 我的代码时,每次都会调用 print 语句而不是 isOn 方法。任何人都可以就此问题提供任何建议吗?
包含我的 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 函数)。
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.
}
}
}
}
您的卡片实例不是播放声音的卡片,您可以在 viewDidLoad 中删除您的卡片实现,并且您必须在从 itemList 数组获取的卡片对象中设置委托:
func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
imgPhoto.isUserInteractionEnabled = false
let card = itemList[imageIndex]
card.delegate = self
card.playSound()
}