美文网首页
iOS 基础复习

iOS 基础复习

作者: MR_詹 | 来源:发表于2020-03-09 00:04 被阅读0次

1、状态栏

从iOS7开始,系统提供了2种管理状态栏的方式
(1)通过UIViewController管理(每一个UIViewController都可以拥有自己不同的状态栏)
(2)通过UIApplication管理(一个应用程序的状态栏都是由它统一管理)

备注:在不同的场景需要设置的方式不同
(1) View controller-based status bar appearance = NO;
    在iOS9之后,只能是在plist文件中,全局设置状态栏,UIApplication的方法已经被弃用

(2) View controller-based status bar appearance = YES;
 a> 没有导航栏UINavigationController的ViewController,由ViewController自己管理自己
    // 状态栏的样式
    - (UIStatusBarStyle)preferredStatusBarStyle;
    // 状态栏的可见性
    - (BOOL)prefersStatusHidden;
    // 状态栏切换时的动画
    - (UIStatusBarAnimation)preferredStatusBarUpdateAnimation ;
    // 可以使用viewController方法更新状态栏设置
    [self setNeedsStatusBarAppearanceUpdate];

 b> 有UINavigationController的ViewController,
    UINavigationController不会将preferredStatusBarStyle这个方法的调用转给它的子视图,而是有导航栏本身进行管理控制
    需要通过导航栏navigationBar的barStyle属性修改,
    // 状态栏文本颜色设置为白色
    self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
    // 状态栏文本颜色设置为黑市,默认就是黑色
    self.navigationController.navigationBar.barStyle = UIBarStyleDefault;

 c> 继承UINavigationController,比如LYNavigationController
     重写以下的方法,就可以将状态栏修改的权利下放给ViewController
      - (UIViewController *)childViewControllerForStatusBarStyle {
        return self.topViewController;
      }
      - (UIViewController *)childViewControllerForStatusBarHidden {
        return self.topViewController;
      }

    ViewController可以继续使用一下方法修改状态栏
     // 状态栏的样式
    - (UIStatusBarStyle)preferredStatusBarStyle;
    // 状态栏的可见性
    - (BOOL)prefersStatusHidden;
    // 可以使用viewController方法更新状态栏设置
    [self setNeedsStatusBarAppearanceUpdate];

2、openURL

(1)iOS 10之前
    [[UIApplication sharedApplication] openURL:url];
(2)iOS10之后
    [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success) {
    }]

  备注:作用
    (1) 打电话
    url = @"tel://10086";
    (2) 发短信
    url = @"sms://10086";
    (3) 发邮件
    url = @"mailto://123456@qq.com";
    (4) 打开网页
    url = @"https://www.baidu.com";
    (5) 打开其他的app
  

3、UIApplication 和 delegate

iOS13之后苹果系统为了支持iPadOS的多窗口,推出了SceneDelegate类
###iOS13之前
Appdelegate负责全权处理App生命周期和UI生命周期

// 应用程序启动完毕时调用
- (void)applicationDidFinishLaunching:(UIApplication *)application;
// 应用程序获取焦点
// 焦点:能否与用户进行交互
- (void)applicationDidBecomeActive:(UIApplication *)application;
// 应用程序将要失去焦点时调用
- (void)applicationWillResignActive:(UIApplication *)application;
// 应用程序即将进入后台
- (void)applicationWillEnterForeground:(UIApplication *)application API_AVAILABLE(ios(4.0));
// 应用程序已经进入后台
- (void)applicationDidEnterBackground:(UIApplication *)application API_AVAILABLE(ios(4.0));
// 当应用程序收到内存警告时调用(程序员去清理缓存、图片、视频)
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application;
// 当应用程序退出的时候调用
- (void)applicationWillTerminate:(UIApplication *)application;


### iOS13之后,
Appdelegate负责处理
* 处理App生命周期
* 新的Scene Session 生命周期
SceneDelegate负责处理
*所有UI生命周期

image.png image.png

4、应用程序启动流程


  1、执行main函数
  2、执行UIApplicationMain,创建UIApplication对象,并设置UIApplication它的代理
  3、开启了一个事件循环(mainRunloop),主运转循环,保证应用程序不会退出
  4、加载info.plist(判断info.list当中有没有main,如果有,加载Main.storyBoard,如果没有就直接执行第五步)
  5、应用程序启动完毕(通知代理应用程序启动完毕)


