ナビゲーションベースのアプリでプッシュアニメーションとポップアニメーションを変更する方法


221

ナビゲーションベースのアプリケーションがあり、プッシュアニメーションとポップアニメーションのアニメーションを変更したい。どうすればいいですか?

2018年を編集

この質問には多くの回答があり、かなり前からありますが、私が今最も関連性があると思うものへの回答を再選択しました。他に考えている人がいたらコメントで教えてください


25
iOS 7以降、このための公式APIがあります。UINavigationControllerDelegateのカスタム遷移アニメーションサポートを参照してください。これに関するWWDC 2013ビデオもあります。
Jesse Rusak 2013

私はこれをSwiftで実行するための回答(以下)を追加しました。Swiftの実装について尋ねるこの質問に出くわしたので、その後の実装でうまくいくと思いました。
djbp

1
公式(iOS 7以降)APIの非常に優れたチュートリアルについては、次を参照してください。bradbambara.wordpress.com
2014/04/11

1
@JesseRusakがWWDC 2013ビデオへのリンクを更新しました:developer.apple.com/videos/play/wwdc2013-218
Wojciech Rutkowski

1
私の受け入れられた回答の人nギャルを変更しました。お役に立てれば!GLHF
ジャブ

回答:


35

ナビゲーションベースのアプリでプッシュアニメーションとポップアニメーションを変更する方法...

2019年の「最終的な回答」

前文:

iOS開発に慣れていないとします。紛らわしいことに、Appleは簡単に使用できる2つのトランジションを提供しています。これらは、「クロスフェード」と「フリップ」です。

しかし、もちろん、「クロスフェード」と「フリップ」は役に立たない。それらは決して使用されません。なぜAppleがこの2つの役に立たないトランジションを提供したのか誰にもわかりません!

そう:

「スライド」などの通常の一般的な遷移を行いたいとします。その場合、あなたは莫大な量の仕事をしなければなりません!

その仕事は、この投稿で説明されています。

繰り返すだけ:

驚くべきことに:iOSでは、最も単純で最も一般的な日常のトランジション(通常のスライドなど)が必要な場合、完全なカスタムトランジションを実装するためのすべての作業を行う必要があります。

これを行う方法は次のとおりです...

1.カスタムが必要 UIViewControllerAnimatedTransitioning

  1. あなた自身のようなブール値が必要popStyleです。(飛び出していますか、飛び出していますか?)

  2. あなたはtransitionDuration(些細な)とメインコールを含める必要があります、animateTransition

  3. 実際、insideには2つの異なるルーチンを記述する必要ありますanimateTransition。1つはプッシュ用、もう1つはポップ用です。おそらくそれらに名前を付けるanimatePushanimatePop。内部animateTransitionpopStyleは、2つのルーチンに分岐します

  4. 以下の例では、単純な移動/移動を行っています

  5. あなたanimatePushanimatePopルーティンで。「from view」と「to view」を取得する必要あります。(その方法は、コード例に示されています。)

  6. そして、あなたは新しい「へ」ビューのために必要ありaddSubviewます。

  7. そしてあなたはあなたのアニメの終わりに電話しなければなりませんcompleteTransition

そう ..

  class SimpleOver: NSObject, UIViewControllerAnimatedTransitioning {
        
        var popStyle: Bool = false
        
        func transitionDuration(
            using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.20
        }
        
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            
            if popStyle {
                
                animatePop(using: transitionContext)
                return
            }
            
            let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
            let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
            
            let f = transitionContext.finalFrame(for: tz)
            
            let fOff = f.offsetBy(dx: f.width, dy: 55)
            tz.view.frame = fOff
            
            transitionContext.containerView.insertSubview(tz.view, aboveSubview: fz.view)
            
            UIView.animate(
                withDuration: transitionDuration(using: transitionContext),
                animations: {
                    tz.view.frame = f
            }, completion: {_ in 
                    transitionContext.completeTransition(true)
            })
        }
        
        func animatePop(using transitionContext: UIViewControllerContextTransitioning) {
            
            let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
            let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
            
            let f = transitionContext.initialFrame(for: fz)
            let fOffPop = f.offsetBy(dx: f.width, dy: 55)
            
            transitionContext.containerView.insertSubview(tz.view, belowSubview: fz.view)
            
            UIView.animate(
                withDuration: transitionDuration(using: transitionContext),
                animations: {
                    fz.view.frame = fOffPop
            }, completion: {_ in 
                    transitionContext.completeTransition(true)
            })
        }
    }

その後 ...

2. View Controllerで使用します。

注:奇妙なことに、これを行う必要があるのはがあるのは「最初の」View Controllerだけです。(「下」にあるもの。)

あなたがにポップしたもので、何もしませ。簡単です。

だからあなたのクラス...

class SomeScreen: UIViewController {
}

になる...

class FrontScreen: UIViewController,
        UIViewControllerTransitioningDelegate, UINavigationControllerDelegate {
    
    let simpleOver = SimpleOver()
    

    override func viewDidLoad() {
        
        super.viewDidLoad()
        navigationController?.delegate = self
    }

    func navigationController(
        _ navigationController: UINavigationController,
        animationControllerFor operation: UINavigationControllerOperation,
        from fromVC: UIViewController,
        to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        
        simpleOver.popStyle = (operation == .pop)
        return simpleOver
    }
}

それでおしまい。

通常どおりにプッシュおよびポップします。変更はありません。プッシュする ...

let n = UIStoryboard(name: "nextScreenStoryboardName", bundle: nil)
          .instantiateViewController(withIdentifier: "nextScreenStoryboardID")
          as! NextScreen
