ios 基本數(shù)據(jù)類型分為以下幾種,用好數(shù)據(jù)類型能讓你一看就是個(gè)老手~
1 NSString 字符串類型(還記得NS代表啥意思了嗎?現(xiàn)在蘋果已經(jīng)在慢慢移除這個(gè)前綴啦)
2 NSInteger 整形
當(dāng)使用int類型定義變量的時(shí)候,可以像寫C程序一樣,用int也可以用NSInteger,推薦使用NSInteger ,因?yàn)檫@樣就不用考慮設(shè)備是32位還是64位了,NSInteger在64位取值范圍是[2的-63次方]到[2的63次方減一]
3 NSUInteger 無符號(hào)整形(即沒有負(fù)數(shù))
4 NSArray 固定數(shù)組
數(shù)組內(nèi)可以塞入對(duì)象類型如 nsstring或者nsnumber,如果塞入int就會(huì)崩潰哦.一旦聲明,不可再更改其內(nèi)部的值.
5 NSMutableArray 可變數(shù)組
聲明后可再更改其內(nèi)部的值.
6 NSDictionary 固定字典
字典內(nèi)可以塞入對(duì)象類型如 nsstring或者nsnumber,如果塞入int也會(huì)崩潰哦.
7 NSMutableDictionary 可變字典
聲明后可再更改其內(nèi)部的值.
8 NSNumber 數(shù)字類,能形容一切的數(shù)字類型如cgfloat,int,long,float
9 CGFloat 浮點(diǎn)型(能表示包含小數(shù)的數(shù)字類型)
讓我們先掌握以上幾種數(shù)據(jù)類型吧
10 bool 布爾類型 YES ,NO 代表是與不是
數(shù)字類型介紹:
寫程序,最多接觸的就是數(shù)字啦,掌握好數(shù)字類型讓你事半功倍!
首先ios 推薦使用nsinterger nsuinterger cgfloat 他們其實(shí)都是int unsigned int float 的包含在32位和64位下nsinterger 等oc類型表示的范圍是有區(qū)別的,但是現(xiàn)在32位的ios設(shè)備已經(jīng)被淘汰了,所以并沒有區(qū)別了.
數(shù)據(jù)類型的一個(gè)比較大的問題就是類型轉(zhuǎn)換了
CGFloat tFloat = 10/1000;
得到的結(jié)果會(huì)是0 哦,surprise mother fxker!!!
原因
計(jì)算機(jī)中的運(yùn)算有個(gè)原則:
相同數(shù)據(jù)類型的值才能進(jìn)行運(yùn)算,而且運(yùn)算結(jié)果依然是同一種數(shù)據(jù)類型。因此,整數(shù)除于整數(shù),求出來的結(jié)果依然是整數(shù),會(huì)損失小數(shù)部分。
在計(jì)算中常常會(huì)忘記這個(gè),所以做除法時(shí)務(wù)必記得這樣!!!!!!!!
CGFloat tFloat = (CGFloat)10/1000;
NSNumber 作為oc 的數(shù)字類,方便大家繼續(xù)數(shù)字相關(guān)的處理
NSNumber *num = @(10); //oc 語法糖,快速轉(zhuǎn)換int 為 nsnumber
反之
int myInt = [intNumber intValue]; //對(duì)象轉(zhuǎn)換為整型值
//[floatnumber floatValue]; //對(duì)象轉(zhuǎn)換為浮點(diǎn)
//[doublenumber doubleValue]; //對(duì)象轉(zhuǎn)換為雙精度浮點(diǎn)值
nsnumber 最需要用到的地方就是將數(shù)字塞入nsarray 或者nsdictionary
//這個(gè)是對(duì)的
NSArray*array=[[NSArray alloc]init];
[array addObject:[NSNumber numberWithInt:6]];
//這個(gè)是錯(cuò)的
NSArray*array=[[NSArray alloc]init];
[array addObject:6];//程序會(huì)無法編譯通過的
此外數(shù)字處理最敏感的貨幣部分,可以使用NSDecimalNumber,其保留精度高,數(shù)字比較,四舍五入等方便計(jì)算.務(wù)必記得使用,同時(shí)可以定義數(shù)字的輸出格式,這樣在銀行或科學(xué)方面app會(huì)有用;
// 定義你數(shù)字的輸出格式 輸出為123,456.045 只保留小數(shù)點(diǎn)后三位
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = kCFNumberFormatterDecimalStyle;
NSString *num = @"123456.0453";
NSNumber *result111 = [NSNumber numberWithDouble:num.doubleValue];
NSString *string = [formatter stringFromNumber:result111];
附上數(shù)字與其他類型轉(zhuǎn)換方式
//字符串轉(zhuǎn)int
NSInteger lNumber = [sNumber integerValue];
//int 轉(zhuǎn)字符串
NSString* sNumber = [NSString stringWithFormat:@"%ld", lNumber];
//字符串轉(zhuǎn)nsnumber
NSNumber *myNumber = [f numberFromString:@"42"];
//float 轉(zhuǎn) NSInteger
NSInteger i = (NSInteger)1.345;
字符串類型介紹:
nsstring 字符串類型操作也十分豐富,本人在定義模型中基本上都用字符串類型,數(shù)字也使用字符串表示
初始化化一個(gè)字符串的方法為
//簡單聲明 "@"表示為oc nsstring類型字符串
NSString *str = @"123";//NSString 為對(duì)象類型,所以記得加*號(hào)
//將變量轉(zhuǎn)換為字符串
NSString *string = [NSString stringWithFormat:@"%.2f",M_PI]; // %.2f表示保留小數(shù)點(diǎn)兩位
stringWithFormat 拼接時(shí)候的占位符一覽
%@ 對(duì)象 (非常常用)
%d, %i 整數(shù)
%u 無符整形
%f 浮點(diǎn)/雙字
%x, %X 二進(jìn)制整數(shù)
%o 八進(jìn)制整數(shù)
%zu size_t
%p 指針
%e 浮點(diǎn)/雙字 (科學(xué)計(jì)算)
%g 浮點(diǎn)/雙字
%s C 字符串
%.*s Pascal字符串
%c 字符
%C unichar
%lld 64位長整數(shù)(long long)
%llu 無符64位長整數(shù)
%Lf 64位雙字
%e 是實(shí)數(shù),用科學(xué)計(jì)數(shù)法計(jì)的
此外字符串的常用方法其實(shí)很多很多
//在字符串temp的基礎(chǔ)繼續(xù)添加temp 并組成一個(gè)新的字符串
NSString *str5 = [temp stringByAppendingString:temp];
//字符串以開頭比較
if([str0 hasPrefix:@"just"])
//字符串以結(jié)尾比較
if([str1 hasSuffix:@"coding"])
//字符串完全相等比較
if([str0 isEqualToString:str1]) //注意不要使用==來比較,這樣比較的是指針地址
//寫字符串到文件:writeToFile方法
NSString *astring = [[NSString alloc] initWithString:@"This is a String!"];
NSLog(@"astring:%@",astring);
NSString *path = @"astring.text";
[astring writeToFile: path atomically: YES];
字符串判斷是否為空問題
看似簡單的nsstring 也有一個(gè)容易被坑的地方,那就是字符串判空.
判斷字符串為空:看似簡單的問題,有人會(huì)說不就使用[string isEqualToString:@""]或者更簡單的string.text == nil就行了嘛。但是并沒有考慮到其中存在的一些問題,例如當(dāng)字符串中存在空格或者換行時(shí)或者當(dāng)請(qǐng)求后臺(tái)數(shù)據(jù)時(shí)得到的是進(jìn)行JSON解析的時(shí)候, 如果解析出的NSDictionary中某個(gè)key對(duì)應(yīng)的value為空, 則系統(tǒng)會(huì)把它處理為NSNull類的單例對(duì)象。這些情況下,上面的判斷方法就不會(huì)起到作用。
+ (BOOL)isEmpty:(NSString *)aStr {
if (!aStr) { //nil 當(dāng)然為空
return YES;
}
if ([aStr isKindOfClass:[NSNull class]]) { //nsnull 也為空
return YES;
}
//剔除空格和換行符
NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSString *trimmedStr = [aStr stringByTrimmingCharactersInSet:set];
if (!trimmedStr.length) {//長度為空
return YES;
}
return NO;
}
json 問題
處理字符串,自然少不了json字符串和nsarray,nsdictionary的轉(zhuǎn)換,大家copy拿走吧
//array,dictinary 轉(zhuǎn)json串
+(NSString *)objectToJson:(id)obj{
if (obj == nil) {
return nil;
}
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:obj
options:0
error:&error];
if ([jsonData length] && error == nil){
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}else{
return nil;
}
}
//nsarray,nsdictionary轉(zhuǎn)換為json字符串
+(id)jsonToObject:(NSString *)json{
//string轉(zhuǎn)data
NSData * jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];
//json解析
id obj = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
return obj;
}
小貼士: nsstring property在實(shí)踐中經(jīng)常使用copy,大家知道為什么嗎?
因?yàn)槭褂胏opy修飾之后,即使屬性拷貝來自可變字符串,也會(huì)被深拷貝成不可變字符串,也就是源字符串修改之后不會(huì)影響到屬性字符串,增強(qiáng)了代碼的健壯性。
//property nsstring 為copy 時(shí)
age = 21;
person.age = age; //age為copy
age = 22;
nslog(@"%d",person.age) //此時(shí)打印的是21,不收age的變化影響
NSString 能表示字串符,但是對(duì)于表示字符串的格式就無能為力了,之后還會(huì)在富文本章節(jié)內(nèi)介紹NSAttributedString.
NSArray 數(shù)組類型介紹
在工作中,我們經(jīng)常要做feeds流,列表展示之類的頁面.本質(zhì)上,就是對(duì)數(shù)組的顯示,所以掌握好數(shù)組真的非常重要,數(shù)組是用來儲(chǔ)存oc對(duì)象的一種數(shù)據(jù)結(jié)構(gòu),好比一節(jié)節(jié)的火車車廂,每個(gè)車廂里坐著一個(gè)oc對(duì)象,大家按照順序從頭節(jié)坐到末節(jié).(你想問這車廂具體有多少節(jié)呀,只要iphone內(nèi)存夠,這車廂就夠長!)
之前有說過數(shù)組分為NSArray和NSMutableArray,多使用不可變數(shù)組,效率更高.數(shù)組的重點(diǎn)在于查找與修改,靈活使用事半功倍,避免重復(fù)造輪子!
不可變數(shù)組常用方法
//新建一個(gè)數(shù)組
NSArray *arr1 = @[@"11",@"22",@"33"]; //語法糖聲明方法
NSArray *arr2 = [[NSArray alloc] initWithObjects:@0, @1, @2, nil];//蠢乎乎的第二種聲明方法,誰會(huì)用呢?
//獲取數(shù)組長度,為什么要用NSUInteger 你還記得嗎? 其實(shí)用int NSInteger 也是可以的,不過浪費(fèi)了變量空間的分配
NSUInteger cout = [arr1 count];
//獲取某個(gè)位置的數(shù)組,請(qǐng)做好判斷,避免訪問到不存在的下標(biāo)
id obj = arr[2]; //程序都是從0開始表示第一位的,[2]表示第三個(gè)位置
id obj = [arr1 objectAtIndex:2]; //同上一樣的效果
//判斷某個(gè)對(duì)象是否存在
BOOL result = [arr1 containsObject:@"11"];
// /取得數(shù)組的首尾元素,很好用有沒有,ios 早期版本還不支持lastObject這個(gè)方法,現(xiàn)在你處在一個(gè)好的時(shí)代.
id obj = [arr1 lastObject]; //取得數(shù)組的最后一個(gè)元素
id obj = [arr1 firstObject];// 取得數(shù)組的第一個(gè)元素
// componentsSeparatedByString,以某個(gè)字符分割字符串,返回一個(gè)數(shù)組
NSString *s = @"今天*我*休息";
NSArray *arr2 = [s1 componentsSeparatedByString:@"*"];//返回@[@"今天",@"我",@"休息"]
//將數(shù)組中元素用某個(gè)字符串拼接起來:componentsJoinedByString,返回一個(gè)字符串類型
NSArray *arr = @[@"小米",@"華為",@"聯(lián)想"].
NSString *newString = [arr componentsJoinedByString:@"*"];//返回@"小米,華為,聯(lián)想"
可變數(shù)組常用方法
//新建一個(gè)數(shù)組
NSMutableArray<NSString*> *mArr = = @[@"11",@"22",@"33"].mutableCopy; //語法糖聲明方法,聲明一個(gè)帶有初始元素的可變數(shù)組
NSMutableArray<NSString*> *mArr = [[NSMutableArray alloc] init]; //常用方法
注:<NSString*>表示數(shù)組內(nèi)都為NSString類型, 不可變數(shù)組與可變數(shù)組都可以這樣表示,在遍歷或者調(diào)用內(nèi)部元素的方法時(shí)ide能提示出對(duì)應(yīng)方法~
//添加元素
[marr addObject:@"123"];
//刪除元素
[mArr removeObject:@"123"];//當(dāng)運(yùn)用數(shù)組等的時(shí)候 運(yùn)用removeObject移除對(duì)象的時(shí)候事實(shí)上這些集合內(nèi)部是有一個(gè)判斷的;這個(gè)判斷是基于方法- (BOOL)isEqual:(id)object;的 而這個(gè)方法是判斷內(nèi)容是否相同。所以只要數(shù)組或者集合中有相同的元素,而你所要移除的對(duì)象正好在數(shù)組或者集合中有兩個(gè)或者兩個(gè)以上的時(shí)候,這些對(duì)象都將被移除!
所以如果
NSString *a = @"123";
NSString *b = @"123";
NSMutableArray *mArr = @[@"1",@"2",a,b].mutableCopy;
[mArr removeObject:b];
a和b都會(huì)被移除,
使用:
[mArr removeObjectIdenticalTo:a];//根據(jù)地址來移除元素
a和b還是都會(huì)被移除
因?yàn)?
(lldb) p a
(__NSCFConstantString *) $0 = 0x00000001027200c0 @"123"
(lldb) p b
(__NSCFConstantString *) $1 = 0x00000001027200c0 @"123"
a 和 b只要字符串內(nèi)容相同都指向同一個(gè)地址喲!!!!!!!!!!!!!
所以只移除a 或者只移除 b 需要你的思考,怎么做到呢?????
//改
mArr[1] = @"456"; //數(shù)組的第二個(gè)元素改為456 ,
[mArr setObject:@"456" atIndexedSubscript:1];//效果同上
//遍歷
[mArr enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//obj 為當(dāng)前遍歷到的對(duì)象
//idx 為遍歷的位置 從0開始哦
//stop 為是否有下一次循環(huán) 用 *stop = YES 來停止
}];
注意:
跳出循環(huán)的坑:
1 只用 *stop = YES; 表示沒有下一次循環(huán)了,這次block"全部"執(zhí)行完就結(jié)束了.
2只用 return;表示這次block就到這,進(jìn)入下一次循環(huán).
此外還有遍歷數(shù)組的刪除問題,邊循環(huán)邊刪除會(huì)出現(xiàn)遍歷跳過后一條的情況. 因?yàn)閯h除元素后,后面的元素下標(biāo)會(huì)都減一,后面的元素跑到了你刪除元素的位置,下一次遍歷就跑到了下下個(gè)元素了. 有沒有暈啊~哈哈
//使用反向遍歷來解決
- (void)enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:(void (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))block;
字典類型介紹
字典在很多語言里也叫map ,也有叫帶鍵值對(duì)的數(shù)組.叫哈希表更高端一些,是根據(jù)key來設(shè)置和訪問值的數(shù)據(jù)結(jié)構(gòu).很常用哦~
//初始化
NSDictionary *dic=@{@"name":@"aaa",@"age":@111};
//@"name" @"age" 表示key
//@"aaa" @111 表示為對(duì)應(yīng)的值
注: 字典里也是只能放對(duì)象類型 所以 放@111是可以的,111是不允許的.
nil 也不被允許 如果你塞入的變量可能為nil 用name?:@""來替代
?: 為三元運(yùn)算符
NSString *str = (b==1?@"123":@"456") 表示 b等于1 的話 str 就賦值 @"123",否則賦值@"456"
NSString *str = (b?:@"456")表示 b有值 的話 str 就賦值b,否則賦值@"456"
//分別獲取所有的鍵, 值
NSLog(@"%@",dic.allKeys);
NSLog(@"%@",dic.allValues);
//獲取字典鍵值對(duì)總數(shù)
NSLog(@"%d",(dic.count));
//字典遍歷,快速枚舉
for (id key in dic) {
id value=[dic objectForKey:key];
NSLog(@"%@:%@",key,value);
}
for (id key in dic) 為一種快速遍歷方法,適用于字典和數(shù)組,如果你只是想簡單的把內(nèi)容都取一遍,這個(gè)方法值得使用.
NSMutableDictionary 可變字典介紹
//創(chuàng)建一個(gè)nsmutabledictionary
NSMutableDictionary *mutableDictionary=[NSMutableDictionary new];
[mutableDictionary setObject:@"shenyue" forKey:@"name"];
[mutableDictionary setObject:@21 forKey:@"age"];
//得到詞典中的所有key
NSEnumerator *enumeratorkey=[mutableDictionary keyEnumerator];
for (NSObject *obj in enumeratorkey) {
NSLog(@"key為:%@",obj);
NSLog(@"通過key找到value值為:%@",[mutableDictionary objectForKey:obj]);
}
//刪除其中一個(gè)key
[mutableDictionary removeObjectForKey:@"name"];
NSLog(@"刪除name的key以后值:%@",mutableDictionary);
[mutableDictionary removeAllObjects];
NSLog(@"刪除所有以后,可變?cè)~典個(gè)數(shù)為%ld",[mutableDictionary count]);
以上為數(shù)據(jù)類型的簡單介紹,工作中最多碰到的就是這些,后面還會(huì)深入介紹其他類型.