iOS从入门到精通

iOS从入门到精通

一、iPhone机型适配

设备型号 屏幕尺寸
iPhone 4/4S 320 * 480
iPhone 5/5C/5S 320 * 568
iPhone 6/6S/7 375 * 667
iPhone 6Plus/6SPlus/7Plus 414 * 736
机型适配

二、mian()函数的作用

(1)创建了一个自动释放池。
(2)调用UIApplicationMain()函数。
(3)释放自动释放池。

main.m文件

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

//整个APP程序的主函数,入口函数
int main(int argc, char * argv[]) {
    //自动内存释放池
    @autoreleasepool {
        //UIKit框架结构的启动函数
        //参数1:  argc    启动时带有参数的个数
        //参数2:  argv    参数列表
        //参数3:  nil     要求传入一个主框架类类名,如果参数为nil系统会用默认的框架类作为主框架类名
        //参数4:  主框架的代理类对象名字
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

三、iOS应用的生命周期

iOS应用程序拥有的5种状态:
(1)Not running 应用还没启动或正在运行但是中途被系统停止
(2)Inactive 应用正在前台运行(不接收事件)
(3)Active 应用正在前台运行(接收事件)
(4)Background 应用处于后台运行(还在执行代码)
(5)Suspended 应用处于后台运行(停止执行代码)

iOS程序的生命周期
#pragma         //////////生命周期有关函数//////////
//应用将要进入非活动调用   (不接受消息或事件)
- (void)applicationWillResignActive:(UIApplication *)application;
//应用进入活动调用        (接收消息或事件)
- (void)applicationDidBecomeActive:(UIApplication *)application;
//应用进入后台调用        (设置后台继续运行)
- (void)applicationDidEnterBackground:(UIApplication *)application;
//应用将要进入前台调用    
- (void)applicationWillEnterForeground:(UIApplication *)application;
//应用将要退出调用        (保存数据,退出前清理)
- (void)applicationWillTerminate:(UIApplication *)application;
//应用被终止前调用        (内存清理,方式应用被终止)
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application;
//应用载入后调用          
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
//应用打开URL时调用
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url;

四、UIViewController生命周期

(1)第一次访问UIViewController的view时,view为nil,然后就会调用loadView方法创建view,通过懒加载的方式进行加载。
(2)重写loadView方法,可以根据重写loadView方法创建View。
(3)View创建完毕后会调用viewDidLoad方法进行界面元素的初始化。
(4)StoryBoard加载的是控制器及控制器View。
(5)XIB加载的仅仅是控制器View。

ViewController生命周期
#pragma         //////////生命周期有关函数//////////
- (void)loadView;                           //加载视图资源并初始化视图(负责创建UIViewController的View)
- (void)viewDidLoad;                         //视图加载完毕(只执行一次,界面初始化操作,往View上添加子视图)
- (void)viewWillAppear:(BOOL)animated;     //视图将要显示
- (void)viewDidAppear:(BOOL)animated;       //视图显示
- (void)viewWillDisappear:(BOOL)animated;   //视图将要消失
- (void)viewDidDisappear:(BOOL)animated;     //视图消失

五、Cocoa中的类

#pragma -核心类
NSObject                //根类           (所有类的根类,定义了所有类共有的方法,如alloc,init)
UIApplication          //应用程序类    (应用运行期间的控制和协作工作)  
[UIApplication sharedApplication];     //获取应用程序实例
UIWindow                //窗口类         (管理和显示视图的容器)
UIView                //视图类       (管理矩形区域内的所有屏幕显示)
#pragma -响应者链:
UIResponder          //响应者类     (接收屏幕上的触摸事件)
    - (void)touchesBegan: withEvent:;       //触摸开始
    - (void)touchesMoved: withEvent:;       //触摸移动
    - (void)touchesEnded: withEvent:;       //触摸结束
    - (void)touchesCancelled: withEvent:;   //触摸取消
UIControl               //控件类       (根据触摸事件触发操作)
UIViewController         //视图控制器类   (管理视图的内容)
#pragma -数据类型类
NSString/NSMutableString                //字符串
NSArray/NSMutableArray                //数组
NSDictionary/NSMutableDictionary        //字典
NSNumber/NSDecimalNumber                //数字
NSDate                                //日期
NSURL                                  //url
NSData                                //二进制
#pragma -UI界面类
UILabel                              //标签
UIButton                                //按钮
UISlider                                //滑块
UIStepper                              //步进
UIImage/UIImageView                  //图片
UISwitch                                //开关
UISegmentedControl                    //分段
UIWebView                              //网页
UIScrollView                            //滚动
UIPageControl                       //翻页
UIProgressView                        //进度
UIActivityIndicatorView              //活动指示器
UITextField/UITextView                //文本框
UIToolbar                              //工具栏
UIDatePicker/UIPickerView              //选择器
UIColor                              //颜色
UITableView                          //列表
UICollectionView                        //网格
UIAlertController                       //选择控制器
UIPopoverController                   //弹框控制器
UINavigationController/UINavigationBar   //导航控制器
UITabBarController/UITabBar             //选项控制器
UISearchController/UISearchBar          //搜索控制器
UIImagePickerController                 //图像选择控制器

六、响应者链

响应者链

先向下找,再向上找的一个过程。
所有的iOS中关于的界面的类都直接或间接地继承与UIResponder。

(1)当用户点击某一个视图或者按钮的时候会首先响应application中UIWindow一层一层的向下查找,直到找到用户指定的view为止。(向下查找)

#pragma -查找用户点击的View
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;   
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;   

(2)查看指定的View是否响应了点击事件,如果没有找它的nextResponder,再继续一层一层的向上查找,直到找到AppDelegate,再没有响应,则此点击事件被系统丢弃。(向上查找)

点击查找View
#pragma -查找用户点击的View响应事件
- (nullable UIResponder*)nextResponder;

七、空指针和野指针的区别

空指针: 没有存储任何内存地址的指针就称为空指针(NULL指针)。空指针就是被赋值为0的指针,在没有被具体初始化之前,其值为0。

野指针: 指向一个已删除的对象或未申请访问受限内存区域的指针。"野指针"不是NULL指针,是指向"垃圾"内存(不可用内存)的指针。野指针是非常危险的。

八、NSRunLoop

作用:

  • 有事情的时候当前NSRunLoop的线程工作,没有事情做让当前NSRunLoop的线程休眠。
  • 一直在循环检测,从线程开始到结束,检测同步事件。
  • 系统已经在每条线程中加入RunLoop,主线程默认启动,子线程默认关闭,保证主线程在运行起来后就处于一种等待状态,如果有接收到事件就会执行任务,否则就会处于休眠状态。
  • 每条线程都有唯一的一个RunLoop对象与之对应
  • 保持程序的持续运行
  • 处理APP中的各种事件(比如触摸,定时器,Selector)
  • 节省CPU资源,提高程序性能,该做事时做事,该休息时休息
#pragma 系统默认注册运行模式RunLoop Mode(5个)
NSDefaultRunLoopMode:           //默认的Mode,通常主线程的RunLoop是在这个Mode下运行。
UITrackingRunLoopMode:          //界面跟踪Mode,当用户与界面交互的时候会在此Mode下运行。
NSRunLoopCommonModes:           //这个不是一种真正的Mode,是一个占位用的Mode。
UIInitializationRunLoopMode:    //程序启动时的Mode,启动完成后就不在此Mode下。
GSEventReceiveRunLoopMode:      //接受系统事件的内部Mode,一般我们用不到。
#pragma RunLoop函数
[NSRunLoop mainRunLoop];        //获取主线程RunLoop对象
[NSRunLoop currentRunLoop];     //获取当前线程RunLoop对象
#pragma RunLoop应用
1)NSTimer
2)ImageView显示:控制方法在特定的模式下可用
3)PerformSelector
4)常驻线程:在子线程中开启一个runloop
5)自动释放池
    第一次创建:进入runloop的时候
    最后一次释放:runloop退出的时候
    其它创建和释放:当runloop即将休眠的时候会把之前的自动释放池释放,然后重新创建一个新的释放池

