第一章 熟悉Objective C

2021-07-10 11:09:13 字數 4255 閱讀 7645

首先,objective-c在c語言的基礎上新增了物件導向的特性,該語言採用「訊息結構」,而非其他語言的「函式呼叫」。「訊息結構」與「函式呼叫」的關鍵區別在於「訊息結構」執行的**由執行環境來決定,而「函式呼叫」由編譯器決定。編譯器甚至不關心接收訊息物件是何型別(接收訊息的物件問題也在執行時處理,其過程為**動態繫結**,第11條詳述)。

oc的重要工作由runtime元件完成,其物件導向特性所需的資料結構和函式都在runtime元件中。比如runtime元件中含有全部的記憶體管理方法。這個runtime元件本質上是一種與**相鏈結的動態庫。這種方式使得,只更新runtime元件就可以提公升應用程式效能。而那種工作在 編譯期完成的語言,需要重新編譯**(這個地方還是有些不理解,重新編譯怎麼了。。。)

如果想理解好oc需要理解c語言的記憶體模型(這個需要搞懂,目前還沒有與看,下次再看的時候需要搞懂!),有助於理解oc的記憶體模型以及引用計數機制的工作原理。若要理解記憶體模型需要明白,**oc中的指標用來指示物件**。

比如我們宣告乙個**變數**,令其指代乙個**物件**:

nsstring *str = @"string"; //要注意區分,str是變數,@"string"是物件 str變數指向分配在堆中的某塊記憶體

要強調的是,所有的**oc語言的物件都是分配在堆中的**(那block算什麼,我得再研究研究),不能在棧中分配oc物件。(細節問題啊,我能說面試的時候考這個了嗎。。。要不說細節決定成敗呢,唉)

