iOS了解之UIViewController

目錄

  1. UIViewController生命周期
  2. 跳轉
  3. 高度自定義控制器間過渡
  4. ViewController 間傳值
  5. 容器視圖控制器
  6. CGFloat、CGPoint、CGSize、CGRect
  7. 屏幕旋轉
  1. UIViewController生命周期

見iOS調試篇

注意:上下拉手機的菜單,并不會走VC的apperar、disappear方法
  1. 跳轉

方式一(present從下方彈出)

    // present下一頁
    [self presentViewController:vc animated:true completion:^{
    }];
    // 返回上一頁
    [self dismissViewControllerAnimated:true completion:^{
    }];
彈出氣泡視圖

    // 1.自定義控制器(:UIViewController)
    YTGrabOrderPopViewController *grabPopC=[YTGrabOrderPopViewController new];
    // 設置pop視圖顯示大小
    [grabPopC setPreferredContentSize:CGSizeMake(142, 160)];
    // 設置presentVC的彈出方式為pop
    [grabPopC setModalPresentationStyle:UIModalPresentationPopover];
    
    // 2.
    UIPopoverPresentationController *popVC=[grabPopC popoverPresentationController];
    [popVC setDelegate:self];       // <UIPopoverPresentationControllerDelegate>
    // 方式一:對于View
    [popVC setSourceView:button];                  // 
    [popVC setSourceRect:button.bounds];    // 位置:可調整
    // 方式二:對于UIBarButtonItem
    [popVC setBarButtonItem:[UIBarButtonItem new]];
    
    // 3.彈出
    [self presentViewController:grabPopC animated:true completion:^{
    }];
present前可以配置過渡類型(高度自定義 參見下一節)

    [vc setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
    /*
     過渡style

     UIModalTransitionStyleCoverVertical  由下而上(默認)
     UIModalTransitionStyleCrossDissolve  淡入淡出
     UIModalTransitionStyleFlipHorizontal 右側向上翻轉
     UIModalTransitionStylePartialCurl    向上翻頁
     */
    [vc setModalPresentationStyle:UIModalPresentationFullScreen];
    /*
     彈出style

     UIModalPresentationFullScreen         全屏(默認,原VC的View消失)
     UIModalPresentationOverFullScreen     占滿全屏(原VC的View不消失)
     UIModalPresentationPageSheet
     UIModalPresentationFormSheet
     UIModalPresentationCurrentContext
     UIModalPresentationCustom
     UIModalPresentationOverCurrentContext
     UIModalPresentationPopover      氣泡
     UIModalPresentationNone
     */
    // 彈出我的是誰
    id presentVC=self.presentingViewController;
    // 我彈出的是誰
    id presentedVC=self.presentedViewController;

方式二(具體參見iOS之UINavigationController篇)

push(從右側彈出)
    前提:在push棧中,[[UINavigationController alloc]initWithRootViewController:[UIViewController new]];


    》》》跳轉到下一頁(2種)
    // 方式一
    [self.navigationController pushViewController:[UIViewController new] animated:true];
    // 方式二
    [self.navigationController showViewController:[UIViewController new] sender:nil];


    》》》返回到上一頁(3種)
    // 一:返回到上一頁
    [self.navigationController popViewControllerAnimated:true];
    // 二:返回到根視圖頁
    [self.navigationController popToRootViewControllerAnimated:true];
    // 三:返回到指定頁(頁面必須在堆棧中)
    [self.navigationController popToViewController:self.navigationController.viewControllers[0] animated:true];
  1. 高度自定義控制器間過渡

TransitionManager.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface TransitionManager : NSObject<UIViewControllerAnimatedTransitioning,UIViewControllerTransitioningDelegate>
/**
 true:正在present
 false:正在dismiss
 */
@property (nonatomic,assign) BOOL presenting;
@end

TransitionManager.m

#import "TransitionManager.h"
@interface TransitionManager()
@end

@implementation TransitionManager
// 動畫結束時(不一定和過渡時間一致,只要動畫停止)調用
-(void)animationEnded:(BOOL)transitionCompleted{
    if(!transitionCompleted){   //
    }else{
    }
}

#pragma mark UIViewControllerAnimatedTransitioning
// 過渡時調用(1.獲取到2個VC的View(2個階段VC代表的不一樣)   2. 分為兩個階段做不同的變化)
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    //
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *toView = toVC.view;
    UIView *fromView = fromVC.view;

    // [toVC beginAppearanceTransition:YES animated:YES];  toVC 調用viewWillAppear  不加不會調用
    if(self.presenting){
        // 階段1
        [self RunPresentAnimation:transitionContext fromVC:fromVC toVC:toVC fromView:fromView toView:toView];
    }else{
        // 階段2
        [self RunDismissAnimation:transitionContext fromVC:fromVC toVC:toVC fromView:fromView toView:toView];
    }
    // [fromVC beginAppearanceTransition:NO animated:YES];  fromVC 調用viewDidDisappear
}
// 過渡時間(沒什么影響,真正決定的還是以上方法中動畫設置的時間)
-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return 0.82;
}