(1)NSTimer应用

NSTimer受RunLoop Mode影响

//一、NSTimer默认添加到主线程中默认模式下工作----------------(NSDefaultRunLoopMode)
    [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(run) userInfo:nil repeats:YES];
    
//二、NSTimer只有在默认模式下工作-----------------------(NSDefaultRunLoopMode)
    NSTimer *timer1 = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(run) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer1 forMode:NSDefaultRunLoopMode];
    
//三、NSTimer只有在拖拽UI界面模式下工作------------------(UITrackingRunLoopMode)
    NSTimer *timer2 = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(run) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer2 forMode:UITrackingRunLoopMode];
    
//四、NSTimer只有在NSRunLoopCommonModes模式下工作-------(标记NSDefaultRunLoopMode/UITrackingRunLoopMode两种模式)
    NSTimer *timer3 = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(run) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer3 forMode:UITrackingRunLoopMode];

RunLoop与GCD

CCD不受RunLoop Mode影响

(2)ImageView显示应用

//只在NSDefaultRunLoopMode下执行(刷新图片,拖拽UI不会刷新图片)
[_myImageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"1.jpg"] afterDelay:2.0 inModes:@[NSDefaultRunLoopMode]];

(3)常驻线程应用

#import "ViewController.h"
/*
思路:为了保证线程不死,我们考虑在子线程中加入RunLoop,
    但是由于RunLoop中没有没有源,就会自动退出RunLoop,
    所以我们要为子线程添加一个RunLoop,
    并且为这个RunLoop添加源(保证RunLoop不退出)
*/
@interface ViewController ()
/** 线程对象 */
@property (nonatomic, strong)NSThread *thread;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 创建子线程
    self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
    //启动子线程
    [self.thread start];
}

