iOS開發(fā)·必會(huì)的算法操作:字符串?dāng)?shù)組排序+模型對(duì)象數(shù)組排序

傳送門:排序算法演示小DEMO

前面的話

為了給字符串?dāng)?shù)組排序,除了用C/C++的基本辦法,iOS開發(fā)者更應(yīng)該學(xué)會(huì)利用蘋果專門為NSArray 排序提供的sortedArrayUsingComparator 方法:

- (NSArray<ObjectType> *)sortedArrayUsingComparator:(NSComparator NS_NOESCAPE)cmptr NS_AVAILABLE(10_6, 4_0);

其中,需要設(shè)置一個(gè)NSComparator 參數(shù),它是一個(gè)block,查看定義如下:

typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);

這個(gè)block體返回的NSComparisonResult 是一個(gè)枚舉類型,它的定義是:

typedef NS_ENUM(NSInteger, NSComparisonResult) {NSOrderedAscending = -1L, NSOrderedSame, NSOrderedDescending};

問(wèn)題來(lái)了,怎么設(shè)置?

  • 為了設(shè)置這個(gè)NSComparator 參數(shù)的block體,你可以在設(shè)置其block體的時(shí)候,手動(dòng)返回一個(gè)NSComparisonResult 枚舉類型的某個(gè)具體值(NSOrderedAscending, NSOrderedSame, NSOrderedDescending 三選一):
image.png
  • 如果數(shù)組里面是字符串,在設(shè)置其block體的時(shí)候,你也可以利用蘋果專門為NSString 提供的字符串比較方法,獲得一個(gè)NSComparisonResult 類型,將其自動(dòng)返回。
- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)rangeOfReceiverToCompare locale:(nullable id)locale; // locale arg used to be a dictionary pre-Leopard. We now accept NSLocale. Assumes the current locale if non-nil and non-NSLocale. nil continues to mean canonical compare, which doesn't depend on user's locale choice.
image.png

這時(shí)候,就需要了解NSStringCompareOptions 的意思。但如果你搜索一下NSStringCompareOptions ,會(huì)發(fā)現(xiàn)很多文章中的翻譯或者中文解釋在誤導(dǎo),或者很難看清什么意思?例如下面這篇博客:

image.png

然后,相同的解釋文案還以訛傳訛的傳開來(lái)了,例如你看下面這個(gè)博客:

image.png

于是,筆者決定寫此本文,好好展示他們的用途。

1. 第一種:數(shù)組的字符串元素里面是基本數(shù)據(jù)類型


1.1 字符串?dāng)?shù)組排序示例

1.1.1 實(shí)驗(yàn)代碼
  • main.m
void handleSortingForIntStrArray(void){
    NSArray *originalArray = @[@"00",@"0",@"00",@"01",@"10",@"21",@"12",@"11",@"22"];
    //block比較方法,數(shù)組中可以是NSInteger,NSString(需要轉(zhuǎn)換)
    NSComparator finderSort = ^(id string1,id string2){
        if ([string1 integerValue] > [string2 integerValue]) {
            return (NSComparisonResult)NSOrderedDescending;
        }else if ([string1 integerValue] < [string2 integerValue]){
            return (NSComparisonResult)NSOrderedAscending;
        }else{
            return (NSComparisonResult)NSOrderedSame;
        }
    };
    //數(shù)組排序:
    NSArray *resultArray = [originalArray sortedArrayUsingComparator:finderSort];
    NSLog(@"第一種排序結(jié)果:%@",resultArray);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Results of handleSortingForIntArray()**********************");
        handleSortingForIntStrArray();
    }
    return 0;
}
1.1.2 運(yùn)行結(jié)果
image.png
1.1.3 實(shí)驗(yàn)結(jié)論
  • 依據(jù)數(shù)組元素的數(shù)值大小返回升序數(shù)組

1.2 NSComparator與NSComparisonResult

上面的代碼中用到了NSComparator與NSComparisonResult,在本文的“前面的話”中已經(jīng)介紹過(guò),這里重新列一下定義。

