美文网首页iOS
iOS - 基础笔记

iOS - 基础笔记

作者: LouisXWB | 来源:发表于2020-02-11 22:02 被阅读0次

    总结一些平常需要注意的点:

    一、基础组件
    二、组件操作
    三、布局
    四、基础模式
    五、网络
    六、线程
    七、数据存储
    八、多媒体
    九、生命周期
    十、 适配
    十一、APPs
    十二、组件化
    十三、集成打包:

    一、基础组件:

    1、Frame:

    frame重新赋值后会自动调节位置。

    2、UILabel
    • sizeFit方法:当UILabel设定宽高后,调用sizeFit可以自动调节宽高。
    • 编辑用UITextField,设置内边距:
            UITextField.leftViewMode = UITextFieldViewModeAlways;
            UITextField.leftView = leftview;
    
    • 多行编辑用UITextView,边距设置用textContainerInset属性
    3、UITableView(UITableViewDelegate,UITableViewDataSource)
    • dataSource + delegate 实现数据和显示
    • UITableViewCell 不一定要用xib实现,继承 UITableViewCell 就可以实现
    • UITableViewCell的复用
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
        
    if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"];
    }
    

    dequeueReusableCellWithIdentifier 是根据cellId从复用队列获取。

    4、UIScrollView
    • 多页面的滑动不一定要用tabbar+ViewController ,可以使用UIScrollView来回切换页面。
      contentSize: 全页面的size
      frame: 屏幕内显示的size
      contentOffset: 页面坐标与屏幕坐标的差值,可以用来移动UIScrollView
    5、UIImageView

    contentMode 使用

    6、UIButton
    • 继承 UIControll

    • Target-Action模式可以实现点击, addTarget,不足是不能传值

    7、UIView

    普通view使用 UITapGestureRegconizer+addGestureRegconizer方法实现点击事件。

    注意:addGestureRegconizer可能无效,因为手势是从上往下传递的,需要把View的userInteractionEnabled设为YES。

    二、组件操作:

    1、坐标转换

    把局部坐标转换成全局坐标

    CGRect rect = [superView convertRect:subview.frame toview:nil];
    
    //rect是相对于someView的,以toView为坐标系重新计算rect的值
    CGRect newRect = [someView convertRect:rect toView:toView];
    

    三、布局:

    1、布局的实现
    • 代码
    • 视图拖拽(StoryBoard)
    2、代码
    • Frame
      主要是固定的相对布局,优点是简单的页面使用Frame实现的效率高,缺点是复杂的组件间约束无法实现,屏幕适配也相当繁琐。
    • AutoLayout
      支持约束布局,通过NSLayoutConstraint来实现,用VFL(Visual Format Lauguage)可以简化代码,第三方库Masonry可以让实现更加简单整洁。

    NSLayoutConstraint 的实现:

    [NSLayoutConstraint activateConstraints:@[
    
             [NSLayoutConstraint constraintWithItem:_avatorImageView
                                          attribute:NSLayoutAttributeCenterY
                                          relatedBy:NSLayoutRelationEqual
                                             toItem:self
                                          attribute:NSLayoutAttributeCenterY
                                         multiplier:1
                                           constant:0],
    
             [NSLayoutConstraint constraintWithItem:_avatorImageView
                                          attribute:NSLayoutAttributeLeft
                                          relatedBy:NSLayoutRelationEqual
                                             toItem:self
                                          attribute:NSLayoutAttributeLeft
                                         multiplier:1
                                           constant:15]
    ]];
    

    注意:为什么 translatesAutoresizingMaskIntoConstraints 使用约束布局时候,就要设置为 NO?
    translatesAutoresizingMaskIntoConstraints 的本意是将frame 布局 自动转化为 约束布局,转化的结果是为这个视图自动添加所有需要的约束,如果我们这时给视图添加自己创建的约束就一定会约束冲突。

    为了避免上面说的约束冲突,我们在代码创建 约束布局 的控件时 直接指定这个视图不能用frame 布局(即translatesAutoresizingMaskIntoConstraints=NO),可以放心的去使用约束了。
    Reference: translatesAutoresizingMaskIntoConstraints 详解

    VFL的实现:

    NSString *vflString = @"H:|-15-[_avatorImageView]-0-[_nickLabel]-(>=0)-
    [_commentImageView(==_avatorImageView)]-0-[_commentLabel]-15-
    [_likeImageView(==_avatorImageView)]-0-[_likeLabel]-15-
    [_shareImageView(==_avatorImageView)]-0-[_shareLabel]-15-|";
    
     [NSLayoutConstraint activateConstraints:[NSLayoutConstraint   
    constraintsWithVisualFormat:vflString 
    options:NSLayoutFormatAlignAllCenterY metrics:nil 
    views:NSDictionaryOfVariableBindings(_avatorImageView, _nickLabel, 
    _commentImageView, _commentLabel, _likeImageView, 
    _likeLabel, _shareImageView, _shareLabel)]];}
    
    @end
    
    

    Masonry的实现:

    [_hintL mas_makeConstraints:^(MASConstraintMaker *make) {
                make.centerX.mas_equalTo(self.appsIcon.mas_right);
                make.centerY.mas_equalTo(self.appsIcon.mas_top);
                make.width.and.height.mas_equalTo(17);
            }];
    

    四、基础模式:

    类与类之间的通信
    1、KVO(NSKeyValueObserving)

    可以监听任何object

    系统提供KVO的问题:

    • 移除观察者比较繁琐,容易发生Crash
    • key命名问题,同名导致问题
    • 实现繁琐,没能直接通过block实现

    尝试KVOController

    2、delegate @protocol
    @protocol xxxx_Delegate <NSObject>
      -(void) method:(Object *)pram;
    @end
    
    @property (nonatomic, weak) id<xxxx_Delegate> delegate;
    
    • 多尝试delegate(protocol)的使用
    • block的区别就是protocol可以把不同类型的方法分组收拢,并且可以要求强制实现,实现的方式也不同, delegate的实现可以拆分成宿主Object的方法。
    • delegate的调用不仅仅是判断delegate,还要判断方法的实现与否
    if(self.delegate && self.delegate responsToSelector(method:))
    

    五、网络:

    1、基本网络请求
    • NSURL
    [NSURL URLWithString:@"xxx"] ; //url = @"xxx"
    
    [NSURL fileURLWithPath:@"xxx"] ;//url = @"file://xxx" 
    
    • NSURLRequest
    • NSURLSession
    • NSURLSessionTask
      resume/cancel

    六、线程

    1、NSThread
    2、GCD Grand Central Dispatch
    • 线程池模式,⾃动分配/调度线程,管理线程的⽣命周期
    • 对开发者使⽤队列代替线程的创建 ( 加⼊到合适的线程 ——> 加⼊到合适的队列 )


      Grand Central Dispatch

    分为三大类:

    • 主线程对应主队列
    • ⾮主线程按照优先级分为4个队列(High / Default / Low / Background)
    • ⾃定义队列(DISPATCH_QUEUE_SERIAL、DISPATCH_QUEUE_CONCURRENT)


      线程三大类

    切换线程:


    切换线程

    例如:切换到主线程

    dispatch_sync(dispatch_get_main_queue(), ^{
                
    });
    
    3、NSOperationNSOperationQueue
    4、Runloop
    总结:
    iOS中的多线程基础

    七、数据存储:

    1、key-value (NSUserDefault)
    • 单例,存取轻量级的数据
    • ⼀般⽤于⽤户的偏好设置
    • 升级安装后还可以继续使⽤
    • ⽂件存储在在 /Library/Preferences 下
    2、文件

    NSPathUtilities 文件工具FrameWork
    [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) 找置顶沙盒文件夹路径
    NSFileManager iOS⽂件管理类

    NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        NSString *cachePath = [pathArray firstObject];
        
        NSFileManager *fileManager = [NSFileManager defaultManager];
        
        //创建文件夹
        NSString *dataPath = [cachePath stringByAppendingPathComponent:@"GTData"];
        NSError *creatError;
        [fileManager createDirectoryAtPath:dataPath withIntermediateDirectories:YES attributes:nil error:&creatError];
        
        //创建文件
        NSString *listDataPath = [dataPath stringByAppendingPathComponent:@"list"];
        
        [fileManager createFileAtPath:listDataPath contents:nil attributes:nil];
    
        //查询文件
     BOOL fileExist = [fileManager fileExistsAtPath:listDataPath];
        
        //删除
     if(fileExist){
        [fileManager removeItemAtPath:listDataPath error:nil];
    }
    

    NSFileHandle 更精细操作的NSFileManager特别是seekToFileOffset方法

       NSFileHandle *fileHandler = [NSFileHandle fileHandleForUpdatingAtPath:listDataPath];
    
       [fileHandler seekToEndOfFile];
       [fileHandler writeData:[@"def" dataUsingEncoding:NSUTF8StringEncoding]];
       [fileHandler synchronizeFile];
       [fileHandler closeFile];
    
    3、数据库
    4、序列化 NSCoder NSCoding

    NSCoder:抽象类, Object 和 ⼆进制数据间进⾏转换
    NSKeyedArchiver : NSCoder 的⼦类
    NSCoding: 对于 Object 的序列号 & 反序列化协议
    NSSecureCoding : 安全的NSCoding

    NSData *listData = [NSKeyedArchiver archivedDataWithRootObject:array requiringSecureCoding:YES error:nil];
    id unarchiveObj = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:[NSArray class],[GTListItem class], nil]  fromData:testListdata error:nil];
    
    <NSSecureCoding>
    
    - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{
        self = [super init];
        if (self) {
            self.category = [aDecoder decodeObjectForKey:@"xxx"];
        }
        return self;
    }
    
    - (void)encodeWithCoder:(NSCoder *)aCoder{
        [aCoder encodeObject:self.category forKey:@"xxx"];
    }
    
    + (BOOL)supportsSecureCoding{
        return YES;
    }
    

    八、多媒体

    1、图片

    SDWebImage

    2、视频

    基础使用:
    AVAsset -> AVPlayItem -> AVPlayer -> AVPlayerLayer

    NSURL *videoURL = [NSURL URLWithString:videoUrl];
    AVAsset *asset = [AVAsset assetWithURL:videoURL];
    AVPlayerItem *videoItem = [AVPlayerItem playerItemWithAsset:asset];
    AVPlayer *avPlayer = [AVPlayer playerWithPlayerItem:videoItem];
    AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:avPlayer];
    playerLayer.frame = rootView.bounds
    [rootView.layer addSublayer:playerLayer];
    

    系统提供的api主要是处理播放和ui:


    视频开发过程

    九、生命周期

    App启动过程
    1、main 函数
    • main 函数前
      动态链接 / ⼆进制⽂件加载 / runtime / 类的加载等等

    • main 函数
      职责是创建UIApplication 和 UIApplicationDelegate


      main函数的实现
    2、UIApplication

    主要职责是:

    • 处理 App ⽣命周期 / 系统内存警告
    • 处理UI / statusbar / 图标消息数等状态的变化/ ⽅向
    • 处理 openURL

    提供 Delegate / Notification 两种⽅式处理业务逻辑:AppDelegate

    控制App生命周期来调整业务逻辑:

    • Not running
    • Inactive:过渡的中间状态
    • Active:正在前台运⾏,系统分配更多资源
    • Background :分配较少资源
    • Suspended: 内存不⾜系统⾃动 kill
    3、UIApplicationDelegate
    AppDelegate生命周期回调
    4、闪屏的实现

    分为:Launch Screen +Splash Screen

    Launch Screen 启动屏 (系统级):
    • 是Main 函数之前 + didFinshLaunch 前
    • 系统启动 App 时⾃动展示
    • 在准备好App UI 数据后⾃动消失(didFinshLaunch执行完之后)
    • 给⽤户以响应,确定点击了正确的图标
    Splash Screen 闪屏(业务逻辑)
    • Launch Screen展示时间短,不能看清
    • 实现同样的图⽚,显示图标等信息
    • 实现⼴告 / 推⼴活动⻚⾯
    • 游戏中的 Loading ⻚⾯

    实现:

    • 直接在当前 Window 上 addSubview
      ⻚⾯结构保证在最上⾯,didFinshLaunch方法内初始化UI之后。
    • 创建新的 Window 成为 KeyWindow
      调整 window 的 level 、多 Window 的管理

    十、机型适配:

    分三种:尺寸、像素和特殊机型

    1、位置、⼤⼩、⽂字的适配(逻辑分辨率)

    主要是针对不同屏幕的尺寸来决定是否按⽐例扩⼤

    2、图⽚资源适配(物理分辨率)

    根据像素密度来对图片进行2x 3x(缩放因⼦) 以及资源管理

    资源管理有两种BundleImageAsset

    Bundle:
    • ⽅便管理和debug(以文件的绝对路劲)
    • 删除和使⽤脚本
    • 物理层⾯更⾼的灵活性
    • 代码上通过语法糖实现特殊逻辑
    ImageAsset:
    • 系统应⽤瘦身 App thinning
    • 不⽤写后缀,直接使⽤名字读取
    • ⽅便管理,直观展示
    • 改变颜⾊
    3、iphoneX 适配

    safeArea / 交互,包括statusbar、Home Indicator

    Status Bar:
    • 竖屏 20 -> 44
    • 横屏 20
    Home Indicator :
    • 竖屏 34
    • 横屏 21
    Frame 布局 —— safeAreaInsets
    • UIEdgeInsets
    • 竖屏 { 44, 0, 34, 0 }
    • 横屏 { 0, 44, 21, 44 }
    4、 UIScreen & UIDevice

    UIScreen:获取设备的逻辑尺⼨

    • 基于硬件显示的相关属性
    • [UIScreen mainScreen]
    • 主要提供 size / 亮度 / 坐标系 等
    适配⽅案选择

    位置⼤⼩⽂字适配:

    • 苹果官⽅ Human Interface Guidelines
    • 更⼤设备显示更多内容
    • 等⽐放⼤ 以 iPhone6 作为基准设计尺⼨
    • iPhoneX 系列特殊的 UI 和交互

    资源适配:

    • 使⽤ @2x @3x 图⽚ / ⽹络数据处理
    • pdf ⽮量图
    • 使⽤合适的管理图⽚⽅式(Bundle / Asset)

    UIDevice:获取设备的信息

    • 操作系统 / 设备Model
    • [UIDevice currentDevice]
    • 设备⽅向 / 电量等

    十一、APPs:

    分为URL Scheme 和 Universal Link

    URL Scheme :

    1、使App能被其他App唤起
    • info->URL Types 添加
    • 在 UIApplication 中处理参数和业务逻辑
    - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
        return YES;
    }
    
    2、通过 Scheme 唤起其它 App
    • 通过 Scheme 判断 App 是否安装
    [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@""]];
    

    注意:这个方法生效的前提是必须在info -> LSApplicationQueriesSchemes 的⽩名单数组中添加,canOpenURL方法才会生效,否则返回NO,且LSApplicationQueriesSchemes的注册数量有限制。

    • 使⽤ UIApplication 唤起 App
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@""] options:nil completionHandler:^(BOOL success) {
            //处理业务逻辑
        }];
    

    Universal Link:

    • 使⽤ HTTP / HTTPS 协议启动客户端
    • Scheme重复 / Web 和 Native 统⼀
    • 需要配合Web端进⾏注册
    • 在Safari / 微信 / 其它 App 中使⽤Universal Link

    十二、组件化

    组件化方案对比

    十三、集成打包:

    cocoapods

    cocoapods是由Ruby语言编写的多项目集成工具,原理是把集成好的项目代码传到cocoapods,然后在要使用的项目里增加podfile文件,写好集成的第三方项目名、版本号等,然后pod install,它会自动生成一个pod项目,并把pod.xcodeproj和原来项目的projectName.xcodeproj合并为一个projectName.xcworkspace,这样项目就可以使用第三方的代码了。

    注意:集成多项目后打开项目的入口是projectName.xcworkspace,而不是projectName.xcodeproj

    366

    相关文章

      网友评论

        本文标题:iOS - 基础笔记

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