를 사용하여 모달 뷰 컨트롤러를 닫을 때 dismissViewController
완료 블록을 제공하는 옵션이 있습니다. 에 대해 비슷한 것이 popViewController
있습니까?
완료 인수는 매우 편리합니다. 예를 들어, 모달이 화면에서 벗어날 때까지 테이블 뷰에서 행 제거를 보류하여 사용자가 행 애니메이션을 볼 수 있도록 할 수 있습니다. 푸시 뷰 컨트롤러에서 돌아올 때도 같은 기회를 원합니다.
내가 배치를 시도 popViewController
에 UIView
나는 완료 블록에 액세스 할 수 있습니까 애니메이션 블록. 그러나 이로 인해 팝업되는 뷰에 원치 않는 부작용이 발생합니다.
이러한 방법을 사용할 수없는 경우 몇 가지 해결 방법은 무엇입니까?
답변
2 년 전에 답변이 받아 들여진 것을 알고 있지만이 답변은 불완전합니다.
원하는 것을 즉시 수행 할 수있는 방법은 없습니다.
이는 UINavigationController
API가 이에 대한 옵션을 제공하지 않기 때문에 기술적으로 정확 합니다. 그러나 CoreAnimation 프레임 워크를 사용하면 기본 애니메이션에 완료 블록을 추가 할 수 있습니다.
[CATransaction begin];
[CATransaction setCompletionBlock:^{
// handle completion here
}];
[self.navigationController popViewControllerAnimated:YES];
[CATransaction commit];
완료 블록은에 의해 사용 된 애니메이션이 popViewControllerAnimated:
종료 되는 즉시 호출됩니다 . 이 기능은 iOS 4부터 사용할 수 있습니다.
답변
들어 iOS9 SWIFT 버전 – (이전 버전에 대한 테스트를하지 않은) 매력처럼 작동합니다. 이 답변을 바탕으로
extension UINavigationController {
func pushViewController(viewController: UIViewController, animated: Bool, completion: () -> ()) {
pushViewController(viewController, animated: animated)
if let coordinator = transitionCoordinator() where animated {
coordinator.animateAlongsideTransition(nil) { _ in
completion()
}
} else {
completion()
}
}
func popViewController(animated: Bool, completion: () -> ()) {
popViewControllerAnimated(animated)
if let coordinator = transitionCoordinator() where animated {
coordinator.animateAlongsideTransition(nil) { _ in
completion()
}
} else {
completion()
}
}
}
답변
@JorisKluivers 답변 Swift
으로 확장 버전을 만들었습니다 .
push
및에 대해 애니메이션이 완료된 후 완료 클로저를 호출합니다 pop
.
extension UINavigationController {
func popViewControllerWithHandler(completion: ()->()) {
CATransaction.begin()
CATransaction.setCompletionBlock(completion)
self.popViewControllerAnimated(true)
CATransaction.commit()
}
func pushViewController(viewController: UIViewController, completion: ()->()) {
CATransaction.begin()
CATransaction.setCompletionBlock(completion)
self.pushViewController(viewController, animated: true)
CATransaction.commit()
}
}
답변
SWIFT 4.1
extension UINavigationController {
func pushToViewController(_ viewController: UIViewController, animated:Bool = true, completion: @escaping ()->()) {
CATransaction.begin()
CATransaction.setCompletionBlock(completion)
self.pushViewController(viewController, animated: animated)
CATransaction.commit()
}
func popViewController(animated:Bool = true, completion: @escaping ()->()) {
CATransaction.begin()
CATransaction.setCompletionBlock(completion)
self.popViewController(animated: animated)
CATransaction.commit()
}
func popToViewController(_ viewController: UIViewController, animated:Bool = true, completion: @escaping ()->()) {
CATransaction.begin()
CATransaction.setCompletionBlock(completion)
self.popToViewController(viewController, animated: animated)
CATransaction.commit()
}
func popToRootViewController(animated:Bool = true, completion: @escaping ()->()) {
CATransaction.begin()
CATransaction.setCompletionBlock(completion)
self.popToRootViewController(animated: animated)
CATransaction.commit()
}
}
답변
나는 같은 문제가 있었다. 그리고 여러 차례에 걸쳐 완료 블록 체인 내에서 사용해야했기 때문에 UINavigationController 하위 클래스에서이 일반 솔루션을 만들었습니다.
- (void) navigationController:(UINavigationController *) navigationController didShowViewController:(UIViewController *) viewController animated:(BOOL) animated {
if (_completion) {
dispatch_async(dispatch_get_main_queue(),
^{
_completion();
_completion = nil;
});
}
}
- (UIViewController *) popViewControllerAnimated:(BOOL) animated completion:(void (^)()) completion {
_completion = completion;
return [super popViewControllerAnimated:animated];
}
가정
@interface NavigationController : UINavigationController <UINavigationControllerDelegate>
과
@implementation NavigationController {
void (^_completion)();
}
과
- (id) initWithRootViewController:(UIViewController *) rootViewController {
self = [super initWithRootViewController:rootViewController];
if (self) {
self.delegate = self;
}
return self;
}
답변
원하는 것을 즉시 수행 할 수있는 방법은 없습니다. 즉, 탐색 스택에서 뷰 컨트롤러를 팝업하는 완료 블록이있는 메서드가 없습니다.
내가 할 일은 논리를 viewDidAppear
. 뷰가 화면에 표시되면 호출됩니다. 뷰 컨트롤러가 나타나는 모든 다른 시나리오에 대해 호출되지만 괜찮습니다.
또는이 UINavigationControllerDelegate
방법 navigationController:didShowViewController:animated:
을 사용하여 비슷한 작업을 수행 할 수 있습니다 . 내비게이션 컨트롤러가 뷰 컨트롤러를 밀거나 터 뜨렸을 때 호출됩니다.
답변
애니메이션을 올바르게 사용하거나 사용하지 않고 popToRootViewController
다음 을 포함합니다 .
// updated for Swift 3.0
extension UINavigationController {
private func doAfterAnimatingTransition(animated: Bool, completion: @escaping (() -> Void)) {
if let coordinator = transitionCoordinator, animated {
coordinator.animate(alongsideTransition: nil, completion: { _ in
completion()
})
} else {
DispatchQueue.main.async {
completion()
}
}
}
func pushViewController(viewController: UIViewController, animated: Bool, completion: @escaping (() -> Void)) {
pushViewController(viewController, animated: animated)
doAfterAnimatingTransition(animated: animated, completion: completion)
}
func popViewController(animated: Bool, completion: @escaping (() -> Void)) {
popViewController(animated: animated)
doAfterAnimatingTransition(animated: animated, completion: completion)
}
func popToRootViewController(animated: Bool, completion: @escaping (() -> Void)) {
popToRootViewController(animated: animated)
doAfterAnimatingTransition(animated: animated, completion: completion)
}
}