1.2.1 NSComparator
typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);
1.2.2 NSComparisonResult
typedef NS_ENUM(NSInteger, NSComparisonResult) {NSOrderedAscending = -1L, NSOrderedSame, NSOrderedDescending};

2. 第二種:數(shù)組的字符串元素里面不是基本數(shù)據(jù)類型


2.1 示例:字符串?dāng)?shù)組排序

2.1.1 實(shí)驗(yàn)代碼
  • main.m
//
//  main.m
//  SortingForArray
//
//  Created by ChenMan on 2017/12/20.
//  Copyright ? 2017年 ChenMan. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <stdio.h>

void handleSortingForStrArray(void){
       NSArray *stringsArray = [NSArray arrayWithObjects:
                             @"string b",
                             @"string A",
                             @"string a",
                             @"string \uFF41",
                             @"string a",
                             @"string A",
                             @"string c",
                             @"string d0030",
                             @"string d2",
                             @"アいろは????イウエ",
                             @"?いろは???????",
                             @"アいろは????イウエ",nil];
    
    NSLocale *currentLocale = [NSLocale currentLocale];
    NSComparator finderSortBlock = ^(id string1,id string2) {
        
        NSRange string1Range =NSMakeRange(0, [string1 length]);
        return [string1 compare:string2 options:nil range:string1Range locale:currentLocale];
    };
    
    NSArray *finderSortArray = [stringsArray sortedArrayUsingComparator:finderSortBlock];
    NSLog(@"finderSortArray: %@", finderSortArray);
    
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Results of handleSortingForStrArray()**********************");
        handleSortingForStrArray();
    }
    return 0;
}
2.1.2 運(yùn)行結(jié)果:
image.png
2.1.3 實(shí)驗(yàn)結(jié)論:

如上實(shí)驗(yàn)代碼中,有這樣一行代碼:

return [string1 compare:string2 options:nil range:string1Range locale:currentLocale];

根據(jù)運(yùn)行結(jié)果,可知如下結(jié)論:

  • 即使在- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)rangeOfReceiverToCompare locale:(nullable id)locale;中將(NSStringCompareOptions)枚舉類型的參數(shù)設(shè)置為nil,也可以運(yùn)行。但一般不這么做,這里只是為了觀察不指定該枚舉參數(shù)時(shí)候系統(tǒng)的默認(rèn)設(shè)置,并與本文接下來(lái)指定該枚舉參數(shù)的排序結(jié)果對(duì)比。
  • 可以發(fā)現(xiàn):
    • 默認(rèn)同一字符的全角字符看做半角字符。不區(qū)分同一個(gè)字符(如日文的片假字)的半角與全角狀態(tài)。相同元素,維持原序。
    • 默認(rèn)區(qū)分字母大小寫,同一個(gè)字符小寫在前,大寫在后。
    • 字母并非按unicode碼的大小升序排列。例如,全角a的unicode為FF41,半角a的unicode為0061,半角A的unicode為0041,半角b的unicode為0062,但排序結(jié)果是 全角a = 半角a < 半角A < 半角b。
    • 默認(rèn)不識(shí)別含有數(shù)字字符的數(shù)值大小,0030雖然數(shù)學(xué)意義比2大,但是,僅從字符串的角度看,第一個(gè)字符0比2小,所以d0030排在d2前面。
2.1.4 知識(shí)拓展:

半角與全角字符

  • 全角占兩個(gè)字節(jié),半角占一個(gè)字節(jié)。通常我們碰到的英文字母、數(shù)字鍵、符號(hào)鍵這種ASCII碼系統(tǒng)里面的字符大多數(shù)情況下是半角的。

  • 國(guó)內(nèi)漢字輸入法輸入的漢字為全角,字母數(shù)字為半角,但是標(biāo)點(diǎn)則默認(rèn)為全角,可切換為半角(可以通過(guò)輸入法工具條上的相應(yīng)按鈕來(lái)切換標(biāo)點(diǎn)符號(hào)的全角半角狀態(tài))。

  • 日文里面的有漢字,也有片假字。這個(gè)片假字有兩套編碼,同一個(gè)片假字分別有半角和全角兩種編碼。例如:看起來(lái)像一樣的片假字組成的句子,全角狀態(tài)字符開頭的為アいろは????イウエ,半角狀態(tài)?字符開頭的為?いろは?????????梢钥吹?,明顯同一個(gè)片假字的全角狀態(tài)半角狀態(tài) “胖”一圈。

  • 英文字母其實(shí)也有全角字母,例如小寫的a,其半角形式的unicode碼為0061,其全角形式的unicode碼為FF41??刹殚?a target="_blank" rel="nofollow">Unicode?字符百科官網(wǎng)。

