這篇文章我們講講 OC
中的型別。
上一篇文章已經說了,OC是對C的擴充套件,因此可以直接使用C中的型別:
long l;
int i;
float f;
double f2;
bool isTrue;
void m;
struct {
int score;
char myId;
} student;
// ...
接下來介紹 Foundation
框架中給我們帶來的新的型別:
布林型 BOOL
注意大小寫,這不是C中的 bool
,不知道這個型別的定義是否是多此一舉。
它有 YES
和 NO
兩個值,顧名思義。我們知道,C中定義真假,無非是0或非0,並且它可以喝數值相互轉換,但 BOOL
顯然不行。
記憶體中, YES
和 NO
是八位的,值如下:
YES:00000001
NO :00000000
當使用 BOOL
與數值比較時,只有數值的低位會參與比較,從而得出不準確的結果,所以千萬不要這麼做。下面上一段官方的example:
#import <Foundation/Foundation.h>
BOOL areIntsDifferent(int thing1,int thing2)
{
if(thing1==thing2)
{
return NO;
}
else {
return YES;
}
}
NSString *boolString(BOOL yesNo)
{
if(yesNo == NO)
{
return @"NO";
}
else {
return @"YES";
}
}
int main(int argc, const char * argv[])
{
BOOL areTheyDifferent;
areTheyDifferent = areIntsDifferent(5, 5);
NSLog(@"Are %d and %d different? %@",5,5,boolString(areTheyDifferent));
areTheyDifferent = areIntsDifferent(23,42);
NSLog(@"Are %d and %d different? %@",23,42,boolString(areTheyDifferent));
return 0;
}
字串 NSString
為區別於 C 中的 string
字串, NSString
字串會在 雙引號前加 @
,前文中我們已經看到了。
類 NSString
本身就提供了很多有用的方法,我們看程式碼:
//...
NSString *string1 = [[NSString alloc] init]; // 構造空字串
NSString *string2 = [[NSString alloc] initWithString:@"This is a String!"]; // 構造字串
NSString *string3 = @"This is also a String!";
string1 = @"This is the first String!";
// 常量字串,這個最簡單。
/* 將C中的string型別賦過來 */
char *Cstring = "This is a String!";
NSString *cString = [[NSString alloc] initWithCString:Cstring];
NSLog(@"astring:%@,%@",string1,string2);
[astring release];
//...
建立格式化字串:
NSString *stringFormat = [[NSString alloc]initWithFormat:@"This is a formated string ,number %i",1];
NSLog(@"Format:%@",stringFormat);
對了,EcmaScript 6 已經引進了跨行字串以及格式化字串,有興趣的同學可以谷歌一下!
比較字串:
NSString *string01 = @"This is a String!";
NSString *string02 = @"This is a String!";
NSString *astring01 = @"This is a String!";
NSString *astring02 = @"this is a String!";
/* 判斷兩者內容是否相同,下面兩種方法都可以: */
BOOL isEqual = [string01 isEqualToString:string02]; // YES
BOOL compare1 = [string01 compare:string02] == NSOrderedSame;
/* NSOrderedAscending判斷兩物件值的大小:按字母順序進行比較,astring02大於astring01為YES */
BOOL compare2 = [astring01 compare:astring02] == NSOrderedAscending;
/* NSOrderedDescending判斷兩物件值的大小:按字母順序進行比較,astring02小於astring01為真 */
BOOL result = [astring01 compare:astring02] == NSOrderedDescending;
查詢字串某處是否包含其他字串:
NSString *string1 = @"This is a string";
NSString *string2 = @"is a";
NSRange range = [string1 rangeOfString:string2];
/*
NSRange 型別實際上是一個C的結構體,不要被這個不明覺厲的東東嚇到
struct {
int location;
int length;
} NSRange;
*/
int location = range.location;
// 包含字串所在的起始位置,這裡的值為5,如不存在,為-1
int leight = range.length;
// 長度,這裡的值為4,如不存在,為0
擷取字串:
NSString *string0 = @"This is a string";
// 1.從字串的開頭一直擷取到指定的位置,但不包括該位置的字元
NSString *string1 = [string0 substringToIndex:3];
NSLog(@"string1:%@",string1); // string1:Thi
// 2.以指定位置開始(包括指定位置的字元),幷包括之後的全部字元
NSString *string2 = [string0 substringFromIndex:3];
NSLog(@"string2:%@",string2); // string2:s is a string
// 3.按照所給出的位置,長度,任意地從字串中擷取子串
NSString *string3 = [string0 substringWithRange:NSMakeRange(0, 4)];
/* NSMakeRange 顧名思義,建立一個NSRange型別的結構體 */
NSLog(@"string3:%@",string3); // string3:This
插入字串
OC這種靜態語言,中的很多引用型別(這麼說合適麼?)的 記憶體空間都是固定的、記憶體空間都是固定的、記憶體空間都是固定的,對於習慣了 js 和 python 的程式設計師們,重要的事情說三遍!
所以嘞,什麼NSString型別啊,以及我們後面要講的NSArray、NSSet這類東西長度都是固定的。當然OC也提供了長度可變的相應型別,後者一般是前者的子集,例如:NSMutableString
NSMutableArray
。想要修改字串,就要用到這種型別。
NSMutableString *string1 = [[NSMutableString alloc] initWithString:@"This is a NSMutableString"];
// 1. 把一個字串接在另一個字串的末尾
[string1 appendString:@", I will be adding some character"];
[string1 appendFormat:[NSString stringWithFormat:@",%i",100]];
NSLog(@"string1:%@",string1);
// 2. 在指定位置插入字串
[string1 insertString:@"Hi! " atIndex:0];
// 3. 替換原有內容
NSMutableString *setString1 = [string1 setString:@"Hello World!"];
// 4.用指定字串替換字串中某指定位置、長度的字串
[string1 replaceCharactersInRange:NSMakeRange(0, 4) withString:@"That"]; // That is a NSMutableString
// 5.檢查字串是否以另一個字串開頭或結尾
NSString *fileName = @"NSStringInformation.txt";
[fileName hasPrefix:@"NSString"] = = 1 ? NSLog(@"YES") : NSLog(@"NO");
[fileName hasSuffix:@".txt"] = = 1 ? NSLog(@"YES") : NSLog(@"NO");
數值型別 NSNumber
它實際上是一種數值物件,但我們一般仍然使用C語言中的數值型別。下面程式碼僅簡單演示一下用法:
NSNumber *number = [NSNumber numberWithInt:123]; // 建立一個整型值
// 或使用構造方法 [[NSNumber alloc] initWithInt:123]
NSLog(@"%i",[number intValue]);
// 或 NSLog(@"%@",number);
/*
還有:
[NSNumber numberWithBool];
... numberWithChar
... numberWithFloat
... stringValue
... isEqualToNumber:(NSNumber *) aNSNumberVariable
*/
陣列: NSArray
和 NSMutableArray
OC中的陣列有一個好,那就是它可以儲存不同型別的變數,並且, NSArray
不能儲存基本型別(必須是引用型別——作者注:這個術語用在OC程式設計中並不嚴謹)。
如果需要將基本型別儲存在 NSArray
陣列中,上面的 NSNumber
就派上了用場。我一直覺得 NSNumber
就像 python
或 java
裡的包裝器物件,能起到類似作用的型別還有 NSValue
、 NSDate
。
另一個問題就是,不能將 nil
加入 NSArray
陣列,因為這代表陣列到此結束,如果需要加入一個空物件,請使用 NSNull
。
想要檢視
Foundation
中提供的全部型別,請點選蘋果官方文件。
還是直接程式碼演示一遍:
NSArray *arr = [NSArray arrayWithObjects:@"Sep",@"Januay",@"April",nil];
/*
由於 nil 只代表陣列結束,所以實際上陣列有三個成員。
也可以直接賦值:
NSArray *arr=@[@"Sep",@"Januay",@"April",nil];
*/
for(int i = 0;i<[arr count];i++){
NSLog(@"%@ at count %i",name,i);
}
// count 即陣列的長度,相當於 java陣列中的length
/*
我們還可以用 for ... in 語法快速遍歷陣列,
與js中的 for ... in 語法不同,OC對此進行了優化,實際上比for語法遍歷陣列的速度更快。
但後者的缺點是不能對陣列成員進行修改、刪除操作,否則編譯器將報錯。
*/
// 返回陣列指定下標的成員:
NSString *str0 = [arr objectAtIndex:0];
// 或
NSString *str0 = arr[0];
// 返回陣列個數
NSLog(@"arr count :%d", [ar count]);
// 追加成員並返回新的array物件
NSArray *arr2 = [arr arrayByAddingObject:@"August"];
NSLog(@"arr2 :%@", arr2);
// 是否包含指定物件
NSLog(@"isContains :%d", [arr containsObject:@"April"]);
// 查詢某個成員所在索引,若成員不存在則返回-1
NSLog(@"indexOfObject :%d",[arr indexOfObject:@"August"]);
// 返回第一個或最後一個元素
NSLog(@"firstObject:%@,lastObejct :%@", [arr firstObject] , [arr lastObject]);
// ...
到目前為止,所介紹的常用到的 Foundation
類依然是比較少的,我們會在後面的文章中繼續介紹。
結尾插個話:我發現 OC
中好像並沒有嚴格意義上的方法過載,我們注意到, OC
的方法名總是因為行參變化而改變,實際上就是兩個不同的方法。
本文的內容忽略了一個問題:記憶體引用計數的問題,因為前兩篇文章已經說了,OC的記憶體管理需要手動管理, java
和 python
中則不存在這個問題。我們在後面的內容中再討論吧。
參考文件: