Objective-C編程 — 類和繼承

来源:https://www.cnblogs.com/Julday/archive/2020/02/20/12335640.html
-Advertisement-
Play Games

講述面向對象中的一個重要概念——繼承,使用繼承 可以方便地在已有類的基礎上進行擴展,定義一個具有父 類全部功能的新類。 父類和子類 我們在定義一個新類的時候,經常會遇到要定義的新類是某個類的擴展或者是對某個類的修正 這種情況。如果可以在已有類的基礎上追加內容來定義新類,那麼新類的定義將會變得更簡單。 ...


講述面向對象中的一個重要概念——繼承,使用繼承 可以方便地在已有類的基礎上進行擴展,定義一個具有父 類全部功能的新類。

父類和子類

我們在定義一個新類的時候,經常會遇到要定義的新類是某個類的擴展或者是對某個類的修正 這種情況。如果可以在已有類的基礎上追加內容來定義新類,那麼新類的定義將會變得更簡單。

像這種通過擴展或者修改既有類來定義新類的方法叫作 繼承 (inheritance)。在繼承關係中,被繼 

承的類稱為 父類 (superclass),通過繼承關係新建的類稱為 子類 (subclass)。

繼承意味著子類繼承了父類的所有特性,父類的數據成員和成員函數自動成為子類的數據成員 

和成員函數。除此之外,子類還可以

●  追加新的方法

●  追加新的實例變數

●  重新定義父類中的方法

當然,如果子類中只追加新的實例變數而不變更方法則沒有任何意義。子類中重新定義父類的方法 叫作 重寫 (override)。

讓我們來看幾個例子。在圖 3-1 中,類 B 是類 A 的子類,類 B 繼承了類 A 的實例變數和方法, 但重寫了 method2。類 C 也是類 A 的子類,類 C 中增加了新的實例變數 z 和新的方法 method3。類 B 和類 C 都是類 A 的子類,無論類 A、類 B 和類 C 的任何一個實例變數都能夠執行方法 method1 和 method2。

  enter image description here

父類和子類是一種相對的稱呼。例如,在上例中,如果以類 B 為父類又派生出一個子類 D,那 麽類 B 相對於類 A 是子類,相對於類 D 卻為父類。

另外,在集合用語中,子集指的是比較小的集合(相對於父集),但在類的情況下子類一般是父 類的擴展。為了避免這種命名上的混亂,C++ 中把父類稱為 基類 (base class),把子類稱為 派生 類 或 導出類 (derived class)。考慮到面向對象的程式設計中一般都使用父類、子類的叫法,本書也 使用這種叫法。

一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是一個我的iOS交流群:1012951431, 分享BAT,阿裡面試題、面試經驗,討論技術, 大家一起交流學習成長!希望幫助開發者少走彎路。

類的層次結構

假如以某個類為父類生成若幹子類,然後再繼承這些子類並生成更多的子類,如此迴圈下去就 可能會生成一顆倒立的樹,它由通過繼承而彼此關聯的類組成,這樣的樹稱為 類層次結構 (class hierarchy)。

位於類層次最頂端的類稱為 根類 (root class),如圖 3-2 所示。

  enter image description here

NSObject 是 Cocoa 環境下的根類,Cocoa 中所有的類都直接或間接地繼承了 NSObjectA。新建的 任何類都必須是 NSObject 或它的繼承類的子類。NSObject 中定義了所有 Objective-C 對象的基本 方法。

由於這種類的層次關係,Objective-C 的所有對象都繼承了 NSObject 類中定義的各種屬性。 Objective-C 的對象能夠作為對象來使用,就是因為類 NSObject 中定義了對象的基本功能。 在面向對象的語言中,有的和 Objective-C 一樣有唯一根類,例如 Java 和 Smalltalk 等;有的則不 存在唯一根類,如 C++。

利用繼承定義新類

繼承的定義

如果想通過繼承為某個類定義一個子類,該怎麼辦呢?

Objective-C 在子類的介面部分聲明繼承關係。在 2.2 節中我們已經說明瞭如何定義類的介面,這 里再介紹一遍。

 

定義父類 A 的子類 B 的時候,“類名”是新類 B,冒號後面的“父類名”是需要繼承的類 A。

至此為止本書中的父類都使用了 NSObject,這是因為 Objective-C 中所有的類都要繼承根類, 而  NSObject 是  Objective-C 中所有類的根類 。如果子類有想繼承的類,就要直接指明該類為父類,否 則就需要指定 NSObject 為父類。前文中定義 Volume 類的時候,因為 Volume 類並沒有特別想繼承的 類,所以直接使用了 NSObject 作為父類。