navigationController?.pushViewController(n, animated: true)

それをポップするには、次の画面でそれを実行したいだけなら可能です:

class NextScreen: TotallyOrdinaryUIViewController {
    
    @IBAction func userClickedBackOrDismissOrSomethingLikeThat() {
        
        navigationController?.popViewController(animated: true)
    }
}

ふew。


3. AnimatedTransitioningをオーバーライドする方法を説明するこのページの他の回答もお楽しみください

@AlanZeinoと@eliasの回答までスクロールして、最近のAnimatedTransitioningiOSアプリでの使用方法についてのディスカッションをご覧ください!


優れた!ナビゲーションスワイプバックジェスチャーが必要な場合は、同じAnimatedTransitioningもサポートしています。何か案が?
sam chi wen

@samchiwenに感謝-実際、それはまさに何でanimatePushありanimatePop、2つの異なる方向です!
Fattie

268

私は次のことをしました、そしてそれはうまく働きます...そしてシンプルで理解しやすいです。

CATransition* transition = [CATransition animation];
transition.duration = 0.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
//transition.subtype = kCATransitionFromTop; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[[self navigationController] popViewControllerAnimated:NO];

プッシュについても同じです。


Swift 3.0バージョン:

let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionFade
self.navigationController?.view.layer.add(transition, forKey: nil)
_ = self.navigationController?.popToRootViewController(animated: false)

34
+1、これは本当に最も健全なソリューションです。将来の訪問者のためのほんのマイナーなメモ:そのAnimated:NO部分は重要です。場合YES渡され、アニメーションが混在して面白い効果を引き起こします。
DarkDust