#pragma mark UIViewControllerTransitioningDelegate
// 當present VC后調用,返回 過渡動畫管理者(實現了UIViewControllerAnimatedTransitioning的類),一般返回單獨的遵守該協議的動畫類
-(id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
    self.presenting=true;
    return self;
}
// 當dismiss VC后調用,返回 過渡動畫管理者
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{
    self.presenting=false;
    return self;
}

// 返回<UIViewControllerInteractiveTransitioning>
//- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator{
//
//}
// 返回<UIViewControllerInteractiveTransitioning>
//- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator{
//
//}
//
//// 返回 :UIPresentationController
//- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(nullable UIViewController *)presenting sourceViewController:(UIViewController *)source{
//
//}





// 動畫階段1(presenting)-——自定義方法
-(void)RunPresentAnimation:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView {
    
    /*
     設置toVC的初始位置,并添加到總容器View上(此時fromView已經在上面)
     */
    // 獲取總容器View
    UIView* containerView = [transitionContext containerView];
    // 獲取fromVC的frame
    CGRect frame = [transitionContext initialFrameForViewController:fromVC];
    // 底部滑進 離屏滑入 即y坐標 從height --->0
    CGRect offScreenFrame = frame;
    offScreenFrame.origin.y = offScreenFrame.size.height;
    toView.frame = offScreenFrame;
    //
    [containerView insertSubview:toView aboveSubview:fromView];
    
    /*
     對formView 和 toView 進行動畫
     */
    //三維變化
    CATransform3D t1 = CATransform3DIdentity;
    t1.m34 = 1.0/-1000;
    //x y方向各縮放比例為0.95
    t1 = CATransform3DScale(t1, 0.95, 0.95, 1);
    //x方向旋轉15°
    t1 = CATransform3DRotate(t1, 15.0f * M_PI/180.0f, 1, 0, 0);
    
    CATransform3D t2 = CATransform3DIdentity;
    t2.m34 = 1.0/-1000;
    //沿Y方向向上移動
    t2 = CATransform3DTranslate(t2, 0, -fromView.frame.size.height*0.08, 0);
    //在x y方向各縮放比例為0.8
    t2 = CATransform3DScale(t2, 0.8, 0.8, 1);
    
    //UIView關鍵幀動畫 總的持續時間:1.0
    [UIView animateKeyframesWithDuration:1.0 delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeCubic animations:^{
        
        //開始時間:1.0*0.0 持續時間:1.0*0.4
        [UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.4f animations:^{
            //執行t1動畫 縮放并旋轉角度
            fromView.layer.transform = t1;
            //fromView的透明度
            fromView.alpha = 0.6;
        }];
        //開始時間:1.0*0.1 持續時間:1.0*0.5
        [UIView addKeyframeWithRelativeStartTime:0.1f relativeDuration:0.5f animations:^{
            //執行t2動畫 向上平移和縮放
            fromView.layer.transform = t2;
        }];
        //開始時間:1.0*0.0 持續時間:1.0*1.0
        [UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:1.0f animations:^{
            //toView向上滑入
            toView.frame = frame;
        }];
        
    } completion:^(BOOL finished) {
        
        // 過渡動畫結束
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}
// 動畫階段2-——自定義方法
-(void)RunDismissAnimation:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView {
    
    /*
     隱藏vc2,還原vc1
     */
    CGRect frame = [transitionContext initialFrameForViewController:fromVC];
    toView.frame = frame;
    
    CGRect frameOffScreen = frame;
    frameOffScreen.origin.y = frame.size.height;
    
    CATransform3D t1 = CATransform3DIdentity;
    t1.m34 = 1.0/-1000;
    t1 = CATransform3DScale(t1, 0.95, 0.95, 1);
    t1 = CATransform3DRotate(t1, 15.0f * M_PI/180.0f, 1, 0, 0);
    
    // 關鍵幀過渡動畫
    [UIView animateKeyframesWithDuration:1.0 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeCubic animations:^{
        
        [UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:1.0f animations:^{
            fromView.frame = frameOffScreen;
        }];
        
        [UIView addKeyframeWithRelativeStartTime:0.35f relativeDuration:0.35f animations:^{
            toView.layer.transform = t1;
            //透明度為1.0
            toView.alpha = 1.0;
        }];
        [UIView addKeyframeWithRelativeStartTime:0.75f relativeDuration:0.25f animations:^{
            //還原3D狀態
            toView.layer.transform = CATransform3DIdentity;
        }];
    } completion:^(BOOL finished) {
        
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

@end
  1. ViewController 間傳值

方式一 (通過屬性傳值)

/**
 id
 */
@property (nonatomic,copy) NSString *expertId;

方式二 (通過block傳值)

/**
 attentionBlock
 */
@property (nonatomic,copy) void (^attentionBlock)(NSString *expertId);

方式三 (dele)

@protocol ExpertViewControllerDele <NSObject>
-(void)attentionExpert:(NSString *)expertId;
@end

@property (nonatomic,weak) id<ExpertViewControllerDele> *dele;

方式四 (通知)

    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(handleAttention:) name:@"AttentionExpert" object:nil];
    [[NSNotificationCenter defaultCenter]postNotificationName:@"AttentionExpert" object:@{@"expertId":@"110",@"isAttention":@(1)}];

方式五 (target+action)

  1. 容器視圖控制器

系統自帶的容器視圖控制器:UINavigationController, UITabBarController和UISplitViewController


普通子控制器

點擊按鈕進入頁面B(根據接口獲取的不同的狀態,進入不同的頁面)

一般把判斷的邏輯放在頁面B,而不是按鈕所在的頁面A。這時需要根據不同的條件添加不同的控制器以顯示不同的頁面。
    // 添加
    [self addChildViewController:vc];
    [self.view addSubview:vc.view];    // 注意:這里會調用viewDidLoad等方法

    // 移除
    [vc removeFromParentViewController];     // 將vc從總VC中移除,此時視圖還在屏幕上
    [vc.view removeFromSuperview];           // 將vc的view移除

6. CGFloat、CGPoint、CGSize、CGRect

CGFloat 
    在UIView的坐標系統中,使用CGFloat類型的數據而不是Double或者Float
    let x=CGFloat(12.0) :將Double或者Float轉換成CGFloat
CGPoint
    var point=CGPoint(x:30.0,y:50.0)
CGSize
    var size=CGSize(width:20.0,height:10.0)
CGRect
    var rect=CGRect(origin:point,size:size) 
    var rect=CGRect(x:10.0,y:10.0,width:20.0,height:5.0)
    使用:
          minX      minY        midX        midY       maxX       maxY        rect1.intersects(rect2)   是否 相交
          rect1.intersect(rect2)            返回相交部分
          rect1.contains(rect2)             是否 包含

常用:
//
        CGRectZero  
// 是否有交集
        CGRectIntersectsRect(rect1, rect2)              
// 返回交集rect
        CGRectIntersection(rect1, rect2)                  
// 是否相同
        CGRectEqualToRect(rect1, rect2)               
// 是否包含 
        CGRectContainsRect(rect1, rect2)                  
// 是否包含某點
        CGRectContainsPoint(rect, CGPointMake(0, 0))      
// 返回合集
        CGRectUnion(rect1, rect2)                       
// frame<——>str 
        CGRectFromString(NSStringFromCGRect(frame))    
//
        CGRectGetMidX(rect) 
        CGRectGetMinX(rect) 
        CGRectGetMaxX(rect) 
        CGRectGetMidY(rect) 
        CGRectGetMinY(rect) 
        CGRectGetMaxY(rect)  
        CGRectGetWidth(rect)
        CGRectGetHeight(rect)

7. 屏幕旋轉

  1. 選擇項目支持的旋轉方向

方式1

項目 | General | Deployment Info 下選擇項目支持的方向
  Portrait 正常方向  (Home鍵在下)
  Landscape Left    (Home鍵在)
  Landscape Right   (Home鍵在)
  Upside Down       (Home鍵在上)
App支持的旋轉方向

方式2

AppDelegate中+

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    return UIInterfaceOrientationMaskPortrait;
}
  1. 指定頁面旋轉
/**
想讓某頁面旋轉,那它的父級頁面也必須支持旋轉
*/
1.自定義UITabbarController中+
// IOS6后
// 是否允許旋轉
-(BOOL)shouldAutorotate{
    return self.selectedViewController.shouldAutorotate;
}
// 返回 哪些方向允許旋轉
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return self.selectedViewController.supportedInterfaceOrientations;
}
/*
UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),//向上為正方向的豎屏
UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),//向左移旋轉的橫屏
UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),//向右旋轉的橫屏
UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),//向下為正方向的豎屏
UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),//向左或者向右的橫屏
UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),//所有的橫豎屏方向都支持
UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),//支持向上的豎屏和左右方向的橫屏
*/
// 返回 最優先使用的方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationPortrait;
}
/*
UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown,//屏幕方向未知
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,//向上正方向的豎屏
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,//向下正方向的豎屏
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,//向右旋轉的橫屏
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft//向左旋轉的橫屏
此方法用來設置當前頁面默認第一次進入的時候顯示的屏幕方向
*/

// IOS6前
// VC是否支持旋轉屏幕(不支持則旋轉屏幕時界面不動)
//- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
//    return toInterfaceOrientation==UIInterfaceOrientationPortrait;
//}

2.自定義Nav中+
-(BOOL)shouldAutorotate{
    return self.topViewController.shouldAutorotate;  
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return self.topViewController.supportedInterfaceOrientations;
}

3.自定義基類VC中+
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}
-(BOOL)shouldAutorotate{
    return false;
}

4.需要旋轉的VC中+
-(BOOL)shouldAutorotate{
    return true;
}
  1. 主動旋轉
當用戶設置iPhone禁止旋轉后,以上方法失效(即不會旋轉)
    [[UIDevice currentDevice]setValue:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight] forKey:@"orientation"];
  1. 監聽旋轉
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容