iOS - 基础笔记

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

一、基础组件
二、组件操作
三、布局
四、基础模式
五、网络
六、线程
七、数据存储
八、多媒体
九、生命周期
十、 适配
十一、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 
  -(void) method:(Object *)pram;
@end

@property (nonatomic, weak) id 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];


- (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 *)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 - 基础笔记)