12
これまでのところ最適なソリューションです。初心者の場合は、QuartCore(#import <QuartzCore / QuartzCore.h>)を含めることを忘れないでください
nomann

4
このソリューションで私が抱えている唯一の問題は、アニメーションなしでプッシュした直後に、プッシュされたビューコントローラーのviewDidAppearが呼び出されることです。それを回避する方法はありますか?
ペドロマンチェノ2013年

9
このコードの私の問題は、各ビューがスライドインまたはスライドアウトすると、灰色または白に点滅するように見えることです。
クリス

1
iOS 7.1.2およびiOS 8.3でチェック—このコードは正常に機能し、メソッドの動作も良好ですsetViewControllers:
proff

256

これが私がいつもこのタスクを完了するために管理してきた方法です。

プッシュの場合:

MainView *nextView=[[MainView alloc] init];
[UIView  beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[self.navigationController pushViewController:nextView animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
[UIView commitAnimations];
[nextView release];

ポップの場合:

[UIView  beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
[UIView commitAnimations];

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelay:0.375];
[self.navigationController popViewControllerAnimated:NO];
[UIView commitAnimations];


私はまだこれから多くのフィードバックを得ているので、先に進んでアニメーションブロックを使用するように更新します。これは、とにかくアニメーションを行うためにAppleが推奨する方法です。

プッシュの場合:

MainView *nextView = [[MainView alloc] init];
[UIView animateWithDuration:0.75
                         animations:^{
                             [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                             [self.navigationController pushViewController:nextView animated:NO];
                             [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
                         }];

ポップの場合:

[UIView animateWithDuration:0.75
                         animations:^{
                             [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                             [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
                         }];
[self.navigationController popViewControllerAnimated:NO];

3
これをありがとう。しかし、ポップはUINavigationControllerによって自動的に行われます。カスタムポップロジックを呼び出せるように、その動作をどのようにオーバーライドしますか?
ジョシュアフランク

1
@stuckj実際に動作します!!! あなただけ交換する必要がsuperself.navigationController
holierthanthou84

右からデフォルトのスライドの代わりに左からスライドを取得する方法はありますか?
シム2013

1つ目は新しいビューをまったく表示しません。2番目はアニメーションを表示しません。非常に悪い答えです!iOS 7
Dmitry

2
UIViewController「ViewController」の部分がない名前をサブクラスに付けたのはなぜですか。この名前は、UIViewに適しています。
user2159978 2014年

29

プッシュ用

CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionFade;
//transition.subtype = kCATransitionFromTop;

[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController pushViewController:ViewControllerYouWantToPush animated:NO];

ポップ用

CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionFade;
//transition.subtype = kCATransitionFromTop;

[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController popViewControllerAnimated:NO];

19

@Magnusの回答、Swift(2.0)の場合のみ

    let transition = CATransition()
    transition.duration = 0.5
    transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    transition.type = kCATransitionPush
    transition.subtype = kCATransitionFromTop
    self.navigationController!.view.layer.addAnimation(transition, forKey: nil)
    let writeView : WriteViewController = self.storyboard?.instantiateViewControllerWithIdentifier("WriteView") as! WriteViewController
    self.navigationController?.pushViewController(writeView, animated: false)

いくつかの傍注:

Segueでもこれを行うことができます。これをprepareForSegueまたはに実装するだけshouldPerformSegueWithIdentifierです。しかしながら、これにより、デフォルトのアニメーションも保持されます。これを修正するには、ストーリーボードに移動し、セグエをクリックして、[アニメーション]ボックスをオフにする必要があります。ただし、これにより、アプリがIOS 9.0以降に制限されます(少なくとも、私がXcode 7で実行したとき)。

セグエで行う場合、最後の2行は次のように置き換える必要があります。

self.navigationController?.popViewControllerAnimated(false)

falseに設定しても、無視されます。


アニメーションの最後に背景の黒い色を削除する方法。
2016

プッシュビューコントローラーで動作しないアニメーションは、ポップビューコントローラーで機能します
Mukul More

16

であることを覚えておいてくださいスウィフト拡張子は間違いなくあなたの友達です!

public extension UINavigationController {

    /**
     Pop current view controller to previous view controller.

     - parameter type:     transition animation type.
     - parameter duration: transition animation duration.
     */
    func pop(transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
        self.addTransition(transitionType: type, duration: duration)
        self.popViewControllerAnimated(false)
    }

    /**
     Push a new view controller on the view controllers's stack.

     - parameter vc:       view controller to push.
     - parameter type:     transition animation type.
     - parameter duration: transition animation duration.
     */
    func push(viewController vc: UIViewController, transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
        self.addTransition(transitionType: type, duration: duration)
        self.pushViewController(vc, animated: false)
    }

    private func addTransition(transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
        let transition = CATransition()
        transition.duration = duration
        transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.type = type
        self.view.layer.addAnimation(transition, forKey: nil)
    }

}

11

Appleがプライベートコールを使用するアプリを承認しないため、プライベートコールを使用することは悪い考えです。多分あなたはこれを試すことができます:

//Init Animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.50];


[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:YES];

//Create ViewController
MyViewController *myVC = [[MyViewController alloc] initWith...];

[self.navigationController pushViewController:myVC animated:NO];
[myVC release];

//Start Animation
[UIView commitAnimations];

それは「半分」しか機能しません-それはポップアニメーションのより難しい問題を解決しません。
Adam

私はこのソリューションをよりよく気に入っています。そうです。プライベートメソッドを使用すると、確実に拒否されます。
ベンジャミンインタル

プライベートAPI呼び出しである@nicktmro。気づかなかった。
フランクリン

@Franklinを使用-pushViewController:transition:forceImmediate:することについてしばらく前にここで議論がありましたが、それは悪い考えでしょう。
nicktmro 2013

9

これがグーグルでのトップの結果なので、私は私が最も健全な方法だと思うことを共有したいと思いました。iOS 7以降の移行APIを使用します。これをiOS 10とSwift 3で実装しました。

UINavigationControllerサブクラスを作成し、UINavigationControllerそれに準拠するクラスのインスタンスを返す場合、これを2つのビューコントローラー間でアニメーション化する方法と組み合わせるのは非常に簡単です。UIViewControllerAnimatedTransitioningプロトコルにです。

たとえば、ここに私のUINavigationControllerサブクラスがあります:

class NavigationController: UINavigationController {
    init() {
        super.init(nibName: nil, bundle: nil)

        delegate = self
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension NavigationController: UINavigationControllerDelegate {

    public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return NavigationControllerAnimation(operation: operation)
    }

}

UINavigationControllerDelegate自身がに設定されていることがわかります。私のサブクラスの拡張機能ではUINavigationControllerDelegate、カスタムアニメーションコントローラー(つまり、NavigationControllerAnimation)を返すことができるメソッドを実装しています。このカスタムアニメーションコントローラーは、ストックアニメーションを置き換えます。

NavigationControllerAnimationイニシャライザを介してインスタンスにオペレーションを渡す理由を疑問に思うかもしれません。私はこれを行うのでNavigationControllerAnimationUIViewControllerAnimatedTransitioningプロトコル、操作が何であるか(つまり、「プッシュ」または「ポップ」)がわかるようにするためです。これは、どのようなアニメーションを実行すべきかを知るのに役立ちます。ほとんどの場合、操作に応じて異なるアニメーションを実行します。

残りはかなり標準的です。UIViewControllerAnimatedTransitioningプロトコルに必要な2つの関数を実装し、好きなようにアニメーション化します。

class NavigationControllerAnimation: NSObject, UIViewControllerAnimatedTransitioning {

    let operation: UINavigationControllerOperation

    init(operation: UINavigationControllerOperation) {
        self.operation = operation

        super.init()
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.3
    }

    public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
            let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else { return }
        let containerView = transitionContext.containerView

        if operation == .push {
            // do your animation for push
        } else if operation == .pop {
            // do your animation for pop
        }
    }
}

異なるタイプの操作(つまり、「プッシュ」または「ポップ」)ごとに、ビューコントローラへのアクセスとビューコントローラからのコントローラは異なることを覚えておくことが重要です。プッシュ操作中は、toビューコントローラがプッシュされます。ポップ操作の場合、toビューコントローラーが遷移先のコントローラーになり、fromビューコントローラーがポップされるコントローラーになります。

また、toビューコントローラーcontainerViewは、遷移コンテキストののサブビューとして追加する必要があります。

アニメーションが完了したら、を呼び出す必要がありますtransitionContext.completeTransition(true)。インタラクティブなトランジションを実行している場合は、アニメーションの最後でトランジションが完了しているかどうかに応じBoolcompleteTransition(didComplete: Bool)、動的にa を返す必要があります。

最後に(オプションの読み取り)、私が取り組んでいた移行をどのように行ったかを確認したい場合があります。このコードはもう少しハッキーで、すぐに書いたので、すばらしいアニメーションコードだとは言えませんが、それでもアニメーション部分の実行方法を示しています。

鉱山は本当に単純な移​​行でした。UINavigationControllerが通常行うのと同じアニメーションを模倣したかったのですが、「上の次のページ」のアニメーションではなく、古いビューコントローラの1:1アニメーションを新しいビューと同時に実装したかったのです。コントローラが表示されます。これには、2つのView Controllerが互いに固定されているように見えるという効果があります。

プッシュ操作の場合は、最初にtoViewControllerのビューの原点を画面外のx軸に設定し、それをのサブビューとして追加し、containerViewそれorigin.xをゼロに設定することで画面にアニメーション化する必要があります。同時に、画面外にfromViewController設定するorigin.xことで、のビューをアニメーション化します。

toViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.size.width, dy: 0.0)

containerView.addSubview(toViewController.view)

UIView.animate(withDuration: transitionDuration(using: transitionContext),
               delay: 0,
               options: [ UIViewAnimationOptions.curveEaseOut ],
               animations: {
                toViewController.view.frame = containerView.bounds
                fromViewController.view.frame = containerView.bounds.offsetBy(dx: -containerView.frame.size.width, dy: 0)
},
               completion: { (finished) in
                transitionContext.completeTransition(true)
})

ポップ操作は基本的に逆です。追加toViewControllerのサブビューとしてcontainerView、そして離れアニメーションfromViewControllerあなたがアニメーションのように右へtoViewController左から:

containerView.addSubview(toViewController.view)

UIView.animate(withDuration: transitionDuration(using: transitionContext),
               delay: 0,
               options: [ UIViewAnimationOptions.curveEaseOut ],
               animations: {
                fromViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.width, dy: 0)
                toViewController.view.frame = containerView.bounds
},
               completion: { (finished) in
                transitionContext.completeTransition(true)
})

これがSwiftファイル全体の要点です:

https://gist.github.com/alanzeino/603293f9da5cd0b7f6b60dc20bc766be


すごい!。私がやりたかったのは、反対方向にアニメーションするだけです。他の解決策もいくつか検討しましたが、すべて画面の左右が点滅しています。暗黙のアルファ変更アニメーションはそれらを使用して削除できないようです。このソリューションのみが問題を修正しました。
beshio 2017年

はい、これが唯一の正しい最新のソリューションです。(私は気にしませんが、それは私が以下に打ち込んだ解決策とまったく同じです!:))
Fattie

@AlanZeino同じViewController内で、ボタンのクリックごとに異なるアニメーションが必要な場合はどうでしょうか。したがって、button1にはディゾルブアニメーションが必要で、button2にはデフォルトの遷移が必要です。
jzeferino

7

UINavigationControllerDelegateとUIViewControllerAnimatedTransitioningがあり、好きなようにアニメーションを変更できます。

たとえば、これはVCの垂直ポップアニメーションです。

@objc class PopAnimator: NSObject, UIViewControllerAnimatedTransitioning {

func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
    return 0.5
}

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {

    let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
    let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
    let containerView = transitionContext.containerView()
    let bounds = UIScreen.mainScreen().bounds
    containerView!.insertSubview(toViewController.view, belowSubview: fromViewController.view)
    toViewController.view.alpha = 0.5

    let finalFrameForVC = fromViewController.view.frame

    UIView.animateWithDuration(transitionDuration(transitionContext), animations: {
        fromViewController.view.frame = CGRectOffset(finalFrameForVC, 0, bounds.height)
        toViewController.view.alpha = 1.0
        }, completion: {
            finished in
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
    })
}

}

その後

func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    if operation == .Pop {
        return PopAnimator()
    }
    return nil;
}

便利なチュートリアル https://www.objc.io/issues/5-ios7/view-controller-transitions/


6

Swift 4用に更新された回答に基づくjordanperry

プッシュ用 UIViewController

let yourVC = self.storyboard?.instantiateViewController(withIdentifier: "yourViewController") as! yourViewController
    UIView.animate(withDuration: 0.75, animations: {() -> Void in
    UIView.setAnimationCurve(.easeInOut)
    self.navigationController?.pushViewController(terms, animated: true)
    UIView.setAnimationTransition(.flipFromRight, for: (self.navigationController?.view)!, cache: false)
})

ポップ

UIView.animate(withDuration: 0.75, animations: {() -> Void in
    UIView.setAnimationCurve(.easeInOut)
    UIView.setAnimationTransition(.flipFromLeft, for: (self.navigationController?.view)!, cache: false)
})
navigationController?.popViewController(animated: false)

5

これが私がSwiftで同じことをした方法です:

プッシュの場合:

    UIView.animateWithDuration(0.75, animations: { () -> Void in
        UIView.setAnimationCurve(UIViewAnimationCurve.EaseInOut)
        self.navigationController!.pushViewController(nextView, animated: false)
        UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromRight, forView: self.navigationController!.view!, cache: false)
    })

ポップの場合:

実際には、これを上記の応答の一部とは少し異なりますが、Swift開発に慣れていないため、正しくない可能性があります。私はオーバーライドviewWillDisappear:animated:してそこにポップコードを追加しました:

    UIView.animateWithDuration(0.75, animations: { () -> Void in
        UIView.setAnimationCurve(UIViewAnimationCurve.EaseInOut)
        UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromLeft, forView: self.navigationController!.view, cache: false)
    })

    super.viewWillDisappear(animated)