實例變數的聲明中只需要聲明新增的變數。如果沒有新增的變數,則只需要加上 {} 即可,有時 甚至連 {} 都可以省略。 方法的聲明中只需要追加新增的方法。如果要覆蓋父類中已聲明的方法(重寫),則需要在介面 中對方法重新聲明。通常我們會給重寫的方法加上註釋,以便理解。

下麵展示了定義類 A 的子類 B 時介面部分的情況。變數 x 和方法 method1 繼承於類 A,所以不 需要重新聲明,方法 method2 的聲明也可以被省略。

 

類定義和頭文件

假設有一個已經定義好了的類 Alpha,那麼頭文件 Alpha.h 就應該已經存在。要定義類 Alpha 的 子類 Beta 的時候,頭文件 Beta.h 中必須包含 Alpha.h。不知道父類定義的話是無法定義子類的。所以 包含父類介面的頭文件是必須的。

類的實現部分必須引入包含類的介面部分的頭文件。實現部分需要包含新增和重寫的方法的實 現。當然實現部分也可以定義各種局部函數和變數。

圖 3-3 的文件 Gamma.m 的方法中調用了方法doSomething ,這個方法是從類 Alpha 繼承而來 的。 文 件 Gamma.m 引 入 的 頭 文 件 Gamma.h 中 引 入 了 Beta.h,Beta.h 中 又 引 入 了 Alpha.h, 所 以 Gamma.m 可以調用方法doSomething。

 

類的定義可以不斷地使用繼承向下擴展,但無論怎麼擴展,只要保證了這種頭文件的引入方式, 任何一個派生類中就都能使用父類中定義的變數和方法。

繼承和方法調用

子類中定義的方法,除了能夠訪問新追加的實例變數外,也能夠訪問父類中定義的實例變數。

另外,因為繼承的原因,子類也可以響應父類中定義的消息。但如果子類中重寫了父類的方法, 就需要註意實際運行中到底哪個方法(父類的還是子類的)被執行了。

如圖 3-4 所示,類 A 包含方法 method1、method2、method3。類 B 是類 A 的子類,類 B 中重新 定義了 method2。類 C 是類 B 的子類,類 C 中重新定義了 method1。

 

我們來看看給類 B 的實例變數發送消息時的情況。首先,假設向類 B 的實例對象發送了對應 method1 的消息,即進行了方法調用。雖然類 B 中沒有 method1 的定義,但因為類 B 的父類類 A 中 定義了 method1,所以會找到類 A 的 method1,調用成功。消息 method3 的情況下也是同樣的道理, 類 A 中定義的 method3 會被執行。method2 同前兩個消息不同,類 B 中定義了 method2,所以會使 用自身定義的 method2 來響應這個消息。

而給類 C 的實例發送消息的話會怎麼樣呢?類 C 中有 method1 的定義,所以會直接使用類 C 中 定義的 method1 來響應這個消息。類 C 中沒有 method2 的定義,所以調用的時候會使用類 B 中定義 的 method2 來響應。類 C 和類 B 中都沒有定義 method3,所以類 A 中的定義 method3 會被調用。

調用父類的方法

子類繼承了父類之後,有時就可能會希望調用父類的方法來執行子類中定義的其他處理,或者 根據情況進行和父類一樣的處理或子類中單獨定義的處理。讓我們來看看圖 3-4 中的例子,如果要在 類 B 的 method2 的定義中調用類 A 的 method2,那麼該怎麼辦呢?通過 self 調用 method2 的話,就 會變成遞歸調用自身定義的 method2。

如果子類中想調用父類的方法,可以通過 super 關鍵字來發送消息。使用 super 發送消息後,就 會調用父類或父類的父類中定義的方法。如圖 3-5 所示,類 C 中定義了 method1 和 method3。類 C  的 method1 中通過 super 調用了 method3,這時被調用的 method3 是類 A 中定義的 method3。

 

super 和 self 不同,並不確定指向某個對象。所以 super 只能被用於調用父類的方法,不能通過 super 完成賦值,也不能把方法的返回值指定為 super。

初始化方法的定義

新追加的實例變數有時需要被初始化。另外,子類也可能需要同父類不同的初始化方法。這些 情況下就需要為子類定義自己的初始化方法。

子類中重寫 init 初始化方法的時候,通常按照以下邏輯。其他以 init 開頭的初始化方法也是同理。

 

請註意第一行調用了父類的init 方法,父類的init 方法會初始化父類中定義的實例變數。下 面是子類專有的初始化操作。