- (void)run {
    NSLog(@"run--%@", [NSThread currentThread]); // 子线程
    // 给子线程添加一个RunLoop,并且加入源
    [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
    // 启动RunLoop
    [[NSRunLoop currentRunLoop] run];
    NSLog(@"------------"); // RunLoop启动,这句没有执行的机会
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    // 在子线程中调用test方法,如果子线程还在就能够调用成功
    [self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:YES modes:@[NSDefaultRunLoopMode]];
}

- (void)test {
    NSLog(@"test--%@", [NSThread currentThread]); // 子线程
}
@end
RunLoop流程
#pragma RunLoop监听活动枚举值
/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry = (1UL << 0),           //状态值:1,表示进入RunLoop
    kCFRunLoopBeforeTimers = (1UL << 1),    //状态值:2,表示即将处理NSTimer
    kCFRunLoopBeforeSources = (1UL << 2),   //状态值:4,表示即将处理Sources
    kCFRunLoopBeforeWaiting = (1UL << 5),   //状态值:32,表示即将休眠
    kCFRunLoopAfterWaiting = (1UL << 6),    //状态值:64,表示从休眠中唤醒
    kCFRunLoopExit = (1UL << 7),            //状态值:128,表示退出RunLoop
    kCFRunLoopAllActivities = 0x0FFFFFFFU   //表示监听上面所有的状态
};

为主线程RunLoop添加观察者

#pragma 1.创建一个监听对象
    /**
     *  参数1:    告诉系统如何给Observer对象分配存储空间
     *  参数2:    需要监听的类型
     *  参数3:    是否需要重复监听
     *  参数4:    优先级
     *  参数5:    监听到对应的状态之后的回调
     */
    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        
        switch (activity) {
            case kCFRunLoopEntry:
                NSLog(@"进入RunLoop");
                break;
            case kCFRunLoopBeforeTimers:
                NSLog(@"即将处理Timer");
                break;
            case kCFRunLoopBeforeSources:
                NSLog(@"即将处理Source");
                break;

            case kCFRunLoopBeforeWaiting:
                NSLog(@"即将休眠");
                break;
            case kCFRunLoopAfterWaiting:
                NSLog(@"从休眠中唤醒");
                break;
            case kCFRunLoopExit:
                NSLog(@"退出RunLoop");
                break;
            case kCFRunLoopAllActivities:
                NSLog(@"监听上面所有状态");
                break;
            default:
                break;
        }
        
    });
