• FMDB数据库的简单使用、VIewController的生命周期、关于导航栏的一些知识


    学习内容

    欢迎关注我的iOS学习总结——每天学一点iOS:https://github.com/practiceqian/one-day-one-iOS-summary

    FMDB数据库的使用

    • 什么是FMDB

      • FMDB使用OC语言封装了sqlite的C语言API,可以在iOS平台使用
    • FMDB的优点

      • 使用起来比较方便,省去了麻烦,冗余的C代码

      • 相比coreData框架更加轻量级和灵活

      • 提供了多线程安全的数据库操作方法,防止数据读取的混乱

    1. 创建数据库

      • 根据数据库名创建数据库(已存在则打开)

        //懒加载数据库
        - (FMDatabase *)fmDB{
        	if (!_fmDB) {
            //获取Documents文件夹路径
            NSString* dbPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, 		NSUserDomainMask, YES) lastObject];
            //在Documents文件夹路径后追加数据库名"picture.sqlite"(Documents/picture.sqlite)
            NSString* path = [dbPath stringByAppendingPathComponent:@"picture.sqlite"];
            //根据指定的路径创建数据库
            _fmDB = [FMDatabase databaseWithPath:path];
          }
            return _fmDB;
        }
        
      • path为空字符则在临时目录中创建数据库,当fmdb的连接关闭时,数据库也会被删除

      • path为nil时会在内存中创建数据库,fmdb连接关闭时,数据库被删除

    2. 数据库操作

      • 在FMDB中除了查询以外的操作都被称作更新,使用executeUpdate:方法更新

      • //创建数据库
        NSString* sql = @"insert into t_schedule"
        NSString* createSql = @"create table if not exists t_schedule
          											(id integer primary key autoincrement,
          											name text not null,
          											teacher text not null,
          											weekId integer not null,
          											time text not null,
          											weekday integer not null)"
        
      • //插入数据
        NSStrng* sql = @"insert into t_schedule (name,teacher,weekId,time,weekday) values (?,?,?,?,?)";
        //第一个参数为sql语句,后面跟着参入的数据
        BooL res = [db executeUpdate:sql,params];
        
      • //查询数据
        NSString* sql = @"select * from t_schedule";
        FMResultSet* res = [db executeQuery:sql];
        while([res next]){
          //可以根据列名或者列的下标来取数据
          NSString* name = [res stringForColumn:@"name"]/[res stringForColumnIndex:0];
          ...
        }
        
      • //关闭数据库
        [db close]
        
      • //如果sql中含有空值,那么应该使用[NSNull null]来代替nil
        NSStrng* sql = @"insert into t_schedule (name,teacher,weekId,time,weekday) values (?,?,?,?,?)";
        BooL res = [db executeUpdate:sql,@"Computer",@"Jack",@(1),@"08:00~09:40",[NSNull null]];
        
    3. 使用FMDataBaseQueue确保线程安全

      • 尽量不要创建一个FMDatabase对象并在多个线程中使用该对象,否则的话容易读到脏数据或者造成写入异常

      • 可以实例化一个FMDatabaseQueue对象,并在不同的线程中使用该对象,FMDatabaseQueue会在多个线程中同步和协调

      • NSString* path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        NSString* dbPath = [path stringByAppendingPathComponent:@"schedule_queue.sqlite"];
        FMDatabaseQueue* queue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
        [queue inDatabase:^(FMDatabase *db) {
          [db executeUpdate:@"create table if not exists t_schedule (id integer primary key autoincrement, name text not null, time text not null, teacher text not null)"];
          [db executeUpdate:@"insert into t_schedule (name,time,teacher) values (?,?,?)",@"Hadoop大数据分析",@"上午九点",@"孙老师"];
        }];
        
    4. 事务操作

      • 事务操作是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么不执行,是一个不可分割的工作单位,事务由事务开始和事务结束之间的全部数据库操作组成

      • //使用FMDatabaseQueue开启事务操作
        [queue inTransaction:^(FMDatabase * _Nonnull db, BOOL * _Nonnull rollback) {
                NSString *sql = @"";
                NSString *sql2 = @"";
                
                BOOL res1 = [db executeUpdate:sql];
                BOOL res2 = [db executeUpdate:sql2];
                if (res1&&res2) {
                    PSLog(@"success");
                }else{
                    PSLog(@"fail,start rollback");
                    [db rollback];
                }
            }];
        

    UIViewController的生命周期(ARC环境下、PUSH)

    1. 单个ViewController的生命周期
      • initWithCoder:(NSCoder*)coder(如果使用StoryBoard或者xib)
      • loadView:加载或创建一个view,赋值给self(视图控制器自身)
      • viewDidLoad:view加载完毕
      • viewWillAppear:控制器的view将要显示
      • viewWillLayoutSubViews:控制器的view将要布局子控件
      • viewDidLayoutSubViews:控制器的view布局子控件完成
      • viewDidAppear:控制器的view完全显示
      • viewWillDisappear:控制器的view即将消失
      • viewDidDisappear:控制器的view完全消失
    2. push的情况下(假设这里有ViewController1和ViewController2)
      • initWithCoder:(ViewController2)
      • loadView(ViewController2)
      • viewDidLoad(ViewController2)
      • viewWillDisAppear(ViewController1)
      • viewWillAppear(ViewController2)
      • viewWillLayoutSubViews(ViewController2)
      • viewDidLayoutSubViews(ViewController2)
      • viewWllLayoutSubViews(ViewController1)
      • viewDidLayoutSubViews(ViewController1)
      • viewDidDisAppear(ViewController1)
      • viewDidAppear(ViewController2)
    3. pop的情况下(从ViewController2—>ViewController1)
      • viewWillDisappear(ViewController2)
      • viewWIllAppear(ViewController1)
      • viewDidDisappear(ViewController2)
      • viewDidAppear(ViewController1)

    导航栏样式的修改(UINavigationController)

    1. 在NavigationController的Stack存储结构下,每当Stack中的任意ViewController修改了导航栏的样式,那么也会影响到其他视图控制器导航栏的样式

      • A控制器导航栏为绿色,push->B控制器,修改B控制器导航栏颜色为紫色,pop->A,那么A控制器的导航栏也会为紫色
      • 在导航栏的Stack中,每一个ViewController对导航栏的操作都会永久的改变其样式,在开发中需要坚持“谁修改谁复原的原则”,否则会造成导航栏样式的混乱(在一些极端的情况下还会引起Stack混乱),造成crash
    2. 导航栏样式转换的时机(一般都是在viewwillappear和viewwilldisappear中进行设置)

      • - (void)viewWillAppear:(BOOL)animated{
            [super viewWillAppear:animated];
            //MARK:change the navigationbar style
        }
        - (void)viewWillDisappear:(BOOL)animated{
            [super viewWillDisappear:animated];
            //MARK:restore the navigationbar style
        }
        
    3. 导航栏的样式变化(主要有两种)

      • 导航栏的显示与否

        • [self.navigationController setNavigationBarHidden:YES animated:YES]
          
        • 尽量使用带有animated参数的API,如果不带有animated可能会造成导航栏转场过程中的闪现,背景错乱等问题

      • 导航栏的颜色改变

        • 当translucent属性(透明)为yes时,直接设置backgroundColor
        • 当translucent属性为no时,需要设置setBackgroundImage:[UIImage new] forBarMetrics:方法
    4. Transparent、translucent、opaque、opacity区别

      • Transparent 完全透明

      • translucent 半透明

      • Opaque 不透明

      • 这三个词都是一种状态不需要量化,所以与这三个词相关的属性一般都是布尔类型

      • opacity和Alpha一般都是用来形容透明度,在前端中,opacity用来给整个元素设置透明度,而Alpha是给元素的某个属性设置透明度(backgroundColor、bordercolor等)

        • view中的alpha属性和view.layer.opacity属性是相等作用的
      • 设置全透明导航栏的正确方法

      • [self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
        self.navigationController.navigationBar.shadowImage = [UIImage new];
        
    5. 设置导航栏的图标

      • //设置返回标志图
        self.navigationController.navigationBar.backIndicatorImage = [UIImage imageNamed:@"back"];
        //设置返回标志过渡遮罩图
        self.navigationController.navigationBar.backIndicatorTransitionMaskImage = [UIImage imageNamed:@"back"];
        
  • 相关阅读:
    JAVA反射机制--静态加载与动态加载
    MyEclipse导入Hibernate出现Path must include project and resource;/project name
    服务器和java程序的桥梁--jdbc/hibernate
    AndroidStudio快捷键大全
    AndroidStudio怎么实现微信分享功能
    《一面》
    java泛型
    java设计模式-Observer(2)
    java设计模式-Observe
    HashSet的自定义实现
  • 原文地址:https://www.cnblogs.com/chenprice/p/12874372.html
Copyright © 2020-2023  润新知