int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        // Setup code that might create autoreleased objects goes here.
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

5、UIWindow

### iOS13之前
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // 1.创建窗口
    self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    // 2.设置窗口的根控制器
    UIViewController *vc = [UIViewController new];
    self.window.rootViewController = vc;
    // 3.显示窗口
    [self.window makeKeyAndVisible];

    ## iOS9之后,如果添加了多个窗口,控制器它会自动把状态栏给隐藏掉
    // 解决办法:把状态栏给应用程序管理
    // 将View controller-based status bar appearance 设置成NO
    self.window1 = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    // 2.设置窗口的根控制器
    UIViewController *mvc = [UIViewController new];
    self.window1.rootViewController = mvc;
    // 3.显示窗口
    [self.window1 makeKeyAndVisible];

    ## 设置窗口层级
    //  级别等级:UIWindowLevelStatusBar > UIWindowLevelAlert > UIWindowLevelNormal
    self.window1.windowLevel = UIWindowLevelStatusBar;

   ## alertView 、 键盘、状态栏其实都是window
  
    return YES;
}

6、 通过storyBoard加载控制器

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    UIWindowScene *windowScene = (UIWindowScene *)scene;
    self.window = [[UIWindow alloc] initWithWindowScene:windowScene];
    self.window.frame = windowScene.coordinateSpace.bounds;
    self.window.backgroundColor = [UIColor grayColor];
    
    // 通过storyBoard加载控制器
    // 1、创建storyBoard对象(比如加载Main.storyBoard对象)
    UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    // 2、加载storyBoard箭头指向的控制器
    UIViewController *vc = [storyBoard instantiateInitialViewController];
    
    // 可以加载storyBoard中指定的控制,通过storyBoardID
    UIViewController *other = [storyBoard instantiateViewControllerWithIdentifier:@"otherStoryBoard"];
    
    self.window.rootViewController = vc;
    [self.window makeKeyAndVisible];
}


#备注
如果初始不需要使用Main.storyBoard,或者是说使用自己其他指定的控制器,请将info.plist文件中的以下值设置为空
Main storyboard file base name = 空值
好处:可以避免应用程序启动的时候默认加载一个Main.storyBoard文件创建一个不需要用的控制器,可以节省内存
image.png storyBoard

7、 通过xib加载控制器

xibView2.gif image.png

8、 loadView

loadView 是 viewController中View的生命周期其中一环
loadView 作用:用来创建控制器的View
什么时候调用:当控制器的View,第一次使用的时候调用
loadView的底层原理:
1、先判断当前控制器是不是从storeBoard加载的控制器,如果是从storyBoard加载的控制器,那么它就会从storyBoard当中加载的控制器的View,设置当前控制器的view
2、当前控制器是不是从xib当中加载的,如果是从xib当中加载的话,把xib当中指定的View,设置为当前控制的view
3、如果也不是从xib加载的,它会创建一个空白的View

// 一旦重写了loadView的方法,就说明要自己定义View 
# 使用场景:当前控制器的View一显示时,就 是一张图片,或者UIWebView
# 好处:可以节省内存,少创建一个空白的View
- (void)loadView {
  // 特别注意的一定,比如下面的写法会造成死循环
  // 原因:
  // self.view.bounds是调用了self.view的getter方法,而self.view的getter方法底层写法类似以下
  // - (UIView *)view {
  //  if (_view == nil) {
  //      [self loadView];
  //  }
  //  return _view;
  // }
  // self.view = [[UIView alloc]initWithFrame:self.view.bounds];
  
  #正确写法
  self.view = [[UIView alloc]initWithFrame:[UIScreen mainScreen].bounds];

  #如果想self.view是一张图片,写法如下
  UIImageView *imgView = [[UIImageView alloc]initWithImage:@"test.jpg"];
  self.view = imgView;
}


- (void)viewDidLoad {
  [super viewDidLoad];

}

死循环导致内存溢出

9、 数据可持续

1、plist文件(不能保存自定义对象 )

    // 举例:
    // 将一组数组保存到Document目录中的data.plist文件
    
    // Document路径
    // 第一个参数:搜索的目录
    // 第二个参数:搜索的范围
    // 第三个参数:是否展开路径(在iOS中使用YES,MAC才使用NO)
   NSString * path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
   NSString *filePath = [path stringByAppendingPathComponent:@"data.plist"];

   NSArray *dataArr = @[@"one",@"two",@"three"];
   [dataArr writeToFile:filePath atomically:YES];

    // 读取数据
    NSArray *readData = [NSArray arrayWithContentsOfFile:filePath];
    NSLog(@"%@",readData);

2、 偏好设置(NSUserDefaults)

    // NSUserDefaults它保存也是一个plist文件
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    // 保存值
    [defaults setObject:@"test" forKey:@"name"];
    [defaults setBool:1 forKey:@"autoLoin"];
    // 取出值
    BOOL isAutoLogin = [defaults boolForKey:@"autoLoin"];
    NSString *name = [defaults objectForKey:@"name"];
    // 立即同步写入(否则系统会在某个时间点保存)
    [defaults synchronize];

3、归档

Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject<NSCoding>
@property (nonatomic,  copy , readwrite) NSString      *name;
@property (nonatomic, assign, readwrite) NSInteger      age;
@end

Person.m
#import "Person.h"

@implementation Person

/// 在归档时,告诉系统哪些属性要保存的
/// @param coder coder
- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:self.name forKey:@"name"];
    [coder encodeInteger:self.age forKey:@"age"];
}


/// 解档时,告诉系统哪些属性要解析
/// @param coder coeer
- (instancetype)initWithCoder:(NSCoder *)coder {
    if (self = [super init]) {
        [coder decodeObjectForKey:@"name"]; 
        [coder decodeIntegerForKey:@"age"];
    }
    return self;
}



========================== 举例 ===========================
    // 备注:归档的对象必须执行NSCoding协议
    // 将person通过归档方式保存本地
    Person *person = [[Person alloc]init];
    person.name = @"one";
    person.age = 18;
    
    NSString *path = NSTemporaryDirectory();
    NSString *filePath = [path stringByAppendingPathComponent:@"person.data"];
    
    // 归档
    // iOS12之后开始弃用
    [NSKeyedArchiver archiveRootObject:person toFile:filePath];
    // iOS11开始沿用
    NSData *saveData = [NSKeyedArchiver archivedDataWithRootObject:person requiringSecureCoding:YES error:nil];
    [saveData writeToFile:filePath atomically:YES];
    
    // 解档
    // iOS12之后开始弃用
    Person *result = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
    // iOS11开始沿用
    NSData *resultData = [[NSData alloc]initWithContentsOfFile:filePath];
    Person *resultPerson = [NSKeyedUnarchiver unarchivedObjectOfClass:Person.class fromData:resultData error:nil];

@end

相关文章

  • iOS 基础复习

    1、状态栏 从iOS7开始,系统提供了2种管理状态栏的方式(1)通过UIViewController管理(每一个U...

  • iOS基础复习

    基础部分(题目来自掘金上面一位朋友写的文章,答案自己写的) 1、分类和扩展有什么区别?可以分别用来做什么?分类有哪...

  • iOS开发面试和底层学习视频整理合集

    基础复习 iOS面试基础知识 (一)[https://www.yuque.com/ioser/spb08a/gu8...

  • iOS 多线程基础复习

    进程 什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间都是独立的,每个进程均运行在其专用且受保护的...

  • ios基础知识复习

    程序篇 1、AppDelegate 周期方法 2、UIViewController 周期方法(按顺序) 3、属性关...

  • iOS 内存管理

    # 前言 反复地复习iOS基础知识和原理,打磨知识体系是非常重要的,本篇就是重新温习iOS的内存管理。 内存管理是...

  • iOS开发·网络请求方法总结复习(下)

    iOS开发·网络请求方法总结复习(下) iOS开发·网络请求方法总结复习(下)

  • iOS 动画基础总结篇

    iOS 动画基础总结篇 iOS 动画基础总结篇

  • 2019-04-05 离职、工作、学习计划

    1.复习mysql 基础知识2.复习python语法3.复习linux 基础命令

  • iOS逆向目录

    越狱最新进展 一.逆向基础 iOS逆向基础01-越狱iOS逆向基础02-编译&调试iOS逆向基础03-符号表iOS...

网友评论

      本文标题:iOS 基础复习

      本文链接:https://www.haomeiwen.com/subject/pfmkdhtx.html