5

@Luca DavanzoのSwift 4.2での回答

public extension UINavigationController {

    /**
     Pop current view controller to previous view controller.

     - parameter type:     transition animation type.
     - parameter duration: transition animation duration.
     */
    func pop(transitionType type: CATransitionType = .fade, duration: CFTimeInterval = 0.3) {
        self.addTransition(transitionType: type, duration: duration)
        self.popViewController(animated: false)
    }

    /**
     Push a new view controller on the view controllers's stack.

     - parameter vc:       view controller to push.
     - parameter type:     transition animation type.
     - parameter duration: transition animation duration.
     */
    func push(viewController vc: UIViewController, transitionType type: CATransitionType = .fade, duration: CFTimeInterval = 0.3) {
        self.addTransition(transitionType: type, duration: duration)
        self.pushViewController(vc, animated: false)
    }

    private func addTransition(transitionType type: CATransitionType = .fade, duration: CFTimeInterval = 0.3) {
        let transition = CATransition()
        transition.duration = duration
        transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
        transition.type = type
        self.view.layer.add(transition, forKey: nil)
    }

}

4

私は最近、似たようなことをしようとしていました。UINavigationControllerのスライドアニメーションは好きではないと判断しましたが、UIViewがカールなどのアニメーションを提供することもしたくありませんでした。プッシュまたはポップするときに、ビュー間でクロスフェードを実行する必要がありました。

