iOS从入门到精通

geyu7363 6年前
   <h2>一、iPhone机型适配</h2>    <table>     <thead>      <tr>       <th>设备型号</th>       <th>屏幕尺寸</th>      </tr>     </thead>     <tbody>      <tr>       <td>iPhone 4/4S</td>       <td>320 * 480</td>      </tr>      <tr>       <td>iPhone 5/5C/5S</td>       <td>320 * 568</td>      </tr>      <tr>       <td>iPhone 6/6S/7</td>       <td>375 * 667</td>      </tr>      <tr>       <td>iPhone 6Plus/6SPlus/7Plus</td>       <td>414 * 736</td>      </tr>     </tbody>    </table>    <p style="text-align:center"><img src="https://simg.open-open.com/show/d90020e5a8605f5f251b6c327830b257.jpg"></p>    <p>机型适配</p>    <h2>二、mian()函数的作用</h2>    <p>(1)创建了一个自动释放池。</p>    <p>(2)调用UIApplicationMain()函数。</p>    <p>(3)释放自动释放池。</p>    <p>main.m文件</p>    <pre>  <code class="language-objectivec">#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]));      }  }</code></pre>    <h2>三、iOS应用的生命周期</h2>    <p>iOS应用程序拥有的5种状态:</p>    <p>(1)Not running 应用还没启动或正在运行但是中途被系统停止</p>    <p>(2)Inactive 应用正在前台运行(不接收事件)</p>    <p>(3)Active 应用正在前台运行(接收事件)</p>    <p>(4)Background 应用处于后台运行(还在执行代码)</p>    <p>(5)Suspended 应用处于后台运行(停止执行代码)</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/e4017ce8969344620afab414f8b5cd64.png"></p>    <p>iOS程序的生命周期</p>    <pre>  <code class="language-objectivec">#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;</code></pre>    <h2>四、UIViewController生命周期</h2>    <p>(1)第一次访问UIViewController的view时,view为nil,然后就会调用loadView方法创建view,通过懒加载的方式进行加载。</p>    <p>(2)重写loadView方法,可以根据重写loadView方法创建View。</p>    <p>(3)View创建完毕后会调用viewDidLoad方法进行界面元素的初始化。</p>    <p>(4)StoryBoard加载的是控制器及控制器View。</p>    <p>(5)XIB加载的仅仅是控制器View。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/f6f6ea41fe57b924dd082293e954698e.jpg"></p>    <p>ViewController生命周期</p>    <pre>  <code class="language-objectivec">#pragma         //////////生命周期有关函数//////////  - (void)loadView;                            //加载视图资源并初始化视图(负责创建UIViewController的View)  - (void)viewDidLoad;                         //视图加载完毕(只执行一次,界面初始化操作,往View上添加子视图)  - (void)viewWillAppear:(BOOL)animated;       //视图将要显示  - (void)viewDidAppear:(BOOL)animated;        //视图显示  - (void)viewWillDisappear:(BOOL)animated;    //视图将要消失  - (void)viewDidDisappear:(BOOL)animated;     //视图消失</code></pre>    <h2>五、Cocoa中的类</h2>    <pre>  <code class="language-objectivec">#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         //视图控制器类   (管理视图的内容)</code></pre>    <pre>  <code class="language-objectivec">#pragma    -数据类型类  NSString/NSMutableString                //字符串  NSArray/NSMutableArray                  //数组  NSDictionary/NSMutableDictionary        //字典  NSNumber/NSDecimalNumber                //数字  NSDate                                  //日期  NSURL                                   //url  NSData                                  //二进制</code></pre>    <pre>  <code class="language-objectivec">#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                    //图像选择控制器</code></pre>    <h2>六、响应者链</h2>    <p style="text-align:center"><img src="https://simg.open-open.com/show/8da79d1d023b793654b8628678dd20a0.jpg"></p>    <p>响应者链</p>    <p>先向下找,再向上找的一个过程。</p>    <p>所有的iOS中关于的界面的类都直接或间接地继承与UIResponder。</p>    <p>(1)当用户点击某一个视图或者按钮的时候会首先响应application中UIWindow一层一层的向下查找,直到找到用户指定的view为止。(向下查找)</p>    <pre>  <code class="language-objectivec">#pragma    -查找用户点击的View  - (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;     - (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;</code></pre>    <p>(2)查看指定的View是否响应了点击事件,如果没有找它的nextResponder,再继续一层一层的向上查找,直到找到AppDelegate,再没有响应,则此点击事件被系统丢弃。(向上查找)</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/7e4fcf266e488870259793433f3ffcdf.jpg"></p>    <p>点击查找View</p>    <pre>  <code class="language-objectivec">#pragma    -查找用户点击的View响应事件  - (nullable UIResponder*)nextResponder;</code></pre>    <h2>七、空指针和野指针的区别</h2>    <p>空指针: 没有存储任何内存地址的指针就称为空指针(NULL指针)。空指针就是被赋值为0的指针,在没有被具体初始化之前,其值为0。</p>    <p>野指针: 指向一个已删除的对象或未申请访问受限内存区域的指针。"野指针"不是NULL指针,是指向"垃圾"内存(不可用内存)的指针。野指针是非常危险的。</p>    <h2>八、NSRunLoop</h2>    <p>作用:</p>    <ul>     <li>有事情的时候当前NSRunLoop的线程工作,没有事情做让当前NSRunLoop的线程休眠。</li>     <li>一直在循环检测,从线程开始到结束,检测同步事件。</li>     <li>系统已经在每条线程中加入RunLoop,主线程默认启动,子线程默认关闭,保证主线程在运行起来后就处于一种等待状态,如果有接收到事件就会执行任务,否则就会处于休眠状态。</li>     <li>每条线程都有唯一的一个RunLoop对象与之对应</li>     <li>保持程序的持续运行</li>     <li>处理APP中的各种事件(比如触摸,定时器,Selector)</li>     <li>节省CPU资源,提高程序性能,该做事时做事,该休息时休息</li>    </ul>    <pre>  <code class="language-objectivec">#pragma 系统默认注册运行模式RunLoop Mode(5个)  NSDefaultRunLoopMode:             //默认的Mode,通常主线程的RunLoop是在这个Mode下运行。  UITrackingRunLoopMode:             //界面跟踪Mode,当用户与界面交互的时候会在此Mode下运行。  NSRunLoopCommonModes:             //这个不是一种真正的Mode,是一个占位用的Mode。  UIInitializationRunLoopMode:     //程序启动时的Mode,启动完成后就不在此Mode下。  GSEventReceiveRunLoopMode:         //接受系统事件的内部Mode,一般我们用不到。</code></pre>    <pre>  <code class="language-objectivec">#pragma RunLoop函数  [NSRunLoop mainRunLoop];        //获取主线程RunLoop对象  [NSRunLoop currentRunLoop];        //获取当前线程RunLoop对象</code></pre>    <pre>  <code class="language-objectivec">#pragma RunLoop应用  1)NSTimer  2)ImageView显示:控制方法在特定的模式下可用  3)PerformSelector  4)常驻线程:在子线程中开启一个runloop  5)自动释放池      第一次创建:进入runloop的时候      最后一次释放:runloop退出的时候      其它创建和释放:当runloop即将休眠的时候会把之前的自动释放池释放,然后重新创建一个新的释放池</code></pre>    <p>(1)NSTimer应用</p>    <p>NSTimer受RunLoop Mode影响</p>    <pre>  <code class="language-objectivec">//一、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];</code></pre>    <p>RunLoop与GCD</p>    <p>CCD不受RunLoop Mode影响</p>    <p>(2)ImageView显示应用</p>    <pre>  <code class="language-objectivec">//只在NSDefaultRunLoopMode下执行(刷新图片,拖拽UI不会刷新图片)  [_myImageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"1.jpg"] afterDelay:2.0 inModes:@[NSDefaultRunLoopMode]];</code></pre>    <p>(3)常驻线程应用</p>    <pre>  <code class="language-objectivec">#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</code></pre>    <p style="text-align:center"><img src="https://simg.open-open.com/show/389f024c6b2801350c3dbfeb4741d025.png"></p>    <p>RunLoop流程</p>    <pre>  <code class="language-objectivec">#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    //表示监听上面所有的状态  };</code></pre>    <p>为主线程RunLoop添加观察者</p>    <pre>  <code class="language-objectivec">#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      //输出:       即将休眠      //.....</code></pre>    <h2>九、沙盒机制</h2>    <p>iOS8.3以后苹果禁止了对沙盒路径的访问</p>    <p>每个应用都只能访问当前沙盒目录下面的文件</p>    <ul>     <li>app 应用文件      <ul>       <li>Documents 保存应用程序的数据文件。</li>      </ul> </li>     <li>Library 保存默认设置或其它状态信息。      <ul>       <li>Caches 保存缓存文件。</li>       <li>Preferences 保存偏好设置文件,Plist文件。</li>      </ul> </li>     <li>tmp 保存各种临时文件。</li>    </ul>    <pre>  <code class="language-objectivec">NSHomeDirectory()                                      //获取沙盒目录  [[NSBundle mainBundle] bundlePath];                    //获取沙盒目录.app文件  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  NSString *DocumentsPath = [paths objectAtIndex:0];    //获取沙河目录Documents文件夹  NSTemporaryDirectory()                                //获取沙河目录tmp文件夹</code></pre>    <h2>十、iOS数据存储</h2>    <p>(1)Plist文件</p>    <p>(2)SQLite数据库</p>    <p>(3)CoreData数据库</p>    <p>SQLite数据库增删改查</p>    <p>支持类型:integer real, text, blob</p>    <p>使用单引号来环绕文本值。如果是数值,请不要使用引号。</p>    <pre>  <code class="language-objectivec">#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 表名;</code></pre>    <p> </p>    <p>来自:http://www.jianshu.com/p/3dcb1f7f14e5</p>    <p> </p>