#pragma 2.给主线程的RunLoop添加监听
    /**
     *  参数1:    需要监听的RunLoop对象
     *  参数2:    给指定的RunLoop对象添加的监听对象
     *  参数3:    在哪种模式下监听
     */
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopCommonModes);
#pragma 3.释放Observer
    CFRelease(observer);
    //输出:       从休眠中唤醒
    //输出:       即将处理Timer
    //输出:       即将处理Source
    //输出:       即将处理Timer
    //输出:       即将处理Source
    //输出:       即将休眠
    //输出:       从休眠中唤醒
    //输出:       即将处理Timer
    //输出:       即将处理Source
    //输出:       即将休眠
    //.....

九、沙盒机制

iOS8.3以后苹果禁止了对沙盒路径的访问
每个应用都只能访问当前沙盒目录下面的文件

  • app 应用文件
    • Documents 保存应用程序的数据文件。
  • Library 保存默认设置或其它状态信息。
    • Caches 保存缓存文件。
    • Preferences 保存偏好设置文件,Plist文件。
  • tmp 保存各种临时文件。
NSHomeDirectory()                                     //获取沙盒目录
[[NSBundle mainBundle] bundlePath];                 //获取沙盒目录.app文件
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *DocumentsPath = [paths objectAtIndex:0];  //获取沙河目录Documents文件夹
NSTemporaryDirectory()                              //获取沙河目录tmp文件夹

十、iOS数据存储

(1)Plist文件
(2)SQLite数据库
(3)CoreData数据库

SQLite数据库增删改查

支持类型:integer real, text, blob
使用单引号来环绕文本值。如果是数值,请不要使用引号。

#pragma 创建表
create table 表名 (字段1, 字段2, 字段3);
create table if not exists (字段1, 字段2, 字段3);
#pragma 插入
insert into 表名 (字段1, 字段2, 字段3) values (值1, 值2, 值3);
#pragma 更新
update 表名 set 字段1 = 值1, 字段2 = 值2, 字段3 = 值3;
update 表名 set 字段1 = 值2 where 字段1 = 值1;
#pragma 删除
delete from 表名
#pragma 查询
select * from 表名;                                      //所有查询
select * from 表名 where 字段 = 值;                      //具体查询
select * from 表名 where 字段 like 值;                    //模糊查询
select * from 表名 order by 字段1 ASC, 字段2 DESC;         //排序查询(ASC升序, DESC降序)
#pragma 统计
select count(*) from 表名;
select count(*) from 表名 where 字段 like 值;
select max(字段) from 表名;
select min(字段) from 表名;
select avg(字段) from 表名;
select sum(字段) from 表名;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容

  • 1,NSObject中description属性的意义,它可以重写吗?答案:每当 NSLog(@"")函数中出现 ...
    eightzg阅读 4,144评论 2 19
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,141评论 30 470
  • 把网上的一些结合自己面试时遇到的面试题总结了一下,以后有新的还会再加进来。 1. OC 的理解与特性 OC 作为一...
    AlaricMurray阅读 2,564评论 0 20
  • 1、截取字符串”20 | http://www.baidu.com”中,”|”字符前面和后面的数据,分别输出它们 ...
    强子ly阅读 2,949评论 8 46
  • 一、深复制和浅复制的区别? 1、浅复制:只是复制了指向对象的指针,即两个指针指向同一块内存单元!而不复制指向对象的...
    iOS_Alex阅读 1,376评论 1 27