ここでの問題は、ビューが文字通りビューを削除している、または現在のビューの上にポップしているという事実に関係しているため、フェードは機能しません。新しいビューを取得して、それをサブビューとしてUIViewControllerのスタックの現在のトップビューに追加するという解決策になりました。アルファ0で追加してから、クロスフェードを行います。アニメーションシーケンスが終了したら、ビューをアニメーション化せずにスタックにプッシュします。次に、古いtopViewに戻り、変更したものをクリーンアップします。

それよりも少し複雑です。navigationItemがあるので、トランジションが正しく見えるように調整する必要があります。また、回転を行う場合は、ビューをサブビューとして追加するときにフレームサイズを調整して、画面に正しく表示されるようにする必要があります。これが私が使用したコードの一部です。UINavigationControllerをサブクラス化し、pushメソッドとpopメソッドをオーバーライドしました。

-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
      UIViewController *currentViewController = [self.viewControllers lastObject];
      //if we don't have a current controller, we just do a normal push
      if(currentViewController == nil)
      {
         [super pushViewController:viewController animated:animated];
         return;
      }
      //if no animation was requested, we can skip the cross fade
      if(!animation)
      {
         [super pushViewController:viewController animated:NO];
         return;
      }
      //start the cross fade.  This is a tricky thing.  We basically add the new view
//as a subview of the current view, and do a cross fade through alpha values.
//then we push the new view on the stack without animating it, so it seemlessly is there.
//Finally we remove the new view that was added as a subview to the current view.

viewController.view.alpha = 0.0;
//we need to hold onto this value, we'll be releasing it later
    NSString *title = [currentViewController.title retain];

//add the view as a subview of the current view
[currentViewController.view addSubview:viewController.view];
[currentViewController.view bringSubviewToFront:viewController.view];
UIBarButtonItem *rButtonItem = currentViewController.navigationItem.rightBarButtonItem;
UIBarButtonItem *lButtonItem = currentViewController.navigationItem.leftBarButtonItem;

NSArray *array = nil;

//if we have a right bar button, we need to add it to the array, if not, we will crash when we try and assign it
//so leave it out of the array we are creating to pass as the context.  I always have a left bar button, so I'm not checking to see if it is nil. Its a little sloppy, but you may want to be checking for the left BarButtonItem as well.
if(rButtonItem != nil)
    array = [[NSArray alloc] initWithObjects:currentViewController,viewController,title,lButtonItem,rButtonItem,nil];
else {
    array = [[NSArray alloc] initWithObjects:currentViewController,viewController,title,lButtonItem,nil];
}

//remove the right bar button for our transition
[currentViewController.navigationItem setRightBarButtonItem:nil animated:YES];
//remove the left bar button and create a backbarbutton looking item
//[currentViewController.navigationItem setLeftBarButtonItem:nil animated:NO];

//set the back button
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:title style:kButtonStyle target:self action:@selector(goBack)];
[currentViewController.navigationItem setLeftBarButtonItem:backButton animated:YES];
[viewController.navigationItem setLeftBarButtonItem:backButton animated:NO];
[backButton release];

[currentViewController setTitle:viewController.title];

[UIView beginAnimations:@"push view" context:array];
[UIView setAnimationDidStopSelector:@selector(animationForCrossFadePushDidStop:finished:context:)];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.80];
[viewController.view setAlpha: 1.0];
[UIView commitAnimations];
}

-(void)animationForCrossFadePushDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{

UIViewController *c = [(NSArray*)context objectAtIndex:0];
UIViewController *n = [(NSArray*)context objectAtIndex:1];
NSString *title     = [(NSArray *)context objectAtIndex:2];
UIBarButtonItem *l = [(NSArray *)context objectAtIndex:3];
UIBarButtonItem *r = nil;
//not all views have a right bar button, if we look for it and it isn't in the context,
//we'll crash out and not complete the method, but the program won't crash.
//So, we need to check if it is there and skip it if it isn't.
if([(NSArray *)context count] == 5)
    r = [(NSArray *)context objectAtIndex:4];

//Take the new view away from being a subview of the current view so when we go back to it
//it won't be there anymore.
[[[c.view subviews] lastObject] removeFromSuperview];
[c setTitle:title];
[title release];
//set the search button
[c.navigationItem setLeftBarButtonItem:l animated:NO];
//set the next button
if(r != nil)
    [c.navigationItem setRightBarButtonItem:r animated:NO];


[super pushViewController:n animated:NO];

 }

コードで述べたように、私は常に左バーボタンの項目を持っているので、アニメーションデリゲートのコンテキストとして渡す配列に配置する前に、それがnilかどうかを確認しません。これを行う場合、そのチェックを行うことができます。

私が見つけた問題は、デリゲートメソッドでまったくクラッシュしても、プログラムがクラッシュしないことです。デリゲートの完了を停止するだけですが、警告は表示されません。
そのデリゲートルーチンでクリーンアップを行っていたので、クリーンアップが完了していないため、奇妙な視覚的な動作が発生していました。