2.2 NSStringCompareOptions

NSStringCompareOptions是一個(gè)枚舉類型,并非一個(gè)類。打開NSStringCompareOptions的定義,可查看如下

typedef NS_OPTIONS(NSUInteger, NSStringCompareOptions) {
    NSCaseInsensitiveSearch = 1,
    NSLiteralSearch = 2,        /* Exact character-by-character equivalence */
    NSBackwardsSearch = 4,      /* Search from end of source string */
    NSAnchoredSearch = 8,       /* Search is limited to start (or end, if NSBackwardsSearch) of source string */
    NSNumericSearch = 64,       /* Added in 10.2; Numbers within strings are compared using numeric value, that is, Foo2.txt < Foo7.txt < Foo25.txt; only applies to compare methods, not find */
    NSDiacriticInsensitiveSearch API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)) = 128, /* If specified, ignores diacritics (o-umlaut == o) */
    NSWidthInsensitiveSearch API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)) = 256, /* If specified, ignores width differences ('a' == UFF41) */
    NSForcedOrderingSearch API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)) = 512, /* If specified, comparisons are forced to return either NSOrderedAscending or NSOrderedDescending if the strings are equivalent but not strictly equal, for stability when sorting (e.g. "aaa" > "AAA" with NSCaseInsensitiveSearch specified) */
    NSRegularExpressionSearch API_AVAILABLE(macos(10.7), ios(3.2), watchos(2.0), tvos(9.0)) = 1024    /* Applies to rangeOfString:..., stringByReplacingOccurrencesOfString:..., and replaceOccurrencesOfString:... methods only; the search string is treated as an ICU-compatible regular expression; if set, no other options can apply except NSCaseInsensitiveSearch and NSAnchoredSearch */
};
2.2.1 NSNumericSearch

官方解釋:Added in 10.2; Numbers within strings are compared using numeric value, that is, Foo2.txt < Foo7.txt < Foo25.txt; only applies to compare methods, not find

  • 假設(shè),將上例中的部分代碼修改為
void handleSortingForStrArray(void){
    NSArray *stringsArray = [NSArray arrayWithObjects:
                             @"string b",
                             @"string A",
                             @"string a",
                             @"string \uFF41",
                             @"string a",
                             @"string A",
                             @"string c",
                             @"string d0030",
                             @"string d2",
                             @"アいろは????イウエ",
                             @"?いろは???????",
                             @"アいろは????イウエ",nil];
    NSStringCompareOptions comparisonOptions = NSNumericSearch;
    NSLocale *currentLocale = [NSLocale currentLocale];
    NSComparator finderSortBlock = ^(id string1,id string2) {
        
        NSRange string1Range =NSMakeRange(0, [string1 length]);
        return [string1 compare:string2 options:comparisonOptions range:string1Range locale:currentLocale];
    };
    
    NSArray *finderSortArray = [stringsArray sortedArrayUsingComparator:finderSortBlock];
    NSLog(@"finderSortArray: %@", finderSortArray);
}
  • 運(yùn)行結(jié)果
image.png
  • 結(jié)論
    NSStringCompareOptions指定為NSNumericSearch,當(dāng)字符串中含有數(shù)字時(shí),從數(shù)值大小的角度按升序排序。
2.2.2 NSCaseInsensitiveSearch

官方解釋:無(wú)。英文字面解釋:不區(qū)分字母大小寫。

  • 假設(shè),將上例中的部分代碼修改為
NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch; 
  • 運(yùn)行結(jié)果