如果所有的類的初始化方法都這樣寫,那麼根類 NSObject 的init 方法就一定會被執行。否則 生成的對象就無法使用。與此同時,這樣做也可以防止漏掉父類中定義的實例變數的初始化。

執行的時候父類的初始化方法可能會出錯。出錯時則會返回 nil,這種情況下子類也不需要再進 

行初始化,直接返回 nil 就可以了。

如果父類是 NSObject,則基本上不可能初始化出錯,因此不判斷這個返回值也是可以的。使用 傳入的參數或通過從文件讀入變數進行初始化時,因為值的類型錯誤或讀取文件失敗等原因,初始 化有可能會失敗。這種情況下,需要確認父類的初始化方法的返回值。另外,上例中對 self 進行了 賦值,關於這個賦值的含義我們會在第 8 章中詳細說明,這裡只需要記住這是初始化方法的一種固 定寫法即可。

生成實例對象的方法alloc 會把實例對象的變數都初始化為 0(後面會提到的實例變數 isa 除 外)。所以,如果子類中新追加的實例變數的初值可以為 0,則可以跳過子類的初始化。但是為了明確是否可以省略,最好為初值可為 0 的變數加上註釋。

從程式的書寫角度來說,設定初始值的方法有兩種,即可以在初始化方法中一次性完成實例變數 的初始化,也可以在初始化方法中先設置實例變數為預設值,然後再調用別的方法來設置實例變數 的值。例如,類 Volume 也可以通過先調用初始化方法init ,然後再調用setMax: 等方法來設定音 量的最大值、最小值和變化幅度。原則上來說,初始賦值之後值不再發生變化的變數和需要顯示設 定初值的變數,都需要通過帶參數的初始化方法來進行初始化。

使用繼承的程式示例

追加新方法的例子

我們來定義一個帶有靜音功能的類 MuteVolume。該類只有一個功能,即當收到mute 消息時, 設置音量為最小。

類 MuteVolume 的定義非常簡單,父類是已經定義好的類 Volume。子類 MuteVolume 除了可以使 用父類 Volume 中定義的所有實例變數和方法之外,還新增加了一個 mute 方法。

 

這裡使用了 Volume 作為父類,並引入了頭文件 Volume.h。Volume 的父類是 NSObject,所以 , 所以就不需要再進行指定了。

沒有定義新的實例變數,意味著子類中沒有要追加的實例變數。

   

該測試程式的功能是從終端讀入輸入的字元串,並根據字元串的第一個字元來決定如何設置音 量。具體來說,第一個字元為 u 時表示提高音量,d 表示降低音量,m 表示靜音,q 表示退出程式。

編譯子類的時候,需要連同父類一起編譯和鏈接,否則就無法使用父類中定義的方法。本例中 

編譯所需要的文件一共有 5 個,即 Volume.h、Volume.m、MuteVolume.h、MuteVolume.m、main.m。

 

方法重寫的例子

上面通過繼承實現靜音功能類的例子非常簡單,讓我們來看一個更實用的例子。

假設該例子要實現兩個功能。第一個功能是,當再次收到mute 消息時,音量會恢複原值;第二 個功能是,在靜音狀態下收到up 或down 消息時,會返回最小音量值,同時改變音量值。

實現這些功能的方法有很多,這裡我們增加一個 BOOL 類型的變數 muting,同時修改方 

法initWithMin:max:step:和 方法value的 實現。

     

初始化方法initWithMin:max:step:首 先調用了父類的初始化方法,然後對新增的實例變數 muting 進行了初始化。如前所述,子類的初始化一定要在父類的初始化之後進行。

value方 法根據當前是否為靜音狀態返回不同的值。靜音狀態下,返回最小值 min。mute 方法 

中只需要改變實例變數 muting 的狀態來標識是否靜音,不需要更改音量值 val。

編譯的情況和上一節一樣。main.m 直接使用上一節的即可。 

繼承和方法調用

使用 self 調用方法

如果想在一個方法中調用當前類中定義的方法,可以利用 self。但如果存在繼承關係,通過 self 調用方法時要格外註意。

在圖 3-6 的例子中,有三個類 A、B、C。類 A 中定義了 method1、method2 和 method3 三個方法。 類 B 繼承了類 A,重寫了 method1 和 method3。類 C 繼承了類 B,重寫了 method2。

 

假設類 B 的方法 method3 想調用 method1 和 method2,通過 self 調用了 method1 和 method2。我 們來分析一下這個過程中到底哪個函數被調用了。對類 B 的實例對象調用 method3 方法時,首先會 通過 self 調用 method1,這個 method1 就是類 B 自身定義的 method1。接著,method3 通過 self 調用 method2,因為類 B 中並沒有 method2 的定義,所以就會調用從類 A 中繼承而來的 method2。