私が作成する戻るボタンは「goBack」メソッドを呼び出し、そのメソッドは単にpopルーチンを呼び出します。

-(void)goBack
{ 
     [self popViewControllerAnimated:YES];
}

また、ここに私のポップなルーチンがあります。

-(UIViewController *)popViewControllerAnimated:(BOOL)animated
{
    //get the count for the number of viewControllers on the stack
int viewCount = [[self viewControllers] count];
//get the top view controller on the stack
UIViewController *topViewController = [self.viewControllers objectAtIndex:viewCount - 1];
//get the next viewController after the top one (this will be the new top one)
UIViewController *newTopViewController = [self.viewControllers objectAtIndex:viewCount - 2];

//if no animation was requested, we can skip the cross fade
if(!animated)
{
    [super popViewControllerAnimated:NO];
            return topViewController;
}



//start of the cross fade pop.  A bit tricky.  We need to add the new top controller
//as a subview of the curent view controler with an alpha of 0.  We then do a cross fade.
//After that we pop the view controller off the stack without animating it.
//Then the cleanup happens: if the view that was popped is not released, then we
//need to remove the subview we added and change some titles back.
newTopViewController.view.alpha = 0.0;
[topViewController.view addSubview:newTopViewController.view];
[topViewController.view bringSubviewToFront:newTopViewController.view];
NSString *title = [topViewController.title retain];
UIBarButtonItem *lButtonItem = topViewController.navigationItem.leftBarButtonItem;
UIBarButtonItem *rButtonItem = topViewController.navigationItem.rightBarButtonItem;

//set the new buttons on top of the current controller from the new top controller
if(newTopViewController.navigationItem.leftBarButtonItem != nil)
{
    [topViewController.navigationItem setLeftBarButtonItem:newTopViewController.navigationItem.leftBarButtonItem animated:YES];
}
if(newTopViewController.navigationItem.rightBarButtonItem != nil)
{
    [topViewController.navigationItem setRightBarButtonItem:newTopViewController.navigationItem.rightBarButtonItem animated:YES];
}

[topViewController setTitle:newTopViewController.title];
//[topViewController.navigationItem.leftBarButtonItem setTitle:newTopViewController.navigationItem.leftBarButtonItem.title];

NSArray *array = nil;
if(rButtonItem != nil)
    array = [[NSArray alloc] initWithObjects:topViewController,title,lButtonItem,rButtonItem,nil];
else {
    array = [[NSArray alloc] initWithObjects:topViewController,title,lButtonItem,nil];
}


[UIView beginAnimations:@"pop view" context:array];
[UIView setAnimationDidStopSelector:@selector(animationForCrossFadePopDidStop:finished:context:)];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.80];
[newTopViewController.view setAlpha: 1.0];
[UIView commitAnimations];
return topViewController;

 }

 -(void)animationForCrossFadePopDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
 {

UIViewController *c = [(NSArray *)context objectAtIndex:0];
//UIViewController *n = [(NSArray *)context objectAtIndex:1];
NSString *title = [(NSArray *)context objectAtIndex:1];
UIBarButtonItem *l = [(NSArray *)context objectAtIndex:2];
UIBarButtonItem *r = nil;



//Not all views have a right bar button.  If we look for one that isn't there
// we'll crash out and not complete this method, but the program will continue.
//So we need to check if it is therea nd skip it if it isn't.
if([(NSArray *)context count] == 4)
    r = [(NSArray *)context objectAtIndex:3];

//pop the current view from the stack without animation
[super popViewControllerAnimated:NO];

//if what was the current veiw controller is not nil, then lets correct the changes
//we made to it.
if(c != nil)
{
    //remove the subview we added for the transition
    [[c.view.subviews lastObject] removeFromSuperview];
    //reset the title we changed
    c.title = title;
    [title release];
    //replace the left bar button that we changed
    [c.navigationItem setLeftBarButtonItem:l animated:NO];
    //if we were passed a right bar button item, replace that one as well
    if(r != nil)
        [c.navigationItem setRightBarButtonItem:r animated:NO];
    else {
        [c.navigationItem setRightBarButtonItem:nil animated:NO];
    }


 }
}

それだけです。ローテーションを実装する場合は、追加のコードが必要になります。表示する前に、サブビューとして追加するビューのフレームサイズを設定する必要があります。そうしないと、向きが横向きであるという問題に遭遇しますが、前回のビューを最後に見たときは縦向きでした。したがって、それをサブビューとして追加してフェードインしますが、ポートレートとして表示されます。アニメーションなしでポップすると、同じビューですが、スタック内にあるビューはランドスケープになります。全体が少しファンキーに見えます。ローテーションの実装は誰でも少し異なるので、そのためのコードはここに含めませんでした。

それが一部の人々に役立つことを願っています。私はこのようなものを探し回ってみましたが、何も見つかりませんでした。私はこれが完璧な答えだとは思いませんが、現時点では私にとってはうまくいきます。


立派ですが、これは正直なところ、7年後の現在の解決策ではありません!
Fattie

あなたが正しいです。この回答は2011年のものでした。当時はうまくいきましたが、それ以来、状況は大きく変化しています。=)
georryan 2018年

4

これで使用できますUIView.transition。ご注意くださいanimated:false。これは、任意の移行オプション、ポップ、プッシュ、またはスタック置換で機能します。

if let nav = self.navigationController
{
    UIView.transition(with:nav.view, duration:0.3, options:.transitionCrossDissolve, animations: {
        _ = nav.popViewController(animated:false)
    }, completion:nil)
}