image.png
  • 結(jié)論
    NSStringCompareOptions指定為NSCaseInsensitiveSearch,不區(qū)分同一個(gè)字母的大小寫狀態(tài),如aA看做相同元素,若其它條件也一致則保持原序。
2.2.3 NSLiteralSearch

官方解釋:Exact character-by-character equivalence

  • 假設(shè),將上例中的部分代碼修改為
NSStringCompareOptions comparisonOptions = NSLiteralSearch;
  • 運(yùn)行結(jié)果
image.png
  • 結(jié)論
    • 區(qū)分 同一個(gè)字符(如日文的片假字)的半角與全角狀態(tài),同一片假字的全角狀態(tài)小于半角狀態(tài)。
    • 其它規(guī)則,繼續(xù)按系統(tǒng)默認(rèn)排序規(guī)則排序,包括默認(rèn)區(qū)分 字母大小寫,以及其它默認(rèn)排序規(guī)則。
    • 按照官方英文說(shuō)明,這個(gè)規(guī)則是指區(qū)分每個(gè)字符的等效狀態(tài)。只要unicode不同的字符,就不認(rèn)可他們“等效”,即使他們的語(yǔ)言上的含義相同。
  • 題外話
    • 所以,有的文獻(xiàn)說(shuō)NSLiteralSearch 是區(qū)分大小寫是誤導(dǎo),系統(tǒng)本就默認(rèn)區(qū)分 字母大小寫,這些人以為蘋果公司提供這個(gè)功能來(lái)畫蛇添足干嘛?而且可以看看官方英文說(shuō)明,也不是這個(gè)意思。只有指定不區(qū)分 字母大小寫的NSCaseInsensitiveSearch,要么不寫,即默認(rèn)區(qū)分
2.2.4 NSWidthInsensitiveSearch

官方解釋:If specified, ignores width differences ('a' == UFF41)

  • 假設(shè),將上例中的部分代碼修改為
NSStringCompareOptions comparisonOptions = NSWidthInsensitiveSearch;
  • 運(yùn)行結(jié)果
image.png
  • 結(jié)論
    • 不區(qū)分 同一個(gè)字符(如日文的片假字)的半角與全角狀態(tài),同一片假字的全角狀態(tài)等于半角狀態(tài)。
    • 其它規(guī)則,繼續(xù)按系統(tǒng)默認(rèn)排序規(guī)則排序,包括默認(rèn)區(qū)分 字母大小寫,以及其它默認(rèn)排序規(guī)則。
    • 同時(shí)指定兩個(gè)時(shí),NSWidthInsensitiveSearchNSLiteralSearch 的優(yōu)先級(jí)高,綜合起來(lái)的結(jié)果是不區(qū)分 半角全角。
    • 官方英文說(shuō)明中的UFF41是指全角a,'a' 是指半角a,如果指定NSWidthInsensitiveSearch,則不區(qū)分字符的全角半角,即使你同時(shí)指定了NSLiteralSearch。

即,當(dāng)有如下代碼

NSStringCompareOptions comparisonOptions = NSWidthInsensitiveSearch | NSLiteralSearch;

其作用相當(dāng)于沒有NSLiteralSearch的代碼

NSStringCompareOptions comparisonOptions = NSWidthInsensitiveSearch;
2.2.5 NSForcedOrderingSearch

官方解釋:If specified, comparisons are forced to return either NSOrderedAscending or NSOrderedDescending if the strings are equivalent but not strictly equal, for stability when sorting (e.g. "aaa" > "AAA" with NSCaseInsensitiveSearch specified)

  • 假設(shè),將上例中的部分代碼修改為
NSStringCompareOptions comparisonOptions = NSForcedOrderingSearch;
  • 運(yùn)行結(jié)果
image.png
  • 結(jié)論
    • 不存在字符等不等效相不相等的概念了,只要unicode不一樣的字符,必須區(qū)分,必須返回一個(gè)誰(shuí)大誰(shuí)小的結(jié)果(NSOrderedAscending or NSOrderedDescending)。
    • 從英文說(shuō)明也可以看出,NSForcedOrderingSearch 的優(yōu)先級(jí)最高,即如果你同時(shí)指定了其它有可能作用沖突的枚舉類型,也以NSForcedOrderingSearch 的作用為準(zhǔn)。