![記憶體布局](

此時的記憶體布局為上圖,nsstring中的資料代表字串實際內容的位元組

分配在堆中的記憶體必須直接管理,而分配在棧上用於儲存變數的記憶體會在棧幀彈出時自動清理。**oc將堆記憶體管理**(malloc和free)**抽象為一套叫做「引用計數」**(具體見29條)**的記憶體管理架構**。另外在oc**中你也會看到不帶*的變數,它們可能會使用棧空間。這些變數儲存的不是oc物件。比如:cgrect,因為它只是乙個c結構體。與建立結構體相比,建立物件有額外的開銷,例如分配和釋放記憶體,會影響效能。如果只儲存非物件型別,用結構體就可以。

這一條的核心概念就是如題,盡量不要在標頭檔案中引入其他的標頭檔案。如果你只需要宣告乙個類,那麼你就使用一種叫做「前向宣告」的辦法,即@class。然後在.m檔案中引入其標頭檔案。這種將引入標頭檔案的時機延後的方式,可以避免增加編譯時間。同時,也解決了兩個類互相引用的問題。

但是,有的時候我們不得不在標頭檔案中引入其他的標頭檔案,例如**你寫的類繼承自某個超類,就必須引入定義那個超類的標頭檔案**。同理,**如果要宣告你寫的類遵從某個協議,那麼這個協議必須有完整定義,不能使用前向宣告,前向宣告只能告訴編譯器有某個協議,而此時,編譯器要知道該協議中定義的方法**。此時有兩種途徑,一是將該協議放在乙個單獨的檔案中,否則容易產生相互依賴,而且還增加編譯時間。二是有些協議,例如委託協議就不用單獨寫在乙個標頭檔案中。此時該協議與接受協議委託的類放在一起定義才有意義。這個時候最好能在實現檔案中宣告此類實現了該委託協議。

每次匯入標頭檔案時思考一下有沒有必要。可以用@class來取代,或者如果要實現屬性、例項變數或者遵循協議,盡量移至"class-continuation分類"中。這樣可以縮減編譯時間,降低彼此的依賴程度,即降低耦合度。依賴關係過於複雜會給維護帶來麻煩。

這個字面量語法呢就是介個「@」。它可以讓你宣告一些oc物件時更加簡單,減少了**量,更易讀。
nsstring
nsstring,可以醬 nsstring *str = @"123";(這在oc1.0以前做不到喲)
nsnumber
還有用於封裝基本資料型別的nsnumber,你可以醬紫操作:

nsnumber *intnum = @1;

nsnumber *floatnum = @1.1f;

nsnumber *intnum = @(3*4);

nsnumber *boolnum = @yes;

nsarray
nsarray *animals = @[@"cat", @"dog"]; //此時要注意,當陣列元素中有nil會丟擲異常

nsstring *dog = animals[1];

下面考慮這樣兩種情況:

nsarray *a = [nsarray arraywithobjects:obj1, obj2, obj3, nil];

nsarray *b = [@obj1, @obj2, @obj3];

如果此時obj2為nil,那麼a中只會剩下obj1,因為arraywithobjects:方法會依次處理各個引數知道nil為止。而b會丟擲異常。所以使用字面量會使得程式更加安全,因為通常插入nil說明程式有錯誤。

nsdictionary
通常用nsdictionary *dic = [nsdictionary  dictiionarywithobjectsandkeys:@"matt", @"first",nil];這種先是物件再是key,覺得彆扭。不如醬紫

nsdictionary *dic = @;

nsstring *last = dic[@"first"];

很簡單,很清晰。同陣列一樣,有nil拋異常。

字面量語法的侷限性
如果你想使用字面量語法,那麼必須是屬於foundation框架。如果自定義了其子類,就無法使用了。

還有就是用字面量語法建立出來的是不可變的,需要醬紫:

nsmutablearray *mutablearray = [@[@obj1, @obj2, @obj3] mutablecopy];

如果我們像這樣去定義常量

#define animation_duration 0.3

這樣沒有型別資訊,預處理過程會對所有的animation_duration做個替換。假如它定義在標頭檔案中,一旦其他類引入這個標頭檔案,也都會進行替換。所以對於常量我們可以這樣定義

static const nstimeinterval kanimationduration = 0.3;

(注意:在這裡static 和 const 要一起用,const代表不能修改,static代表該變數僅在此編譯單元(即實現檔案)可見)

這樣我們就可以知道他的常量型別,有助於編寫開發文件,更易讀,關於常量的命名方法是,若常量侷限於某編譯單元之內,要在前面加k;若常量在類之外可見,需要以類名為字首。

(注意:因為oc沒有namespace,所以最好不要把常量定義在標頭檔案。如果定義在標頭檔案最好加上類名字首)

有時候你想對外公開某個常量,比如在類**中呼叫nsnotificationcenter以通知他人。派發通知時通過字串表示通知的名稱,這個名稱可以為乙個外界可見的常值變數,要注意前面要加類名字首。

// .h extern關鍵字會告訴編譯器全域性符號表中有這個符號

extern nsstring *const eocstringconstant;

// .m 這裡const代表這個指標變數不能被修改

nsstring *const eocstringconstant = @"value";

由實現檔案生成目標檔案時,編譯器會在**資料段**為字串分配空間。

一般我們在定義狀態或者選項的時候可以用列舉。 

enum eocconnectionstate ;

這種方式使得實現列舉所用的資料型別取決於編譯器

後期有了些改進,可以指明用何種「底層資料型別」儲存列舉型別的變數。這樣就可以向前宣告列舉變數了,不然因為編譯器不清楚底層資料型別大小,就不知道應分配多少空間。

enum eocconnectionstate : nsinteger;

把第乙個值設定為1,後面的值會遞增1。

在foundation框架中定義了一些輔助的巨集,用這些巨集來定義列舉型別。(推薦這種方式),這些巨集具備向後相容的能力,如果目標平台支援新標準,就用新式語法,否則用舊式語法。

列舉狀態

typedef ns_enum(nsinteger, eocconnectionstate) ;

列舉選項,可以通過或操作,進行多選

typedef ns_options(nsinteger, eocpermitteddirection) ;

如何用巨集實現的就先不打出來了。

注意如果列舉需要按或進行相互組合,一定要用options,因為c++編譯器會預設運算結果的資料型別應該是nsinteger,且不允許隱式轉換,就需要自己顯式轉換。

還有一點需要注意,就是我們在用switch列舉狀態時不要加default,因為當我們新加入一種狀態時編譯器會發出警告,提示新加入狀態未在switch分支中處理,加上default就預設處理了。

python第一章筆記 第一章 基礎

參與除法的兩個數中有乙個數為浮點數,結果也為浮點數 如 1.0 2,1 2.0,1.0 2.0 python print 1.0 2 結果 0.5 print 1 2.0 結果 0.5 print 1.0 2.0 結果 0.5 整數 整數,計算結果的小數部分被截除,只保留整數部分 不會四捨五入 如 ...

第一章 緒論

1.16 void print descending int x,int y,int z 按從大到小順序輸出三個數 print descending 1.17 status fib int k,int m,int f 求k階斐波那契序列的第m項的值f gender char schoolname 校...

第一章 概述

1.模擬量輸入,輸出,開關量 閃爍 輸入,輸出及資料通訊 2.模擬量大多為開關量 3.mcu前做為前端採集器,mcu 感測器 4.開發步驟 1 i o分析 2 mcu造型 3 評估系統及相關硬體 4 設計硬體系統 5 硬體系統模組測試 6 軟體系統設計 7 系統測試 8 進一步工作 5.交叉編譯 6...