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];
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容