2.2.6 綜合應(yīng)用
  • 一個(gè)比較多的應(yīng)用示例是,區(qū)分字母大小寫,區(qū)分?jǐn)?shù)值大小,區(qū)分半角全角,并強(qiáng)制性指定區(qū)分unicode不一樣的字符。綜合這些條件,寫起來(lái)就是:
NSStringCompareOptions comparisonOptions = NSNumericSearch|NSWidthInsensitiveSearch|NSForcedOrderingSearch;
  • 運(yùn)行結(jié)果
image.png
2.2.7 誤導(dǎo)用法
  • 我看過(guò)有很多其它博客用了這樣的誤導(dǎo)示例:
NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch|NSNumericSearch|NSWidthInsensitiveSearch|NSForcedOrderingSearch;

這里面,NSCaseInsensitiveSearch是為了不區(qū)分大小寫字母,但是后面再加個(gè)NSForcedOrderingSearch想強(qiáng)制區(qū)分字符又是怎么回事?雖然,這樣寫并不會(huì)報(bào)錯(cuò),運(yùn)行效果跟上面的綜合示例一摸一樣。但這樣誤導(dǎo)的想法是個(gè)邏輯矛盾。不信,你看看它運(yùn)行的結(jié)果:

image.png

3. 數(shù)組里面是類的對(duì)象


需求:假設(shè)我們根據(jù)后臺(tái)返回的JSON字典數(shù)組用MJExtension轉(zhuǎn)換成模型數(shù)組,現(xiàn)在我們需要根據(jù)ID或者Age對(duì)模型數(shù)組進(jìn)行排序。

  • Pesson.m
#import <Foundation/Foundation.h>  
  
@interface Person : NSObject  
@property (nonatomic,copy) NSString *ID;  
@property (nonatomic,copy) NSString *name;  
@property (nonatomic,assign) int age;  
@end  
  • 根據(jù)int類型的屬性對(duì)模型數(shù)組進(jìn)行排序
NSArray *sortArrayByAgeInt = [self.dataArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {  
      
    Person *pModel1 = obj1;  
    Person *pModel2 = obj2;  
    
    if (pModel1.age > pModel2.age) { 
        return NSOrderedDescending;//降序  
    }else if (pModel1.name < pModel2.name){  
        return NSOrderedAscending;//升序  
    }else {  
        return NSOrderedSame;//相等  
    }  
      
}];
  • 根據(jù)str類型的屬性對(duì)模型數(shù)組進(jìn)行排序
NSArray *sortArrayByIDStr = [self.dataArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {  
      
    Person *pModel1 = obj1;  
    Person *pModel2 = obj2;  
    
    if ([pModel1.ID intValue]> [pModel2.ID intValue]) { 
        return NSOrderedDescending;//降序  
    }else if (pModel1.name < pModel2.name){  
        return NSOrderedAscending;//升序  
    }else {  
        return NSOrderedSame;//相等  
    }  
      
}];

4. 花樣玩法:例題


在OC的高級(jí)用法中,經(jīng)常需要查看系統(tǒng)類或者某個(gè)自定義類中的私有屬性以及私有成員變量,并通過(guò)KVC的辦法強(qiáng)制修改這些私有成員變量的值,以取代系統(tǒng)或者自定義類中的默認(rèn)設(shè)置。所以,如果你懶得創(chuàng)建一些假數(shù)據(jù)的數(shù)組,可以想到運(yùn)用運(yùn)行時(shí)的辦法獲取成員變量的數(shù)組,并進(jìn)行排序操作訓(xùn)練。

題1. 請(qǐng)取出NSString類的全部公有 屬性 并存放到一個(gè)數(shù)組,并利用NSArraysortedArrayUsingComparator的方法給這個(gè)數(shù)組進(jìn)行升序排序操作。要求:排序過(guò)程中需要區(qū)分字符全角半角狀態(tài),其它可按系統(tǒng)默認(rèn)條件。

  • 參考代碼:
    main.m
