說說iOS中的常用的關鍵字static ,class(僅限Swift關鍵字)

瘦子_or_胖子發表於2019-02-28

本文說說static在iOS中的作用包括OC和Swift,並講解常用的情況.程式碼主要以OC為主,Swift中主要描述和另外一個關鍵字class的異同

當static修飾區域性變數時

  1. 變數在記憶體中的位置: 當用static修飾區域性變數時,區域性變數的記憶體地址會從棧變為全域性區(靜態區)
  2. 作用域:只在函式內部可見,只初始化一次,所以也只有一個記憶體地址
  3. 生命週期程式結束時才釋放
- (void)viewDidLoad {
    [super viewDidLoad];
    [self tobeYoung];
    [self tobeYoung];
    [self tobeYoung];
    static int age = 20;//使用static修飾的區域性變數,在其他的函式中宣告相同變數名的變數時,是一個全新的變數
    NSLog(@"age===%d",age);
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)tobeYoung {
    static int age = 10;
    age--;
    NSLog(@"age===%d",age);
}
// 控制檯的輸出結果
2018-11-29 22:46:31.602384+0800 static[1260:222387] age===9
2018-11-29 22:46:31.602557+0800 static[1260:222387] age===8
2018-11-29 22:46:31.602672+0800 static[1260:222387] age===7
2018-11-29 22:46:31.602758+0800 static[1260:222387] age===20
//每次的輸出結果都不一樣,被static修飾的區域性變數記憶體地址只有一份,只被初始化一次,所有第二次呼叫tobeYoung方法時age沒有被重新初始化,所以是9,9--之後就是輸出8了
複製程式碼
  1. 常用情況講解:我們經常在tableViewcell複用的時候使用到static,為什麼需要在區域性變數identifier之前加上static.我們先看看常用的寫法
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
    static NSString * identifier = @"cellIdentifier";
    UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
    }
    return cell;
}
複製程式碼

tableview的這個代理方法是一個會被反覆呼叫的方法,當identifier的前面不加static修飾時,identifier這個臨時變數是儲存在棧中的,指向常量區中的@”cellIdentifier”,一旦這個代理方法執行完畢,identifier這個區域性變數就會被回收.當再次呼叫的時候又會重新生成一個區域性變數重新指向常量區的@”cellIdentifier”.,消耗記憶體.

當使用static修飾identifier時,identifier的記憶體就會被分配在全域性區(靜態區),生命週期會變成這個程式的執行時間,不會隨著代理方法呼叫完畢而銷燬,一直指向常量區的@”cellIdentifier”.當再次呼叫時不需要重新生成.節省記憶體

當static修飾全域性變數時

  1. 記憶體中的位置 :仍然是在靜態儲存區沒變,生命週期為整個程式執行期間.
  2. 作用域 :在整個宣告它的檔案中可用,在宣告他之外的檔案之外不可見
  3. 常用情況:iOS中的單例中的全域性變數會用static修飾
#import "Singleton.h"

@implementation Singleton
static Singleton * instance = nil;
+ (Singleton *)getInstance{
    if (instance == nil) {
        instance = [[Singleton alloc] init];
    }
    return instance;
}

+ (id) allocWithZone:(struct _NSZone *)zone{
    if (instance == nil) {
        instance = [super allocWithZone:zone];
        
    }
    return instance;
}
- (id) copyWithZone :(struct _NSZone*)zone{
    
    return instance;
}
@end

複製程式碼

為什麼一定要用static 來修飾變為一個靜態變數,而不是寫成一個例項變數.因為單例是程式生命週期中唯一的例項,為確保例項化的唯一.而利用類的類方法來生成,而在類方法中不可以使用例項物件的變數,只能使用屬於類的(static)類變數(一般在OC中沒有特意區分static變數和類變數的區別).而且在宣告它之外的檔案不可見.

    /**
     在其他的類中實用extern來訪問
     */
    extern Singleton * instance ;
    NSLog(@"instance====%@",instance);
    
    直接無法編譯過會直接報錯
    Undefined symbols for architecture x86_64:
  "_instance", referenced from:
      -[ViewController viewDidLoad] in ViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

複製程式碼

在Swift中static的使用(包含與關鍵字class的異同)

說道Swift中的static那就不得不說到另一個關鍵字class,在Swift中static和class都是用來描述型別作用域這一概念.兩者都可以用來修飾計算型別.都可以用來修飾方法,static修飾的方法叫做靜態方法,class修飾的是類方法.(在OC中我們不會特別的區分類方法,類變數,靜態方法,靜態變數),但是在Swift中class和static,無論是能夠修飾的範圍還是修飾後產生的效果區別都很大,不能混為一談.

  • class 和 static相同點
  1. 都可以在class中修飾方法,static修飾的叫做靜態方法,class修飾的叫做類方法.
  2. 都可以修飾class中的計算屬性
class Programmer :NSObject {
    
    static var name : String{
        return "老王"
    }
    class var nickname :String {
        return "王重陽"
    }
    class func writeTheCode() -> Void {
        print("寫程式碼")
    }
    static func fixTheBug() -> Void {
        print("修復bug")
    }
    
}
複製程式碼
  • class 和static中的不同點
  1. 首先class修飾的屬性和方法可以被子類重寫,但是static不能被重寫
    說說iOS中的常用的關鍵字static  ,class(僅限Swift關鍵字)

    class修飾的類方法被重寫時,可以使用static修飾,讓方法變成靜態方法,但它的子類就不能重寫了
    class修飾的計算屬性被重寫時,可以使用static修飾,讓其變成靜態變數,但它的子類就不能重寫了

class iOSProgrammer :Programmer{
    // 重寫計算屬性 可以使用static 來重寫,但是static 重寫後,就不能被它的子類再次重寫了
    static override var nickname: String{
        return "iOS王重陽"
    }
    // 重寫類方法時可以使用static 讓其變成靜態方法
    static override func writeTheCode() -> Void {
        print("寫程式碼")
    }
    
}
複製程式碼
  1. 其次class 和static能夠修飾的範圍不一樣,class只能在class中修飾,而static可以不僅可以作用於class中,也可以在enum,和struct中使用.
    說說iOS中的常用的關鍵字static  ,class(僅限Swift關鍵字)

    通篇有限今天暫時到此為此,如有錯誤,希望大家幫忙在評論中指出,歡迎大家來交流溝通.

相關文章