iOS從入門到精通

geyu7363 7年前發布 | 10K 次閱讀 RunLoop 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])); } }</code></pre>

三、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;</code></pre>

    四、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; //視圖消失</code></pre>

    五、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 //視圖控制器類 (管理視圖的內容)</code></pre>
      #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;</code></pre>

    (2)查看指定的View是否響應了點擊事件,如果沒有找它的nextResponder,再繼續一層一層的向上查找,直到找到AppDelegate,再沒有響應,則此點擊事件被系統丟棄。(向上查找)

    點擊查找View

    #pragma    -查找用戶點擊的View響應事件
  • (nullable UIResponder*)nextResponder;</code></pre>

    七、空指針和野指針的區別

    空指針: 沒有存儲任何內存地址的指針就稱為空指針(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];</code></pre>

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</code></pre>

    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 表名;

     

    來自:http://www.jianshu.com/p/3dcb1f7f14e5

     

 本文由用戶 geyu7363 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!