而如果是類 C 的實例對象調用方法 method3 的話會怎麼樣呢?我們首先來看看 method3,因為 類 C 中並沒有定義 method3,所以調用的是類 B 中定義的 method3。要註意這個時候 self 指的是類 C 的實例對象,當 [self  method1] 執行時,因為類 C 中沒有定義 method1,所以調用的是類 B 中 定義的 method1。然後,當 [self  method2] 執行時,因為類 C 中定義了 method2,所以執行的是 類 C 中定義的 method2,而不是上例中類 A 中定義的 method2。另外還有一點需要註意,就算類 B 中定義了 method2,調用的也是類 C 中定義的 method2。

也就是說,self 指的是收到當前消息的實例變數 ,因此,就算是同一個程式,根據實例的類的不 同,實際調用的方法也可能不相同。

使用 self 的時候要一定小心,要仔細分辨到底調用了哪個類的方法。即便如此,利用 self 的特 性來編程也是很常見的,更多詳細內容請參考 11.1 節的內容。

使用 super 調用方法

而如果不使用 self 而使用 super,程式執行的結果會怎樣呢?

圖 3-7 是用 super 替代圖 3-6 中的 self 的情況。使用 super 調用方法時,最後被調用的方法是類 B 的父類中定義的方法。所以無論是類 B 還是類 C 的實例變數調用了 method3,最後調用到的都是類 A 中定義的 method1 和 method2。

 

測試程式

我們用一個簡單的程式來驗證一下上面所描述的內容。這個程式本身並沒有太大的意義,僅僅 是用來測試方法調用的。

測試程式中有三個類 A、B、C。類 A 中定義了方法 method1 和 method2。類 B 中對 method1 進 行了重寫,通過 self 調用了 method1,通過 super 調用了 method2。類 C 重寫了 method1。

   

程式執行之後輸出如下。可以看出,類 B 和類 C 的實例分別調用了不同的方法。

 

方法定義時的註意事項

局部方法

實現介面聲明中的方法時,可把具備獨立功能的部分獨立出來定義成子方法。一般情況下,這 些子方法都只供內部調用,不需要包含在類的介面中對外公開。

這種情況下,局部方法可以只在實現部分(通常是 .m 文件)中實現,而不需要在介面部分中進 行聲明。這樣一來,就算其他模塊引用了介面文件,也無法獲得這個方法的定義,無法調用這個方 法,從而就實現了局部方法。但這裡只是說無法從介面中獲得這個方法的定義,這個方法本身還是存在的,只要發送了消息,就能夠執行。

讓我們來看一個簡單的例子,類 ClickVolume 是類 Volume 的一個子類,它的主要功能是當音量 發 生 變 化(提 高 或 降 低 )時 發 出 提 示 音。 提 高 或 降 低 音 量 時 發 出 提 示 音 使 用 一 個 共 同 的 方 法playClick, 定義如下所述。因為這個功能不會在其他地方使用到,所以我們把它定義成一個局 部方法,不在介面文件中聲明。

 

未在介面中聲明的局部方法和沒有進行屬性聲明的 C 語言函數一樣,只能被定義在局部方法之 後的方法調用。在上面的例子中,playClick 就必須定義在up 和down 的前面。定義順序方面出現的 問題,可以使用第 10 章介紹的“範疇”(category)來解決。

編程的時候使用局部方法可以增強程式的可維護性,但在繼承的時候可能會出現問題。例如, 子類新追加的方法可能並不知道父類已經實現了局部方法而去重新實現一個父類的局部方法。

為了避免這一問題,蘋果公司建議為局部方法名添加固定的首碼(詳情請參考附錄 C)。 

指定初始化方法

前面已經介紹過瞭如何定義初始化方法,但還有一些要註意的地方。

根據需求有時可能需要為一個類定義多個不同的初始化方法。例如,既需要提供一個可指定每 個參數初始值的初始化方法,又需要提供一個每個參數都直接使用預設值的初始化方法;既需要提供 一個用記憶體變數進行初始化的初始化方法,又需要提供一個能從文件讀入變數完成初始化的初始化 方法等。 指定初始化方法 (designated initializer)就是指能確保所有實例變數都能被初始化的方法, 這種方法是初始化的核心,類的非初始化方法會調用指定初始化方法完成初始化。通常,接收參數 最多的初始化方法就是指定初始化方法。

子類的指定初始化方法通常都是通過向 super 發送消息來調用超類的指定初始化方法。除此之外, 還有一些通過封裝來調用指定初始化方法的方法叫作 非指定初始化方法 (secondary initializer)。圖 3-8展示了指定初始化方法的概念,箭頭指明瞭調用關係。圖中每個類都只有一個指定初始化方法,實 際上也可以存在多個。

