2017-08-01 46 views
3

Cocoa中有幾個單例類,如UIApplication,NSNotificationCenter。現在,我想找到所有單身人士的課程,我有什麼建議可以快速找到他們?找到所有單身的可可類?

我正在處理一個巨大的代碼庫,我需要將系統單例對象從定製的單例中分離出來。

+0

在Xcode中,您可以按Command-Shift-O組合(字母「哦」,而不是數字零),然後搜索「共享」,你會看到一個相當有前途的開局您也可以搜索「default」和「main」,以查找其他類似單身的對象。但也許你可以詳細說明你的意思是「我需要將系統單例對象從定製的單例中分離出來」。什麼是「系統單身人士」,這是什麼「定製單身人士」?請只編輯/澄清你的問題,而不是在下面發表評論。我試圖理解你想解決什麼問題... – Rob

+0

你也可以通過按命令2來使用「符號導航器」,然後再次搜索「默認」。您需要取消選中搜索框旁邊的「僅顯示項目定義的符號」選項。然後,您可以快速瀏覽,關注那些'class'屬性。 – Rob

回答

7

Objective-C運行時hackery!有趣!

現在,在我繼續之前,我會提出免責聲明,我絕不會推薦在實際運輸代碼中放置任何類似的東西,如果這樣做,這完全不是我的錯。不過,這對於教育目的可能很有趣。

這不會是一門精確的科學,因爲語言本身沒有任何「單身人士」的實際概念。基本上,我們只是尋找具有特定贈品前綴的類方法的Objective-C類。如果我們找到其中之一,那麼我們很有可能擁有一個單身人士。

考慮到這一點:

#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 

static BOOL ClassIsSingleton(Class class) { 
    unsigned int methodCount = 0; 
    Method *methods = class_copyMethodList(object_getClass(class), &methodCount); 

    @try { 
     for (unsigned int i = 0; i < methodCount; i++) { 
      Method eachMethod = methods[i]; 

      // only consider class methods with no arguments 
      if (method_getNumberOfArguments(eachMethod) != 2) { 
       continue; 
      } 

      char *returnType = method_copyReturnType(eachMethod); 

      @try { 
       // only consider class methods that return objects 
       if (strcmp(returnType, @encode(id)) != 0) { 
        continue; 
       } 
      } 
      @finally { 
       free(returnType); 
      } 

      NSString *name = NSStringFromSelector(method_getName(methods[i])); 

      // look for class methods with telltale prefixes 
      if ([name hasPrefix:@"shared"]) { 
       return YES; 
      } else if ([name hasPrefix:@"standard"]) { 
       return YES; 
      } else if ([name hasPrefix:@"default"]) { 
       return YES; 
      } else if ([name hasPrefix:@"main"]) { 
       return YES; 
      } // feel free to add any additional prefixes here that I may have neglected 
     } 
    } 
    @finally { 
     free(methods); 
    } 

    return NO; 
} 

int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
     NSMutableArray *singletons = [NSMutableArray new]; 

     int classCount = objc_getClassList(NULL, 0); 

     Class *classes = (Class *)malloc(classCount * sizeof(Class)); 

     @try { 
      classCount = objc_getClassList(classes, classCount); 

      for (int i = 0; i < classCount; i++) { 
       Class eachClass = classes[i]; 

       if (ClassIsSingleton(eachClass)) { 
        [singletons addObject:NSStringFromClass(eachClass)]; 
       } 
      } 
     } 
     @finally { 
      free(classes); 
     } 

     NSLog(@"Singletons: %@", singletons); 
    } 
    return 0; 
} 
+1

非常聰明!怎麼樣,對於每個返回對象的類方法,調用它,檢查該對象是否是該類的一個實例。如果是,則再次調用該方法並比較兩個對象的強相等性。如果他們是一樣的,那就更好的證明你找到了一個單身人士。 – danh

+1

這似乎是一個好主意,直​​到有人引入瞭如下方法: +(NSError *)eraseTheHardDrive; :-P –

+0

您應該限制自己調用以init開頭的方法。 實際上,您可能會通過調用alloc方法兩次並比較這些方法以獲得確切的相等性,從而獲得良好的刺戳效果。不要讓對象改變以正式初始化自己。當然,有些單例不使用這種模式,但這是一個開放式問題 –