- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个占据整个屏幕的单元,所以一次只有一个可见单元。在单元内部,我有一个AVPlayer。在单元的父vc内,我有一个KVO观察器,它监听"timeControlStatus"
。当播放器停止播放时,我在单元格内调用函数stopVideo()
停止播放器,并显示重播按钮或播放按钮等。
3个问题:
1-如果视频停止/到达结束(如果我不使用KVO内的DispatchQueue),则在调用单元格的函数时应用崩溃。
2-当视频停止并且我确实在KVO中使用DispatchQueue时,它的观察者一直在观察并且Xcode冻结(没有崩溃)。 KVO内部有一个可无限期打印的打印语句,这就是Xcode冻结的原因。阻止它的唯一方法是杀死Xcode,否则死亡的沙滩球将继续旋转。
3-在KVO中,我尝试使用通知来发送到单元格来代替调用cell.stopVideo()
函数,但是单元格内的函数从不运行。
如何解决此问题?
应当指出,在KVO之外,其他所有功能均无法正常工作。我有一个定期的时间观察器,无论何时滚动,视频加载都很好,并且每个单元都可以完美运行,而当我按单元格停止/播放视频时,一切正常。
细胞:
protocol MyCellDelegate: class {
func sendBackPlayerAndIndexPath(_ player: AVPlayer?, currentIndexPath: IndexPath?)
}
var player: AVPlayer?
var indexPath: IndexPath?
var playerItem: AVPlayerItem? {
didSet {
// add playerItem to player
delegate?.sendBackPlayerAndIndexPath(player, indexPath)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
player = AVPlayer()
// set everything else relating to the player
}
// both get initialized in cellForItem
var delegate: MyCellDelegate?
var myModel: MyModel? {
didSet {
let url = URL(string: myModel!.videUrlStr!)
asset = AVAsset(url: url)
playerItem = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: ["playable"])
}
}
// tried using this with NotificationCenter but it didn't trigger from parent vc
@objc public func playVideo() {
if !player?.isPlaying {
player?.play()
}
// depending on certain conditions show a mute button, etc
}
// tried using this with NotificationCenter but it didn't trigger from parent vc
@objc public func stopVideo() {
player?.pause()
// depending on certain conditions show a reload button or a play button etc
}
MyVC: ViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var player: AVPlayer?
var currentIndexPath: IndexPath?
var isObserving = false
func sendBackPlayerAndIndexPath(_ player: AVPlayer?, currentIndexPath: IndexPath?) {
if isObserving {
self.player?.removeObserver(self, forKeyPath: "status", context: nil)
self.player?.removeObserver(self, forKeyPath: "timeControlStatus", context: nil)
}
guard let p = player, let i = currentIndexPath else { return }
self.player = p
self.currentIndexPath = i
isObserving = true
self.player?.addObserver(self, forKeyPath: "status", options: [.old, .new], context: nil)
self.player?.addObserver(self, forKeyPath: "timeControlStatus", options: [.old, .new], context: nil)
}
// If I don't use DispatchQueue below the app crashes
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if object as AnyObject? === player {
if keyPath == "status" {
if player?.status == .readyToPlay {
DispatchQueue.main.async { [weak self] in
self?.playVideoInCell()
}
}
}
} else if keyPath == "timeControlStatus" {
if player?.timeControlStatus == .playing {
DispatchQueue.main.async { [weak self] in
self?.playVideoInCell()
}
} else {
print("3. Player is Not Playing *** ONCE STOPPED THIS PRINTS FOREVER and Xcode freezes but doesn't crash.\n")
DispatchQueue.main.async { [weak self] in
self?.stopVideoInCell()
}
}
}
}
}
func playVideoInCell() {
guard let indexPath = currentIndexPath else { return }
guard let cell = collectionView.cellForItem(at: indexPath) as? MyCell else { return }
cell.playVideo()
// also tried sending a NotificationCenter message to the cell but it didn't trigger
}
func stopVideoInCell() {
guard let indexPath = currentIndexPath else { return }
guard let cell = collectionView.cellForItem(at: indexPath) as? MyCell else { return }
cell.stopVideo()
// also tried sending a NotificationCenter message to the cell but it didn't trigger
}
stopVideoInCell()
函数。当该函数调用单元格的
stopVideo()
函数时,
player?.pause暂停会短暂获得
EXC_BAD_ACCESS(代码= 2,地址= 0x16b01ff0)崩溃。
lldb-rpc-server_2020-06-14-155514_myMacName.crash
语句。
最佳答案
问题在于,在属性观察器中,您正在更改要观察的属性。那是一个恶性循环,一个无限的递归。 Xcode通过冻结您的应用程序来显示此信息,直到最终您崩溃(讽刺)堆栈溢出。
让我们来看一个更简单,独立的示例。我们的界面中有一个UISwitch。开了如果用户将其关闭,我们希望检测到该问题,然后将其切换回打开。该示例是执行此操作的一种愚蠢方法,但可以完美地说明您面临的问题:
class ViewController: UIViewController {
@IBOutlet weak var theSwitch: UISwitch!
class SwitchHelper: NSObject {
@objc dynamic var switchState : Bool = true
}
let switchHelper = SwitchHelper()
var observer: NSKeyValueObservation!
override func viewDidLoad() {
super.viewDidLoad()
self.observer = self.switchHelper.observe(\.switchState, options: .new) {
helper, change in
self.theSwitch.isOn.toggle()
self.theSwitch.sendActions(for: .valueChanged)
}
}
@IBAction func doSwitch(_ sender: Any) {
self.switchHelper.switchState = (sender as! UISwitch).isOn
}
}
switchState
;作为响应,我们将开关切换回On并调用
sendActions
。并且
sendActions
更改
switchState
。但是我们仍然处于观察
switchState
的代码中间!因此,我们再次执行此操作,然后再次发生。再一次,它再次发生。无限循环...
if
解决问题,就像选择使用的解决方案一样:
self.observer = self.switchHelper.observe(\.switchState, options: .new) {
helper, change in
if let val = change.newValue, !val {
self.theSwitch.isOn.toggle()
self.theSwitch.sendActions(for: .valueChanged)
}
}
var observer: NSKeyValueObservation!
func startObserving() {
self.observer = self.switchHelper.observe(\.switchState, options: .new) {
helper, change in
self.observer?.invalidate()
self.observer = nil
self.theSwitch.isOn.toggle()
self.theSwitch.sendActions(for: .valueChanged)
self.startObserving()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.startObserving()
}
startObserving
调用了它自己,但实际上不是,因为它在调用时的作用是配置观察值。直到我们观察到更改,内部花括号中的代码才会运行。
关于ios - 单元格的父vc中的Swift -AVPlayer'KVO导致Xcode卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62377105/
当应用程序启动时,您将从 ViewController(中间的那个)开始。从那里我在右边添加了 VC。当用户点击此 VC 上的按钮时,我希望该 View 消失(我目前只需将其框架更改为 900 即可实
我在 Xcode 7 中使用简单的主/详细信息分割 View 模板,并希望用户从具有主要类别的高级 Master VC 开始,然后选择一个并深入到各个项目 - 仍然在左侧- 然后当他们从第二个主 VC
我有一个名为“firstVC”的 View Controller 和另一个名为“secondVC”的 View Controller 。第二个 VC 将以模态方式呈现在第一个 VC 上,当用户按下第二
我被困在一个问题上,我有一个案例 我有一个父 VC 它有2个容器[childVC A, childVC B] API 正在调用 childVC (UIViewController) A 一旦 chil
我从呈现的 VC 导航到 VC(让我们调用 VC A)。在 VC A 中,我有一个容器 View ,它有一个 VC(让我们调用 VC B)。从 VC B 我提出了另一个 VC(我们称之为 VC C)。
我有一个主 VC(称为 VC A),它有一个子 VC(VC B)。当我点击 VC B 上的按钮时,我将其作为子 VC 关闭,但是一旦完成,我想实例化另一个 VC(VC C)。我通过在 VC B 上创建
我们正在寻求改变用户退出我们应用程序的方式。为了做到这一点,我们要关闭当前 VC 下面的所有 VC,并将另一个 VC 作为根 VC。现在我们正在这样做,我相信这不会从内存中消除下面的任何 VC。 le
我仅使用 segue 在我的应用程序中导航。 我只是想知道,如果我从 1st-VC 导航到 V2,再到 V3,然后再到 4th-VC,如何直接从 4th-VC 导航回 1st VC,而不返回到 V3、
最新的 Xcode/Swift/iOS。 我有一个主 VC(称为 StartVC),其中包含一个子 VC(称为 TopBarVC)via 和嵌入式 segue。子 VC 包含一个按钮,按下该按钮时,会
我试图将从 map 中获得的地址传递到我的其他 View Controller 中并保持相同的设置(即开关仍然打开) mapVC 名为 MapViewController,tableVC 名为 Add
我有一个嵌入在 navigationcontroller 中的 viewcontroller,它将另一个 viewcontroller 推送到堆栈上。这个推送的 View Controller 有一个
昨天更新后,我在 iPad 上遇到了这个问题:如果我加载第二个 View Controller ,它看起来比第一个 View Controller 小(见下图)。有趣的是,自从我在 iPad 上更新了
我的项目有这样的设计: VC1 ---firstSegue----> VC2 ---secondSegue---> VC3 通过使用协议(protocol)/委托(delegate)方法,我可以毫无问
图像不是从一个 VC 到另一个 VC。 问题是将它显示到主 UIViewController 中的 ImageView 。我已将所有内容正确连接到 Storyboard中。 点击here查看我的 St
如何在vc++中调用vc++dll。 在.h文件中 typedef int (*LPVAR)(char * ptr_f, char *CC); HINSTANCE hDLL; 在.cpp 文件中 hD
当我从 VC1 转到 VC2 时,如果 VC2 被解雇,我可以通过在 VC2 中设置协议(protocol)并让 VC1 符合它,轻松地将数据传回 VC1。我想做类似的事情,但有以下区别 当我从 VC
我有一个 VC(A),它有一个容器 View 并根据 segementControl 值更改它的 VC(B-C),我在 A ViewController 中发送请求并获得响应,我想确保 B 和C Vi
所以我在我的应用程序中实现了通用链接,当按下按钮时,我打开了我的第二个应用程序: UIApplication.shared.open(aUrl!) 我也接到了电话: func application(
我想在 ios 中模拟联系人列表。当点击 + 按钮添加联系人时,会出现一个新的 View Controller ,为您提供文本字段以输入联系人姓名和用于保存该联系人的其他信息。一旦你点击完成按钮,下一
我有两个 ViewControllers - Slider 和 Foo。我将 Slider 添加为 Foo subview 并将其框架设置在 Foo VC 中,但是 Slider 的框架没有改变 ->
我是一名优秀的程序员,十分优秀!