我怎样才能删除"在我的容器视图中嵌入segue,还是完全删除容器视图?

时间:2015-07-18 00:28:19

标签: ios swift

我有一个splashViewController containerView,它是在Storyboard中创建的。

在我的故事板中,我会自动将嵌入的segue从containerView拖到profileViewController

splashViewController内,我想以编程方式"销毁" containerView + profileViewController(两者都有)。

我试过这个:

self.containerView.hidden = true //obviously doesn't work. it's just visual
self.containerView.removeFromSuperView() //nope. it's just visual.

如何完全删除containerView profileViewController,确保两个deinit都适当?如果那不可能,我至少可以放弃profileViewController吗? (我只是将containerView设置为隐藏)。

注意:我在profileViewController中自动播放电影视频(循环播放)。它有声音,即使我将containerView设置为nil并从superview中删除它,声音也会继续播放。

3 个答案:

答案 0 :(得分:3)

我在这里写了一个快速示例项目来演示解决方案here。 自动播放视频(带有狗吠声)会自动在屏幕底部播放。按“停止播放器”按钮将删除子UIViewController和容器。

即使在moviePlayer停止或设置为nil后,

MPMoviePlayerController也完成了播放音频(如果MPMoviePlayerController的内部部分保留了我怀疑是问题的强引用,则不一定要解除分配)。

无论如何,在致电contentURL

之前,我在deinit上将电影播放器​​的moviePlayer.stop()设置为nil,找到了解决方法
//The `ProfileViewController` is created in the storyboard as a child of `ViewController`. 
class ViewController: UIViewController {

    @IBOutlet weak var container: UIView?

    @IBAction func stopPlayer(sender: UIButton) {            
        //We remove the child view controller (the ProfileViewController) from the parent
        for controller in self.childViewControllers {
            if let child = controller as? ProfileViewController {
                child.removeFromParentViewController() //This causes the deinit call
                container?.removeFromSuperview() //Clear up the container (stays as a black box otherwise)
            }
        }
    }
}

ProfileViewController中,我们必须更改contentURL并停止我们的电影播放器​​

class ProfileViewController: UIViewController {

    lazy var moviePlayer: MPMoviePlayerController = {
        let path = NSBundle.mainBundle().pathForResource("TestMovie", ofType: "mp4")!
        let moviePlayer = MPMoviePlayerController(contentURL: NSURL(fileURLWithPath: path)!)
        moviePlayer.movieSourceType = .File
        moviePlayer.prepareToPlay()
        moviePlayer.view.frame = self.view.frame
        return moviePlayer
    }()

    override func viewDidAppear(animated: Bool) {
        view.addSubview(moviePlayer.view)
        moviePlayer.play()

        //Looping
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "moviePlayerDidFinish:", name:MPMoviePlayerPlaybackDidFinishNotification, object: moviePlayer)
    }

    //Change our contentURL then stop
    deinit {
        moviePlayer.contentURL = nil
        moviePlayer.stop()
    }

    @objc func moviePlayerDidFinish(notification: NSNotification) {
        let reasonInt = notification.userInfo![MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] as! Int
        let reason = MPMovieFinishReason(rawValue: reasonInt)
        if (reason == MPMovieFinishReason.PlaybackEnded) {
            moviePlayer.play()
        }
    }
}

在iPhone 5设备和模拟器上测试

TL;博士

  1. 通过调用UIView
  2. 删除容器removeFromSuperview
  3. MPMoviePlayerController在停止后继续播放音频,这是一个错误。通过设置contentURL然后停止
  4. 来解决它

答案 1 :(得分:0)

这里缺少一些细节,所以我会尽力做到最好,但听起来像containerView不是UIViewController的主要视图,因为我不认为你可以说自我。 .removeFromSuperView()

如果您想要一个删除容器视图的模式,我建议您看看Apple如何建议您使用ContainerViewController执行此操作。还有一些步骤涉及但它允许您轻松添加和删除儿童。缺点是您需要将ViewController与每个视图相关联。

这听起来像你正在处理的问题是这个MPMoviePlayerController。 MPMoviePlayerController需要与其关联的视图。来自Apple的文档

  

在电影播放器​​拥有的视图中进行播放并进行播放   全屏或内联。您可以合并电影播放器​​的视图   进入您的应用程序拥有的视图层次结构,或使用   MPMoviePlayerViewController对象为您管理演示文稿。

我的猜测是没有查看任何代码,MPMoviePlayerController挂起对您删除的视图之一的引用及其强引用,因此它不允许您实际删除该视图并使其继续而不在屏幕上。

看起来在ios9中不推荐使用MPMoviePlayerController,因此您应该转移到AVPlayer,这样可以让您更好地控制视图中的电影

答案 2 :(得分:-1)

我认为你应该找到一种方法来停止播放声音。此外,您只需将nil分配给要解除分配的视图控制器即可。但是,您无法执行self = nil;