1
@Fattie、この特定の方法は、developer.apple.com
documentation / uikit / uiviewanimationoptions

3

iJordanの答えをインスピレーションとして使用して、このアニメーションコードをあちこちにコピー/貼り付ける代わりに、アプリ全体で使用するUINavigationControllerにカテゴリを作成するだけではどうですか。

UINavigationController + Animation.h

@interface UINavigationController (Animation)

- (void) pushViewControllerWithFlip:(UIViewController*) controller;

- (void) popViewControllerWithFlip;

@end

UINavigationController + Animation.m

@implementation UINavigationController (Animation)

- (void) pushViewControllerWithFlip:(UIViewController *) controller
{
    [UIView animateWithDuration:0.50
                     animations:^{
                         [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                         [self pushViewController:controller animated:NO];
                         [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];
                     }];
}

- (void) popViewControllerWithFlip
{
    [UIView animateWithDuration:0.5
                     animations:^{
                         [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                         [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];
                     }];

    [self popViewControllerAnimated:NO];
}

@end

次に、単にUINavigationController + Animation.hファイルをインポートして、通常どおり呼び出します。

[self.navigationController pushViewControllerWithFlip:[[NewViewController alloc] init]];

[self.navigationController popViewControllerWithFlip];

賢い。しかし、flipFromRightにハードコードではなく、UIViewAnimationTransitionの引数を取るpush / popメソッドを追加しないのはなぜですか。
Jef 2016年

@Jefこれらは便利なメソッドです。このようにして、実装者は特定のアニメーションタイプごとにどのUIViewAnimationTransition値を渡すかを覚える必要がなく、達成したいことの「英語」名でメソッドを呼び出すだけです。
DiscDev 2016年

@Jefも、あなたの提案は間違いなく有効です。私が引き続きObjective-Cを使用していて、多くのトランジションスタイルをサポートする必要がある場合(多くの異なるトランジションスタイルがユーザーを混乱させるため、お勧めしません)、UIViewAnimationTransitionタイプを取る1つのメソッドがあります。開発を容易にするいくつかの便利な方法。
DiscDev 2016年

3

とてもシンプルです

self.navigationController?.view.semanticContentAttribute = .forceRightToLeft

StackOverflowへようこそ:コード、XML、またはデータサンプルを投稿する場合は、テキストエディターでそれらの行を強調表示し、エディターのツールバーの[コードサンプル]ボタン({})をクリックするか、キーボードのCtrl + Kを使用して適切にフォーマットしてくださいそして構文はそれを強調します!
WhatsThePoint 2018

2

Applidiumで作成したカスタム遷移アニメーション(そのAPIはUINavigationControllerのAPIと一致します)を持つUINavigationControllerの代わりのドロップであるADTransitionControllerを見てください。

SwipeFadeCubeCarrouselZoomなどのプッシュアクションとポップアクションに、事前定義されたさまざまなアニメーションを使用できます。


2

ここでのすべての回答は素晴らしく、ほとんどが非常にうまく機能しますが、同じ効果を達成する少し簡単な方法があります...

プッシュの場合:

  NextViewController *nextViewController = [[NextViewController alloc] init];

  // Shift the view to take the status bar into account 
  CGRect frame = nextViewController.view.frame;
  frame.origin.y -= 20;
  frame.size.height += 20;
  nextViewController.view.frame = frame;

  [UIView transitionFromView:self.navigationController.topViewController.view toView:nextViewController.view duration:0.5 options:UIViewAnimationOptionTransitionFlipFromRight completion:^(BOOL finished) {
    [self.navigationController pushViewController:nextViewController animated:NO];
  }];

ポップの場合:

  int numViewControllers = self.navigationController.viewControllers.count;
  UIView *nextView = [[self.navigationController.viewControllers objectAtIndex:numViewControllers - 2] view];

  [UIView transitionFromView:self.navigationController.topViewController.view toView:nextView duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished) {
    [self.navigationController popViewControllerAnimated:NO];
  }];}

これは、ルートビューコントローラーにポップするとクラッシュします。
Abdullah Umer 2013年

1

トランジションアニメーションを公に変更する方法を私は知りません。

「戻る」ボタンが不要な場合モーダルビューコントローラーを使用して、「下から押す」/「フリップ」/「フェード」/(≥3.2)「ページカール」の切り替えを行う必要があります。


プライベート側、方法が-pushViewController:animated:文書化されていないメソッドを呼び出して-pushViewController:transition:forceImmediate:、あなたがフリップから左から右への移行をしたい場合は、あなたが使用することができます例えばので、

[navCtrler pushViewController:ctrler transition:10 forceImmediate:NO];

ただし、この方法で「ポップ」トランジションを変更することはできません。


1

はるかに少ないコード行で実行する方法については、この質問に対する私の回答参照してください。このメソッドを使用すると、新しいビューコントローラの疑似「プッシュ」を好きなようにアニメーション化できます。アニメーションが完了すると、標準のプッシュメソッドを使用した場合と同じように、ナビゲーションコントローラが設定されます。この例では、スライドインを左または右からアニメーション化できます。便宜上、ここでコードを繰り返します。