void handlePrintingOfProperties(void){
    unsigned int count;// 記錄屬性個(gè)數(shù)
    objc_property_t *properties = class_copyPropertyList([NSString class], &count);
    // 生成一個(gè)屬性名稱組成的數(shù)組
    NSMutableArray *propertyNameArray = [NSMutableArray array];
    for (int i = 0; i < count; i++) {
        // An opaque type that represents an Objective-C declared property.
        // objc_property_t 屬性類型
        objc_property_t property = properties[i];
        // 獲取屬性的名稱 C語(yǔ)言字符串
        const char *cName = property_getName(property);
        // 轉(zhuǎn)換為Objective C 字符串
        NSString *name = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
        [propertyNameArray addObject:name];
    }
    NSLog(@"排序前的屬性列表 = %@",propertyNameArray);
    
    NSComparator cmptr = ^(NSString *obj1, NSString *obj2){
        return [obj1 compare:obj2 options:NSLiteralSearch];
    };
    NSArray *afterSort = [propertyNameArray sortedArrayUsingComparator:cmptr];
    NSLog(@"排序后的屬性列表 = %@",afterSort);
    
    //C語(yǔ)言中,用完copy,create的東西之后,最好釋放
    free(properties);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"handlePrintingOfProperties()**********************");
        handlePrintingOfProperties();
    }
    return 0;
}
  • 運(yùn)行結(jié)果
image.png

題2. 請(qǐng)取出NSURL類中包括私有 在內(nèi)的全部 成員變量,并存放到一個(gè)數(shù)組,并利用NSArraysortedArrayUsingComparator的方法給這個(gè)數(shù)組進(jìn)行升序排序操作。要求:排序過(guò)程中需要區(qū)分字符全角半角狀態(tài),其它可按系統(tǒng)默認(rèn)條件。

  • 參考代碼:
void handlePrintingOfIvars(void){
    unsigned int count;// 記錄屬性個(gè)數(shù)
    Ivar *properties = class_copyIvarList([NSURL class], &count);
    // 生成一個(gè)屬性名稱組成的數(shù)組
    NSMutableArray *propertyNameArray = [NSMutableArray array];
    for (int i = 0; i < count; i++) {
        // An opaque type that represents an Objective-C declared property.
        // objc_property_t 屬性類型
        Ivar property = properties[i];
        // 獲取屬性的名稱 C語(yǔ)言字符串
        const char *cName = ivar_getName(property);
        // 轉(zhuǎn)換為Objective C 字符串
        NSString *name = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
        [propertyNameArray addObject:name];
    }
    NSLog(@"排序前的成員變量列表 = %@",propertyNameArray);
    
    NSComparator cmptr = ^(NSString *obj1, NSString *obj2){
        return [obj1 compare:obj2 options:NSLiteralSearch];
    };
    NSArray *afterSort = [propertyNameArray sortedArrayUsingComparator:cmptr];
    NSLog(@"排序后的成員變量列表 = %@",afterSort);
    
    //C語(yǔ)言中,用完copy,create的東西之后,最好釋放
    free(properties);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"handlePrintingOfIvars()**********************");
        handlePrintingOfIvars();
    }
    return 0;
}
  • 運(yùn)行結(jié)果
image.png

5. 附錄:本實(shí)驗(yàn)中創(chuàng)建工程說(shuō)明


任何能在計(jì)算機(jī)上執(zhí)行的項(xiàng)目稱之為程序,其中,有圖形化用戶界面的程序稱之為應(yīng)用 ,沒有圖形界面的程序可以是守護(hù)進(jìn)程 ,還有一種稱之為命令行工具。本文這里關(guān)注的是算法和數(shù)據(jù)結(jié)果,不關(guān)注圖形界面,所以新建一個(gè)命令行工具即可。創(chuàng)建方法:新建一個(gè)macOS工程,選擇Command Line Tool類型,點(diǎn)擊下一步配置工程信息即可。

創(chuàng)建一個(gè)命令行工具
工程創(chuàng)建成功
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容