子類的指定初始化方法,必須調用超類的指定初始化方法。如圖 3-8 中所示,按照類層次從底向 上,各個類的指定初始化方法會被連鎖調用,一直到最上層的 NSObject 的指定初始化方法——init 為止。

 

如果子類中想重寫父類中的指定初始化方法,就一定要調用父類的指定初始化方法,而不能調 用父類的非指定初始化方法。原因是非指定初始化方法內部會調用指定初始化方法,造成遞歸迴圈 調用,無法終止。

請看圖 3-9 中的例子,類 A 的指定初始化方法是initWithMax :。init 是類 A 的非指定初始 化方法。類 B 是類 A 的子類,在 B 中重寫了指定初始化方法initWithMax :。initWithMax :中 調用了父類類 A 的 init。如圖所示,如果類 A 的 init 中通過 self 調用了initWithMax :,那麼,當 初始化對象是類 B 的實例時,就又會調用到類 B 的initWithMax :,這樣就變成了一個遞歸迴圈, 調用永遠無法結束。

 

再讓我們回頭看一下圖 3-8,圖 3-8 中類的非指定初始化方法都調用了指定初始化方法來進行初 始化,同時父類的非指定初始化方法也可以被繼承,但定義的時候一定要註意,否則也會出現迴圈 調用的問題。

Objective-C 沒有特殊的語法或關鍵字來表明哪個方法是指定初始化方法,所以通常需要通過 文檔或註釋來標明指定初始化方法。Cocoa API 文檔中的絕大多數類都標明瞭哪個方法是指定初始 化方法。

另外,如果你想一起進階,不妨添加一下交流群1012951431,選擇加入一起交流,一起學習。期待你的加入!

 
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、環境說明 | 操作系統 | CentOS Linux release 7.4.1708 (Core) | | | : : | | Ambari | 2.6.x | | HDP | 2.6.3.0 | | Spark | 2.x | | Phoenix | 4.10.0 HBase 1.2 | 2 ...
  • 本文是自己對MySQL的 索引的理解,如有錯誤,還望不吝指出。 1 索引 索引這兩個字著實有些太泛,而在我的理解中,其就是一個查字典的過程,比方說現在我們要從一本字典中查一個 字,那麼我們可以從目錄中的 字母找到這個 字,發現在 頁,然後翻到 就可以看到關於 這個的解釋、用法等。 可以看到我們不是從 ...
  • HDFS架構(Master Slave) 幾個進程的角色 1. nameNode(master):用於保存、管理、持久化文件的元數據(文件名、文件副本數、文件塊大小、文件塊列表),同時還要接收客戶端的文件讀寫請求。 2. secondaryNameNode:用於實時同步文件元數據,給nameNode ...
  • Yarn架構(Master Slave) 進程角色: resourceManager(Master):任務調度和集群資源管理。 nodeManager(Slave):單個節點的資源管理。 applicationMaster:為任務程式申請資源,任務程式運行狀態監控、錯誤恢復。 container:對 ...
  • 顧名思義 zookeeper 就是動物園管理員,他是用來管 hadoop(大象)、Hive(蜜蜂)、pig(小 豬)的管理員, Apache Hbase 和 Apache Solr 的分散式集群都用到了 zookeeper;Zookeeper: 是一個分散式的、開源的程式協調服務,是 hadoop ...
  • 主要用到的Zookeeper機制: 臨時+有序節點,節點watch機制 過程: 1. 發生分散式鎖競爭時,參與競爭的各個客戶端服務都到Zookeeper的同一父節點(代表著同一把鎖)下建立自己的臨時+有序子節點,創建成功後子節點名被zk返回給客戶端,各客戶端保存在本地。 2. 所有客戶端服務都拉取父 ...
  • Android中一個用於網頁顯示的控制項,實際上,也可以看做一個功能最小化的瀏覽器,看起來類似於在微信中打開網頁鏈接的頁面。WebView主要用於在app應用中方便地訪問遠程網頁或本地html資源。同時,WebView也在Android中充當Java代碼和JS代碼之間交互的橋梁。 WebView基本用 ...
  • 解決方法一: 前提:需要一個鍵盤 步驟: 1、直接按下鍵盤上的Menu鍵。 解決方法二: 前提:需要Root之後的文件瀏覽器 步驟: 1、在文件管理器中打開 /System 文件夾; 2、複製 build.prop 文件到 SD Card 文件夾,並將原始的 build.prop 重命名備份; 3、 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...