-(void) showVC:(UIViewController *) nextVC rightToLeft:(BOOL) rightToLeft {
    [self addChildViewController:neighbor];
    CGRect offscreenFrame = self.view.frame;
    if(rightToLeft) {
        offscreenFrame.origin.x = offscreenFrame.size.width * -1.0;
    } else if(direction == MyClimbDirectionRight) {
        offscreenFrame.origin.x = offscreenFrame.size.width;
    }
    [[neighbor view] setFrame:offscreenFrame];
    [self.view addSubview:[neighbor view]];
    [neighbor didMoveToParentViewController:self];
    [UIView animateWithDuration:0.5 animations:^{
        [[neighbor view] setFrame:self.view.frame];
    } completion:^(BOOL finished){
        [neighbor willMoveToParentViewController:nil];
        [neighbor.view removeFromSuperview];
        [neighbor removeFromParentViewController];
        [[self navigationController] pushViewController:neighbor animated:NO];
        NSMutableArray *newStack = [[[self navigationController] viewControllers] mutableCopy];
        [newStack removeObjectAtIndex:1]; //self, just below top
        [[self navigationController] setViewControllers:newStack];
    }];
}

0

サンプルアプリから、このバリエーションを確認してください。 https://github.com/mpospese/MPFoldTransition/

#pragma mark - UINavigationController(MPFoldTransition)

@implementation UINavigationController(MPFoldTransition)

//- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
- (void)pushViewController:(UIViewController *)viewController foldStyle:(MPFoldStyle)style
{
    [MPFoldTransition transitionFromViewController:[self visibleViewController] 
                                  toViewController:viewController 
                                          duration:[MPFoldTransition defaultDuration]  
                                             style:style 
                                        completion:^(BOOL finished) {
                                            [self pushViewController:viewController animated:NO];
                                        }
     ];
}

- (UIViewController *)popViewControllerWithFoldStyle:(MPFoldStyle)style
{
    UIViewController *toController = [[self viewControllers] objectAtIndex:[[self viewControllers] count] - 2];

    [MPFoldTransition transitionFromViewController:[self visibleViewController] 
                                  toViewController:toController 
                                          duration:[MPFoldTransition defaultDuration] 
                                             style:style
                                        completion:^(BOOL finished) {
                                            [self popViewControllerAnimated:NO];
                                        }
     ];

    return toController;
}

0

ただ使う:

ViewController *viewController = [[ViewController alloc] init];

UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
navController.navigationBarHidden = YES;

[self presentViewController:navController animated:YES completion: nil];
[viewController release];
[navController release];

0

これを実現することは古い問題です。viewControllers提案された回答をいくつかポップするのに問題があったので、私はまだこの回答を投稿したいと思います。私の解決策は、UINavigationControllerすべてのpopメソッドとpushメソッドをサブクラス化してオーバーライドすることです。

FlippingNavigationController.h

@interface FlippingNavigationController : UINavigationController

@end

FlippingNavigationController.m:

#import "FlippingNavigationController.h"

#define FLIP_DURATION 0.5

@implementation FlippingNavigationController

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [UIView transitionWithView:self.view
                      duration:animated?FLIP_DURATION:0
                       options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionFlipFromRight
                    animations:^{ [super pushViewController:viewController
                                                   animated:NO]; }
                    completion:nil];
}

- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
    return [[self popToViewController:[self.viewControllers[self.viewControllers.count - 2]]
                             animated:animated] lastObject];
}

- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated
{
    return [self popToViewController:[self.viewControllers firstObject]
                            animated:animated];
}

- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    __block NSArray* viewControllers = nil;

    [UIView transitionWithView:self.view
                      duration:animated?FLIP_DURATION:0
                       options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionFlipFromLeft
                    animations:^{ viewControllers = [super popToViewController:viewController animated:NO]; }
                    completion:nil];

    return viewControllers;
}

@end

0

この糸は古いのはわかっているが、2セント入れてみようと思った。カスタムアニメーションを作成する必要はありません。それを行う簡単な(おそらくハックな)方法があります。プッシュを使用する代わりに、新しいナビゲーションコントローラーを作成し、新しいビューコントローラーをそのナビゲーションコントローラーのルートビューコントローラーにして、元のナビゲーションコントローラーのナビゲーションコントローラーを表示します。Presentは多くのスタイルで簡単にカスタマイズでき、カスタムアニメーションを作成する必要はありません。

例えば:

UIViewcontroller viewControllerYouWantToPush = UIViewController()
UINavigationController newNavController = UINavigationController(root: viewControllerYouWantToView)
newNavController.navBarHidden = YES;
self.navigationController.present(newNavController)

また、プレゼンテーションスタイルは自由に変更できます。


-1

私の目的に役立つ、これを行うためのやや再帰的な方法を見つけました。通常のポップアニメーションをブロックし、アニメーション化されていない独自のポップメッセージを置き換えるために使用するインスタンス変数BOOLがあります。変数は最初はNOに設定されています。[戻る]ボタンがタップされると、デリゲートメソッドはそれをYESに設定し、アニメーション化されていない新しいポップメッセージをナビゲーションバーに送信します。これにより、同じデリゲートメソッドが再度呼び出されますが、今回は変数がYESに設定されています。変数がYESに設定されている場合、デリゲートメソッドは変数をNOに設定し、YESを返して、アニメーション化されていないポップを発生させます。2番目のデリゲート呼び出しが戻った後、最初の呼び出しに戻り、NOが返され、元のアニメーションポップがブロックされます。それは実際にはそれが聞こえるほど厄介ではありません。私のshouldPopItemメソッドは次のようになります。

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item 
{
    if ([[navigationBar items] indexOfObject:item] == 1) 
    {
        [expandedStack restack];    
    }

    if (!progPop) 
    {
        progPop = YES;
        [navBar popNavigationItemAnimated:NO];
        return NO;
    }
    else 
    {
        progPop = NO;
        return YES;
    }
}

私のために働く。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.