Cocoa Application-基础
Cocoa
Cocoa基于Quartz,采用Painter model來繪制
Painter model主要是在一個連續(xù)的繪制操作中會將一層的繪制應用于一個output 畫布(canvas)上
在添加新的繪制層(layers of paints)時先前的繪制層可能被覆蓋或者修改
繪制環(huán)境(drawing enviroment)
包含數(shù)字畫布(digital canvas)和圖形設置(graphics setting) 數(shù)字畫布決定了你在哪繪制,而圖形設置控制繪畫的每一方面,包括大小,顏色,方向等等
繪制上下文(draw context)
封裝了繪制在畫布上的所有信息 包含當前繪制的屬性和 device-specific representation of the digital paint on the canvas 還不能理解什么意思
坐標系
用戶坐標空間:使用固定比例的坐標值 一個單位實際上等于1/72英寸,但是實際上坐標控件并沒有像素和英寸(dpi)的概念
設備坐標空間:主要依賴于使用設備的本地坐標空間,主要于設備分辨率有關
視圖繪制
當view需要繪制的時候 cocoa會給這個視圖發(fā)一個drawRect消息,然后就會調用drawRect方法
XIB/storyboard
本質都是將可視化的窗口轉換成代碼去創(chuàng)建控件
區(qū)別
Xib是輕量級的,用來描述局部的UI界面 XIB一般用來封裝獨立控件
XIB實現(xiàn)了控件的添加與frame的設置這兩步?(沒看懂)
xib是IB編譯過程中的一種文件類型 nib是該工程編譯后
Storyboard是重量級的,用來描述整個軟件的多個界面,并且能展示多個界面之間的跳轉關系
Storyboard可以簡單理解成一組與viewController關聯(lián)的xib的集合 該集合中也同時保存了各個viewChontroller之間跳轉的數(shù)據(jù)
XiB初始化
懶加載
用到的時候再加載 并且只加載一次
比如說在調用的時候會判斷一下這個對象是否為空 如果為空才會進行一次創(chuàng)建 這樣就避免了重復創(chuàng)建
loadNibNamed
會通過NibName尋找和NibName相同的xib文件進行l(wèi)oad
//一NSBundle *bundle = [NSBundle bundleForClass:[self class]];if (![bundle loadNibNamed:self.className owner:self topLevelObjects:nil]) {return;} //二HYLShopView *shopView=[[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil] firstObject];initWithNibName/initWithWindowNibName(獲取windowController的辦法)
這個的主要作用是返回Xib的控制權
@interface CustomWindowController ()@end@implementation CustomWindowController -(id)initGetWindowController{//self = [super initWithNibName:NSStringFromClass([self class]) bundle:[NSBundle bundleForClass:[self class]]];self = [super initWithWindowNibName:NSStringFromClass([self class])];//這里獲取xib的windowControllerreturn self; } @end 此時就可以在其他的類或者window里面去獲取這個window的controller CustomWindowController* windowController = [CustomWindowController alloc]initGetWindowController]XIB中File’s Owner應該是程序的NSApplication對象 NSApplication對象從時間隊列中取得事件 轉發(fā)給相應的窗口
指向別的對象的成員變量指針叫做outlet
IBAction等價于void
awakeFromNib
當awakeFromNib方法被調用時,所有視圖的outlet和action已經連接,但還沒有被確定
NIB文件是應用程序所有對象的存檔
當程序啟動后 對象從文件中釋放 重新賦予聲明 準備接收用戶出發(fā)的事件信息
在獲得聲明后 并沒有接收到用戶的事件信息以前 所有的對象自動發(fā)送awakeFormNib消息
awakeFromNib
運行過程
awakeFromNib->applicationDidFinishLaunching
這個awakeFormNib的Nib是項目創(chuàng)建的時候自帶的那個xib文件
首先運行NSApplicationMain函數(shù)
創(chuàng)建一個NSApplication的實例
應用程序對象讀取main NIB文件內容 將歸檔的對象釋放出來
NIB文件中的每個對象都發(fā)送awakeFromNib消息
應用程序對象開始檢查是否有時間發(fā)生
當應用程序接收到鼠標鍵盤發(fā)送的事件后 窗口服務器將事件數(shù)據(jù)放到合適的應用程序事件隊列中
應用程序對象從事件隊列中讀取事件數(shù)據(jù) 轉發(fā)給用戶界面對象(如按鈕) 就出發(fā)了程序代碼
如果程序改變了界面中的數(shù)據(jù) 界面就會被重新繪制 然后應用程序繼續(xù)檢查他的事件隊列 接收下一個事件
檢查時間隊列的過程以及動作組成了整個主程序的事件循環(huán)
當用戶選擇從菜單中退出時 NSApp接收到一個terminate:消息 終止進程 應用程序銷毀所有對象
關于target和action
target是一個指向對象的指針
action就是一個消息
例如單擊按鈕時 按鈕將action發(fā)送給他的target
action方法中的sender參數(shù)使得接受者知道是哪個控制發(fā)送的消息 sender中也會存儲一些其他的消息
比如
BOOL isOn = [sender state];//查看按鈕是否被勾選上
AppDelegate文件
最先執(zhí)行applicationSupportsSecureRestorableState
再執(zhí)行applicationDidFinishLaunching:(NSNotification *)aNotification
(void)applicationDidFinishLaunching:(NSNotification *)aNotification作為程序的入口 用于初始化
在程序結束的時候會調用applicationDidFinishLaunching
還聲明了一個NSwindow*window 的XIB文件的IBOutlet輸出變量 這就讓AppDelegate可以直接對window做一些操作 比如說windows的背景顏色等
Assets.xcassets文件
主要對工程中使用的圖片資源進行統(tǒng)一管理
例如AppIcon的圖片資源就作為應用的安裝圖標
NSControl繼承關系圖
結構
NSResponder 是一個非正式協(xié)議的抽象類 里面主要是聲明了各種響應鍵盤鼠標觸摸板等事件的抽象方法 約定了是將響應的響應者鏈處理機制 也就是約束了大家處理這些事件該怎么處理
然后NSApplication,NSWindow,NSWindowController,NSView,NSViewController就是事件響應者 他們繼承了NSResponder 他們具體分化去處理具體的事情 比如說NSView就是具體處理視圖(例如button)接收到鼠標鍵盤消息時的反應 NSWindow就是處理winow消息的鼠標鍵盤消息時的反應 然后依次往下戲份 直到NSButton這種
所以上面這些大的類就是規(guī)定類大的方向 怎么去處理
NSResponder定義了事件相關的抽象接口 具體實現(xiàn)由子類NSView負責
NSControl實現(xiàn)了界面交互的Action Message事件處理。NSControl內部包括一個cell類來負責UI界面繪制和Action Message事件處理 對于直接繼承自NSCiew的子類 界面繪制由空間自己完成
NSCell
NSCell可以理解為對 NSControl更細粒度的控制 大多數(shù)NSView子類控件并不是由NSView完成界面繪制和事件響應處理 而是內部的cell類完成
NSSlider
右邊欄里勾選continuous則滾動條移動時會不斷的發(fā)送action消息 如果不勾選則是在鼠標釋放后才發(fā)送action消息
NSTextField
NSTextField類的實例文本框允許用戶輸入一行文字 可以設置:可編輯 不可編輯
Action
button需要綁定一個IBAction 在按下的時候就要調用這個action
對于button來說 他只需要綁定一個行為 -(IBAction)xxx:(id)sender; //這樣點擊這個按鈕的時候就會發(fā)送這個消息
例如
outLet
文本框就需要指定一個outLet 在輸入后傳數(shù)據(jù)給outLet對象
例如
快捷創(chuàng)建outLet和Action
右鍵按住按鈕或者文本框什么的
lebel
@property (weak) IBOutlet NSTextField *lebel;lebel.editable = NO;lebel.bordered = NO;lebel.drawsBackground = NO;setObjectValue:
NSString *string = [_test stringValue];//從_test綁定的文本框中獲取輸入的值 [_lebel setObjectValue:[NSString stringWithFormat:@"%@ num:%d",string, [string length]]];//通過setOBjectValue設置lebel要顯示什么help
很多類都有一個delegate成員變量
可以設置該變量指向一個helper對象
創(chuàng)建一個windows的代碼
//myWindow.h #import <Foundation/Foundation.h> #import <Cocoa/Cocoa.h> NS_ASSUME_NONNULL_BEGIN@interface myWindow : NSObject @property(nonatomic,strong) NSWindow* myWindow; -(IBAction)showWindowAction:(id)sender; @endNS_ASSUME_NONNULL_END //myWindow.m #import "myWindow.h"@implementation myWindow -(NSWindow*)myWindow {NSRect fram = CGRectMake(0,0, 200, 200);//設置位置和長寬NSUInteger style = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask;NSWindow *window = [[NSWindow alloc]initWithContentRect:fram styleMask:style backing:NSBackingStoreBuffered defer:YES];//sbacking 窗口繪制的緩存模式 defer表示延遲創(chuàng)建還是立即創(chuàng)建window.title = @"New Create Window";return window; } -(IBAction)showWindowAction:(id)sender {//窗口顯示[self.myWindow makeKeyAndOrderFront:self];//窗口居中[self.myWindow center]; } @end關于什么是keyWindow
key
獲取activeWindow的名字
NSDictionary *activeApp = [[NSWorkspace sharedWorkspace] activeApplication];NSLog(@"Active application is: %@", (NSString *)[activeApp objectForKey:@"NSApplicationName"]);delegate和viewController的區(qū)別
AppDelegate是什么
OC應用程序是一個不斷循環(huán)的程序
而AppDelegate是在不斷循環(huán)的程序和我們的代碼之間進行通訊
AppDelegate對象是作為Application對象的委托屬性
主要作用是使我們有機會在每次應用程序狀態(tài)更改時做出反應
AppDelegate protocol可選方法
application(UIApplication, didFinishLaunchingWithOptions: Dictionary) 這是第一個要執(zhí)行的方法。調用它是為了讓我們知道基本對象已被實例化,并且該應用已準備就緒。我們可以在此方法中編寫準備應用程序所需的所有代碼,例如聲明初始值,創(chuàng)建或打開數(shù)據(jù)庫,檢查當前設置等。 applicationWillResignActive(UIApplication) 當應用程序不活動時通常由于傳入呼叫或消息而調用此方法。 applicationDidEnterBackground(UIApplication) 關閉應用程序(移至后臺)時調用此方法。 applicationWillEnterForeground(UIApplication) 在應用再次激活之前調用此方法。 applicationDidBecomeActive(UIApplication) 在啟動應用程序以及從非活動狀態(tài)恢復時調用此方法。 applicationWillTerminate(UIApplication) 在終止應用程序之前調用此方法。當系統(tǒng)決定終止應用程序時,通常會發(fā)生此狀態(tài),因為它需要其他應用程序的內存或應用已被用戶終止。MVC
M:model模型,一個程序需要處理的數(shù)據(jù)
V:view視圖,就是用戶界面,由窗口和視圖組成
C:controller,控制器,在接受數(shù)據(jù)或者接受到視圖行為后,對數(shù)據(jù)進行處理和視圖進行變化的控制器對象
也就是說model和view是不會相互鏈接的,所以中間就需要controller來進行中間傳輸和處理
優(yōu)點在于數(shù)據(jù)傳輸過來 通過controller的邏輯進行處理,作出相對應的反應,這個邏輯是可以重復多用的,
App生命周期
App載入會先調用loadView方法或載入IB中創(chuàng)建的初始界面的方法,將視圖載入到內存中
window生命周期
View的生命周期
(view從xib右鍵拉出來)VC init->view->awakeFromNib->VC viewDidLoad->view drawRect
(通過代碼init alloc)
首先調用initWithFrame(如果是IB創(chuàng)建的會對view對象archives 自動調用initWithFrame),所以想要對IB創(chuàng)建的view進行屬性初始化配置可以調用awakeFromNib
awakeFromNib是在一個nib文件中所有view對象都完成加載之后,會向文件中所有view對象發(fā)一個awakeFromNib消息
viewDidDisappear的時候會調用 removeFormSuperView
當調用removeFromSuperView的時候 會先判斷SuperView是否為nil 如果不為nil 則superView 會將當前view release
initWithFrame
目前測試的情況是,如果我自己實現(xiàn)了一個customView類型,然后重寫initWithFrame,和awakeFromNib 將這個view在IB的inspect版面賦值給viewController的view的一個subView(customView),然后如果通過右鍵在viewController.mm文件中添加這個@property (strong) IBOutlet customView *cusView;則在viewController init的時候會自動調用awakeFromNib來初始化屬性,
如果不右鍵添加,而是自己手動添加一個@property (strong) customView *cusView;則需要在viewController的init方法里面調用_cusView = [[customView alloc]initWithFrame:NSMakeRect(0, 0, 30, 30)];然后在initWithFrame里面初始化屬性,
在加載viewController的時候并不會自動調用initWithFrame。需要手動調用
drawRect
This method is invoked during the display process to generate code that’s rendered by the window server into a raster image
主要是在view被繪制的時候
接受的參數(shù)是一個rectangle,這個rectangle是接受者自己的坐標系中需要被繪制的區(qū)域
setNeedDispaly
延遲繪制
標記一個view需要被redisplay 然后在這個event loop結束的時候會redisplay
如果需要立即繪制就直接調用display
displayIfNeeded
立即繪制如果當前這個view已經被標記為需要redesplay,應該是前面已經調用過setNeedDispaly
關于中途接受到display消息的繪制起點:View Opacity
在調用display方法的時候 這個view會在view hierarchy中定位第一個會返回isOpacity為YES的view,從這個view開始向前繪制
內存問題
viewDidUnload
在發(fā)生內存警告的時候如果本視圖不是當前屏幕上正在顯示的視圖的話, viewDidUnload將會被執(zhí)行,本視圖的所有子視圖將被銷毀,以釋放內存,此時開發(fā)者需要手動對viewLoad、viewDidLoad中創(chuàng)建的對象釋放內存。 因為當這個視圖再次顯示在屏幕上的時候,viewLoad、viewDidLoad 再次被調用,以便再次構造視圖。
問題
IBOutlet是什么修飾符 被IBOutlet修飾的應該就是target 可以用來指向控件的指針
IBAction和void有區(qū)別嗎
怎么刪除控件:command+刪除鍵
cell是什么
cell是一個控件的內部單元格
總結
以上是生活随笔為你收集整理的Cocoa Application-基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 算法与数据结构实战实验——线性数据结构实
- 下一篇: Mac中替换Caps Lock为Cont