Effective Objective-C 2.0 初讀小結

  • 1.對于OC中的對象聲明例如NSObject *obj1 = [NSObject new];, obj1這個指針變量是分配在棧上的, 他指向的是這一個分配在堆上面的實例對象, 如果進行下面的賦值操作NSObject *obj2 = obj1;,那么并沒有新生成一個實例對象, 只是在棧上分配了一個新的指針變量obj2, 而obj2和obj1指向的實例對象是同一個.
  • 2.關于文件頭文件的引入問題, 一般情況下不建議在A.h文件中引入其他的B.h文件, 因為在別人引入A.h的時候, 同時也引入了B.h文件, 增加不必要的文件耦合和編譯時間, 一般在.h文件中使用前向聲明@class B, 而在.m文件中才真的引入頭文件, 當然對于protocol不能使用前向聲明, 如果將protocol放在了另一個.h文件中, 那么就必須要引入這個頭文件了.
  • 3.盡量使用字面量語法來初始化字符串, 數組, 字典等, 因為字面量語法其實是一種語法糖, 使用它可以讓代碼可讀性更高, 當然對于一些必須要使用到初始化方法的時候字面量語法就不好用了.例如:
  • NSString *str = @"string";
    NSArray *arr = @[obj1, obj2];
    arr[1]// 讀取使用下標而盡量不使用對應的函數...
    [array setObject:(nonnull id) atIndexedSubscript:(NSUInteger)]
  • 4.少用#define來定義常量, 因為宏定義只是簡單的代碼替換, 并沒有類型判斷, 不便于我們閱讀判斷, 同時宏定義可以被覆蓋, 當別人引入了我們的頭文件的時候, 可能會覆蓋我們里面定義的宏, 帶來很麻煩的調試, 我們應該使用C語言風格的const,static, extern相結合來定義常量
    /// 使用static 和const 定義文件內部的常量 一般使用k開頭命名
    static float const kAnimationTime = 2.0f;
    /// 使用const定義全局的常量, 在其他文件中可以通過 extern float const kAnimationTime引入使用, 一般不用k開頭命名, 而使用class名字
    float const CustomAnimationTime = 2.0f;
  • 5.用好枚舉, 使用枚舉來表示選項, 狀態碼, 可以讓代碼更清晰, 這個在系統的API中也經常看到, 比如按鈕的狀態, autoresizing... , 例如如果你需要用一些狀態碼來表示網絡請求的結果: 你可能會有兩種方法
      1. 定義一個整形變量, 然后說明, 不同的整數代表不同的狀態, 那么這樣對于開發就很不方便, 必須得很清楚并且很正確的輸入對應的整數才能表示相應的狀態, 那么就很容易出錯, 和不便于維護int statusCode;if (statusCode == 200) { }/// 請求成功else if () ....2. 使用枚舉, 對不同的狀態定義不同的名字, 這樣就很清晰方便了, 當然定義的時候使用NS_ENUM比使用enum要`好`
    typedef NS_ENUM(NSInteger, ErrorCode) {ErrorCodeNotFind,ErrorCodeLostConnection,ErrorCodeUnknow
    };
    顯然上面你應該選用枚舉, 同時還有一種情況就是, 定義多選項, 這個你是會把他們都放進一個數組中么?? 當然不要這樣做, 這個時候也應該使用枚舉來定義, 不過會有一點的小技巧, Apple對這種進行了一個包裝, 使用NS_OPTIONS而不是enum
    typedef NS_OPTIONS(NSInteger, ErrorOptions) {ErrorOptionsNone = 0,ErrorOptionsOne = 1 << 0, ///左移操作    --- 1 --- 0001ErrorOptionsTwo = 1 << 1,               --- 2 --- 0010ErrorOptionsThree = 1 << 2              --- 4 --- 0100
    };
    因為上面定義的枚舉值都為2的整數次冪值, 所以后面就可以使用位操作符 與(&)和或(|)來進行選項的篩選
    ErrorOptions options = ErrorOptionsOne | ErrorOptionsTwo; //--- 0011if (options & ErrorOptionsOne) {// ErrorOptionsOne// 結束判斷后面}else if (options & ErrorOptionsTwo) {// ErrorOptionsTwo// ...}else {// ...}
  • 6.需要遍歷操作的時候, 盡量不要用C語言風格的for遍歷, 而是采用OC的 for-in方式的快速枚舉, 當然使用block的方式來遍歷未必不是更好的一種方式, 尤其是遍歷字典的時候.
  • 7.需要緩存的時候使用NSCache而不要使用NSArray或者NSDictionary, 因為使用NSCache來進行緩存當內存不足的時候系統會自動清理緩存, 并且會首先清理緩存時間較長的東西, 如果使用NSArray或者NSDictionary就沒有這個福利了
  • 8.不要在load方法里面執行耗時的操作, 因為這個時候會阻塞當前的線程, 如果是主線程被阻塞, 那么...就不能接受用戶的響應, 同時不要在load方法里面使用其他的類和調用函數, 因為這個時候程序是脆弱的, 有可能使用的class還沒有被加載到系統中來, 當然使用Foundation里面的NSString...這些是沒有問題的
  • 9.initialize這個方法在文檔中寫明了是在第一次使用這個類的時候才會調用一次(懶加載), 但是需要注意的是, 如果父類中實現了initialize這個方法, 而子類中沒有實現這個方法, 當初始化子類的時候, 父類的這個initialize方法是會被調用多次的(消息轉發機制), 比如
        ZJChildClass類里面沒有重寫initialize方法, 但是他的父類重寫了, 所以在初始化ZJChildClass的時候, 父類的initialize會被調用兩次, 即會打印兩條@interface ZJBaseClass : NSObject@end@implementation ZJBaseClass+ (void)initialize {NSLog(@"加載一次-----");}@end@interface ZJChildClass : ZJBaseClass@end
    所以一般都是這樣來重寫initialize方法的, 保證只會像我們期望的那樣調用一次
      + (void)initialize {if (self == [ZJBaseClass class]) { /// 不能用 [self class]NSLog(@"加載一次-----");}}
  • 10.對只需要執行一次的代碼使用dispatch_once, 這樣可以保證線程安全, 并且只執行一次, 最常見的是用來實現單例
    + (instancetype)sharedInstance {static Object *sharedInstance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{sharedInstance = [self new];});return sharedInstance;
    }
  • 11.多用GCD少用NSObject的一些performSelector等方法, 因為使用performSelector這種方式可能會造成內存泄漏, 一般情況下使用GCD都可以完成, 比如dispatch_after來實現延時后執行
  • 12.使用NSTimer的時候要特別注意內存泄漏的問題, 因為NSTimer會持有目標對象, 很容易造成循環引用的問題, 也許你會想到在這個目標對象的dealloc里面讓NSTimer失效(調用 invalidation 并且置為nil), 但是這根本就沒有用, 因為循環引用的原因, 根本就不會調用dealloc方法, 所以在里面銷毀是沒有用的, 需要在對象被銷毀之前手動銷毀計時器

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247982.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247982.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247982.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

APS系統對制造企業到底有多重要?看完這5點你就明白了

第一個問題&#xff1a;需要APS嗎&#xff1f; APS是否重要&#xff0c;不能從其所體現的軟件工具或系統角度來說&#xff0c;而應該從業務角度來說。對于制造工廠和車間的運行而言&#xff0c;計劃是核心的業務。就如同那句俗話說的&#xff0c;沒有規矩不成方圓&#xff0c;領…

Node — 第九天 (大事件項目接口實現三)

文章管理接口 設計數據表 添加文章接口 編寫接口&#xff0c;使用postman模擬提交formdata類型的數據 在article.js 中&#xff0c;加入 /add 路由 postman模擬提交formdata類型的數據 multer處理文件上傳 下載安裝multer 加載模塊 const multer require(multer) 配置上…

Python之爬蟲-段子網

Python之爬蟲-段子網 https://ishuo.cn #!/usr/bin/env python # -*- coding:utf-8 -*- import re import requestsresponse requests.get(https://ishuo.cn) data response.text print(data) r re.findall(<div class"content">(.*?)</div>,data) f…

Node — 第九天 (ES6降級 and 發布屬于自己的[第三方模塊]包)

ES6降級處理 因為 ES 6 有瀏覽器兼容性問題&#xff0c;可以使用一些工具進行降級處理&#xff0c;例如&#xff1a;babel 降級處理 babel 的使用步驟 安裝 Node.js命令行中安裝 babel配置文件 .babelrc運行命令&#xff0c;完成降級 項目初始化 (項目文件夾不能有中文) npm …

Vue — 第一天(極速入門)

基本介紹 vue是什么 目標&#xff1a;了解vue的一些基礎概念。 官方網站&#xff1a; https://cn.vuejs.org/ vue是&#xff1a;漸進式javascript框架。 兩組概念 &#xff08;1&#xff09;框架 庫。只提供一些API給開發者使用。jquery 是一個js庫框架。擁有自己的規則和…

python類和實例化

簡答介紹類和實例python是面向對象的語言&#xff0c;最主要的就是類和實例&#xff0c;類是抽象的模版創建一個類class Studen(object),class 后接類名&#xff0c;定義的類名大些字母開頭&#xff0c;object為類的繼承&#xff0c;沒有合適的繼承類用object類&#xff0c;這是…

pjsip庫分析

http://blog.chinaunix.net/space.php?uid287570&doblog&cuid728411 如果你對SIP/VoIP技術感興趣,哪希望你不要錯過:),如果你對寫出堪稱優美的Code感興趣,那么你也不可錯過:)這期間我想分析一下一個實際的協議棧的設計到實現的相關技術,算是自己的一個學習經歷記錄.最…

Vue — 第二天(v-model和過濾器)

VUE-02-v-model和過濾器 昨日反饋與回顧 代碼倉庫的問題 不要修改你克隆下來的倉庫中任意代碼&#xff0c;否則&#xff0c;下次pull時&#xff0c;可能會報錯&#xff0c;從而得到不到最新的代碼。 如果已經遇到了這個沖突&#xff1a; 解決沖突(git 中解決沖突)把關鍵代碼…

Count

題目鏈接&#xff1a;點這里 題目意思&#xff1a;令f(x)表示<x的正整數中與x互質的數的平均數*2&#xff0c;求sigma(f(i)^k),L<i<R Solution: 首先&#xff0c;我們定義\(S(x)\sum_{gcd(a,x)1}a\)&#xff0c;因為gcd(a,x)1&#xff0c;所以對于任意a&#xff0c;滿…

牛人iOS開發系列--音頻播放、錄音、視頻播放、拍照、視頻錄制

概覽 隨著移動互聯網的發展&#xff0c;如今的手機早已不是打電話、發短信那么簡單了&#xff0c;播放音樂、視頻、錄音、拍照等都是很常用的功能。在iOS中對于多媒體的支持是非常強大的&#xff0c;無論是音視頻播放、錄制&#xff0c;還是對麥克風、攝像頭的操作都提供了多套…

Vue — 第三天(計算屬性和json-server)

計算屬性 使用場景 如果一個結果需要依賴data中的數據&#xff0c;但是需要經過一些邏輯處理&#xff0c;才能得到你想要的數據。此時就可以使用計算屬性。 例如&#xff1a;要對給定的字符串做翻轉處理之后再來顯示。 <div id"app"><!-- 此處邏輯復雜 …

JQuery的ready函數與JS的onload的區別詳解

JQuery的ready函數與JS的onload的區別&#xff1a;1.執行時間window.onload必須等到頁面內包括圖片的所有元素加載完畢后才能執行。$(document).ready()是DOM結構繪制完畢后就執行&#xff0c;不必等到加載完畢。 2.編寫個數不同window.onload不能同時編寫多個&#xff0c;如果…

Vue — 第四天(components組件)

問題導入 下面的代碼是一個折疊面板的效果。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Docu…

iOS開發常用的RGB色值和宏

iOS中RGB常用的色值,同時可將對顏色的設置定義成宏,方便開發應用,如: // name 顏色相關 // 參數格式為&#xff1a;0xFFFFFF #define kColorWithRGB(rgbValue) \ [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16)) / 255.0 \ …

防火墻綜合實驗

防火墻技術綜合實驗 一、實驗目的&#xff1a;本次實驗是將多種訪問控制列表以及防火墻部分的知識做一個匯總 二、實驗內容 A&#xff1a;Established控制列表 拓撲圖 配置步驟 1:配置各端口ip地址&#xff0c;配置登陸密碼 R4: 登陸賬號&#xff1a;ys 密碼&#xff1a;123 2:…

iOS獲取當前設備型號等信息總結 包含iPhone7和iPhone7P

#include <sys/types.h> #include <sys/sysctl.h>//獲得設備型號(NSString *)getCurrentDeviceModel {int mib[2];size_t len;char *machine;mib[0] CTL_HW;mib[1] HW_MACHINE;sysctl(mib, 2, NULL, &len, NULL, 0);machine malloc(len);sysctl(mib, 2, mac…

Vue — 第五天(路由)

前端路由 問題導入 在前面完成的資產管理案例中&#xff0c; 我們是把列表區域和添加表單區域實現在了一個區域。當頁面功能比較復雜時&#xff0c;我們需要它們拆分開來&#xff1a;一個頁面中只顯示一個區域。 一個比較直觀的解決方案是把它們分別做成兩個獨立的網頁文件&…

獲取網絡時間,在不同時間觸發事件

<!DOCTYPE html><html lang"en"><head>   <meta charset"UTF-8">   <title>時間事件</title></head><body></body><script> var int_timenew Date();//使用Date獲取網絡時間;   functi…

iOS獲取手機的IP地址

1.添加這五個庫&#xff08;在聯網的情況下&#xff09; #import <sys/socket.h> #import <sys/sockio.h> #import <sys/ioctl.h> #import <net/if.h> #import <arpa/inet.h>2.寫一個方法 - (NSString *)getDeviceIPIpAddresses {int sockfd soc…

Vue — 第六天(vue-cli-介紹)

vue-cli-介紹 vue-cli是官方提供的開發vue項目的腳手架工具。 腳手架是為了保證各施工過程順利進行而搭設的工作平臺。 在開發過程中&#xff0c;腳手架工具是有用的&#xff0c;開發完成&#xff08;項目上線&#xff09;&#xff0c;它就沒有用了。 vue-cli可以提供基于vue項…