Iphone 从UIPageViewController中删除视图控制器
奇怪的是,没有直接的方法可以做到这一点。考虑下面的场景:Iphone 从UIPageViewController中删除视图控制器,iphone,objective-c,ios,cocoa-touch,Iphone,Objective C,Ios,Cocoa Touch,奇怪的是,没有直接的方法可以做到这一点。考虑下面的场景: 您有一个具有1个页面的页面视图控制器 添加另一页(共2页)并滚动至该页 我想要的是,当用户滚动回第一页时,第二页现在被删除并取消分配,用户不能再刷回该页 在转换完成后,我尝试将视图控制器作为子视图控制器删除,但它仍然允许我滚动回空页面(它不会“调整”页面视图的大小) 我想做的是可能的吗?我只是自己在学习,所以请恕我直言,但据我所知,您需要更改pageviewcontroller的数据源,而不是删除viewcontroller。pagevi
我想做的是可能的吗?我只是自己在学习,所以请恕我直言,但据我所知,您需要更改pageviewcontroller的数据源,而不是删除viewcontroller。pageviewcontroller中显示的页面数由其数据源决定,而不是由ViewController决定。maq是正确的。如果使用滚动转换,从UIPageViewController中删除子视图控制器不会阻止用户导航到已删除的“页面”时返回屏幕。如果您感兴趣,下面是我如何从UIPageViewController中删除子视图控制器的
// deleteVC is a child view controller of the UIPageViewController
[deleteVC willMoveToParentViewController:nil];
[deleteVC.view removeFromSuperview];
[deleteVC removeFromParentViewController];
var isScrolling = false
func viewDidLoad() {
...
for v in view.subviews{
if v.isKindOfClass(UIScrollView) {
(v as! UIScrollView).delegate = self
}
}
}
func scrollViewWillBeginDragging(scrollView: UIScrollView){
isScrolling = true
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView){
isScrolling = false
}
func jumpToVC{
if isScrolling { //you should not jump out when scrolling
return
}
setViewControllers([vc], direction:direction, animated:true, completion:{[unowned self] (succ) -> Void in
if succ {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.setViewControllers([vc], direction:direction, animated:false, completion:nil)
})
}
})
}
视图控制器deleteVC已从UIPageViewController的ChildViewController属性中删除,但如果用户导航到它,它仍会显示在屏幕上
在比我聪明的人找到一个优雅的解决方案之前,这里有一个解决办法(这是一个黑客——所以你必须问问自己是否真的需要从UIPageViewController中删除页面)
这些说明假定一次只显示一页
用户点击表示要删除页面的按钮后,使用SetViewController:direction:animated:completion:方法导航到下一页或上一页。当然,然后需要从数据模型中删除页面的内容
接下来(这里是黑客),创建和配置一个全新的UIPageViewController,并将其加载到前台(即在另一个UIPageViewController前面)。确保新的UIPageViewController开始显示与先前显示完全相同的页面。新的UIPageViewController将从数据源获取新的视图控制器
最后,卸载并销毁位于后台的UIPageViewController
不管怎样,maq问了一个非常好的问题。不幸的是,我没有足够的声望来投票支持这个问题。啊,敢于梦想。。。总有一天我会得到15点声誉积分 事实上,我想我解决了这个问题。这就是我的应用程序中发生的情况:
我将把这个答案放在这里只是为了我自己将来的参考,如果它对任何人都有帮助的话——我最后做的是:
setViewControllers
的完成块中,我使用修改后的数据创建/初始化了一个新的UIPageViewController(项目已删除),并在不设置动画的情况下推送它,因此屏幕上没有任何变化(我的UIPageViewController包含在UINavigationController中)ViewController
数组的副本,移除倒数第二个视图控制器(即旧的UIPageViewController)虽然这里的答案都是信息性的,但这里给出了另一种处理问题的方法: 当我第一次搜索这个问题的答案时,我搜索时的措辞让我在这个问题上陷入了困境,而不是我刚刚链接到的那个问题,所以我觉得有义务发布一个链接到另一个问题的答案,现在我已经找到了它,并且进行了一点详细阐述 matt很好地描述了这个问题: 这实际上是UIPageViewController中的一个错误。它仅在滚动样式(UIPageViewControllerTransitionStyleScroll)和 调用SetViewController后:方向:动画:完成:使用 动画:是的。因此,有两种解决办法: 不要使用UIPageViewControllerTransitionStyleScroll 或者,如果调用SetViewController:direction:animated:completion:,则使用 只有动画:没有 要清楚地看到错误,请调用 SetViewController:方向:动画:完成:然后,在 界面(作为用户),向左(向后)导航到上一页 手动。您将导航回错误的页面:而不是前面的页面 一页都没有,但你在 调用了setViewControllers:方向:已设置动画:完成: 出现此错误的原因似乎是,在使用滚动时 样式,UIPageViewController执行某种内部缓存。因此 在调用SetViewController:direction:animated:completion:, 它无法清除其内部缓存。它认为它知道 上一页是。因此,当用户向左导航到
- (void) setViewControllers:(NSArray*)viewControllers direction:(UIPageViewControllerNavigationDirection)direction animated:(BOOL)animated completion:(void (^)(BOOL))completion {
if (!animated) {
[super setViewControllers:viewControllers direction:direction animated:NO completion:completion];
return;
}
[super setViewControllers:viewControllers direction:direction animated:YES completion:^(BOOL finished){
if (finished) {
dispatch_async(dispatch_get_main_queue(), ^{
[super setViewControllers:viewControllers direction:direction animated:NO completion:completion];
});
} else {
if (completion != NULL) {
completion(finished);
}
}
}];
}
UIViewController *jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex-1];
[self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];
jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex-1];
[self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex;
[self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
- (void)deleteAViewController:(id)sender {
YourUIViewController *dyingGroup = (YourUIViewController *)sender;
NSUInteger dyingPageIndex = dyingGroup.pageIndex;
// Check to see if we are in the last page as it's a special case.
BOOL isTheLastPage = (dyingPageIndex >= YourTotalNumberOfPagesFromModel.count);
// Make a temporary jump back - make sure to use animated:NO to have it jump instantly
UIViewController *jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex-1];
[self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];
// Now delete the selected group from the model, setting the target
[YourModel deletePage:dyingPageIndex];
if (isTheLastPage) {
// Now jump to the definitive controller. In this case, it's the same one, we're just reloading it to refresh the data source.
// This time we're using animated:YES
jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex-1];
[self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
} else {
// Now jump to the definitive controller. This reloads the data source. This time we're using animated:YES
jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex];
[self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
}
}
var isScrolling = false
func viewDidLoad() {
...
for v in view.subviews{
if v.isKindOfClass(UIScrollView) {
(v as! UIScrollView).delegate = self
}
}
}
func scrollViewWillBeginDragging(scrollView: UIScrollView){
isScrolling = true
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView){
isScrolling = false
}
func jumpToVC{
if isScrolling { //you should not jump out when scrolling
return
}
setViewControllers([vc], direction:direction, animated:true, completion:{[unowned self] (succ) -> Void in
if succ {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.setViewControllers([vc], direction:direction, animated:false, completion:nil)
})
}
})
}
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers {
self.pageViewControllerTransitionInProgress = YES;
}
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
self.pageViewControllerTransitionInProgress = NO;
}
- (void)setCurrentPage:(NSString *)newCurrentPageId animated:(BOOL)animated {
if (self.pageViewControllerTransitionInProgress) {
return;
}
[self.pageContentViewController setViewControllers:@[pageDetails] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:^(BOOL finished) {
}
}
NSMutableArray *mArray = [[NSMutableArray alloc] initWithArray:self.userArray];
[mArray removeObject:userToBlock];
self.userArray = mArray;
UIViewController *startingViewController = [self viewControllerAtIndex:atIndex-1];
NSArray *viewControllers = @[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];
fileprivate var isAnimated:Bool = false
override func setViewControllers(_ viewControllers: [UIViewController]?, direction: UIPageViewControllerNavigationDirection, animated: Bool, completion: ((Bool) -> Void)? = nil) {
if self.isAnimated {
delay(0.5, closure: {
self.setViewControllers(viewControllers, direction: direction, animated: animated, completion: completion)
})
}else {
super.setViewControllers(viewControllers, direction: direction, animated: animated, completion: completion)
}
}
extension SliderViewController:UIPageViewControllerDelegate {
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
self.isAnimated = true
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
self.isAnimated = finished
}
}
func delay(_ delay:Double, closure:@escaping ()->()) {
DispatchQueue.main.asyncAfter(
deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
}