iOS開(kāi)發(fā)經(jīng)驗(yàn)(1)

目錄:
  1. 在字符串查看指定字符串
  2. UILabel自適應(yīng)
  3. 服務(wù)器數(shù)據(jù)處理
  4. copy解釋
  5. 對(duì)象及可變字典賦值取值方法
  6. nil NSNULL NULL解釋
  7. 字面量
  8. UILabel 黑線問(wèn)題
  9. nullable和nonnull
1. 在Objective-C中怎么檢查一個(gè)字符串中是否還有另外一個(gè)字符串.
  • iOS8或OS X Yosemite之后:
- (BOOL)containsString:(NSString *)str     NS_AVAILABLE(10_10, 8_0);

之前:

NSString *string = @"hello bla bla";
if ([string rangeOfString:@"bla"].location == NSNotFound) 
{
     NSLog(@"string does not contain bla");
} else { 
    NSLog(@"string contains bla!");
}
2. UILabel自適應(yīng)
  • UILabel不能設(shè)置豎直方向的排列布局,可以通過(guò)sizeToFit改變labelframe來(lái)實(shí)現(xiàn)曲線救國(guó)。
  • 適用于根據(jù)字體計(jì)算出文本單行的長(zhǎng)度和高度(寬度和高度),注意是單行,首先來(lái)看單行文本的問(wèn)題:對(duì)于單行文本來(lái)說(shuō),計(jì)算CGSize就比較簡(jiǎn)單了
CGSize size = [s.text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:10]}];
  • 多行文本的顯示:
    首先UILabelnumberOfLines設(shè)置為0,其次通過(guò)方法來(lái)計(jì)算CGSize,具體代碼如下:button.titleLabel 亦如此
NSDictionary *attribute = @{NSFontAttributeName: font};
height = [text boundingRectWithSize:CGSizeMake(width, 0) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine attributes:attribute context:nil].size.height;
  • UITextView多行文本的顯示:
    • boundingRectWithSize:options:attributes 來(lái)計(jì)算。
      嗯確實(shí),這是個(gè)利器。其本上能正確返回字體的rect。但對(duì)于UITextView 似乎使用此方法計(jì)算出來(lái)的結(jié)果比實(shí)際顯示的要小:UITextView在上下左右分別有一個(gè)8px的padding,需要將UITextView.contentSize.width減去16像素(左右的padding 2x8px)。同時(shí)返回的高度中再加上16像素(上下的padding),這樣得到的才是UITextView真正適應(yīng)內(nèi)容的高度。如代碼中
CGSizeMake(width -16.0, CGFLOAT_MAX)
return sizeToFit.height + 16.0。

UILable中則不用.

  • 通用(推薦)
CGSize sizeToFit = [textView sizeThatFits:CGSizeMake(width, MAXFLOAT)];
3.后臺(tái)數(shù)據(jù)處理
  • 系統(tǒng)請(qǐng)求方法
    接受到的數(shù)據(jù)類型為NSData類型,需要json解析,解析后整個(gè)json字符串為字典類型,里面的數(shù)據(jù)類型可以為數(shù)組,字典,NSNumber(一般數(shù)據(jù)類型?BOOL),字符串
NSDictionary *responsObj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments   error:nil];
  • AFN請(qǐng)求方法
    通過(guò)指定接受到的數(shù)據(jù)格式為 text/json,可自動(dòng)將數(shù)據(jù)解析
  • ** 通過(guò)以上兩種方法獲取數(shù)據(jù)并解析后。要對(duì)數(shù)據(jù)做容錯(cuò)處理。**
    通常我們以約定好的數(shù)據(jù)類型,定義對(duì)象去接受并使用數(shù)據(jù),但要注意,有時(shí)候后臺(tái)返回的并不是我們?cè)诳蛻舳硕x的數(shù)據(jù)類型,所以以下要做容錯(cuò)處理。
    由于數(shù)據(jù)造成app crash原因包括:獲取的對(duì)象跟我們使用的方法不一致,比如字符串對(duì)象調(diào)用了字典的方法,空對(duì)象可以調(diào)用任何方法,這是系統(tǒng)設(shè)定的,不會(huì)crash。
    所以一般判斷步驟為:首先以約定好的數(shù)據(jù)類型接受后臺(tái)數(shù)據(jù),然后判斷對(duì)象是否為空(nil,NULL),再判斷是什么類型,特別是嵌套包含的數(shù)據(jù),要一步步判斷,切勿偷懶直接用字面量方法獲取。
4. 三種方式 copy, mutableCopy, =
  • copy mutableCopy 統(tǒng)稱為copy
    共同特點(diǎn):對(duì)原對(duì)象改變,副本不改變;對(duì)副本改變,原對(duì)象不改變,互不影響。
    作用:在改變?cè)袑?duì)象的時(shí)候,不會(huì)改變新對(duì)象的值
    原因在本小段末尾解釋.

  • copy :
    創(chuàng)建的對(duì)象是不可變副本(如NSString、NSArray、NSDictionary)。
    不可變對(duì)象調(diào)用copy,原對(duì)象與副本對(duì)象地址一樣,沒(méi)有生成新對(duì)象,是淺拷貝;
    可變對(duì)象調(diào)用copy,原對(duì)象與副本對(duì)象地址不一樣,生成了新的對(duì)象,是深拷貝。

  • mutableCopy:
    創(chuàng)建的對(duì)象是可變副本也是新對(duì)象(如NSMutableString、NSMutableArray、NSMutableDictionary)。
    不論是可變不可變對(duì)象調(diào)用mutableCopy方法,都屬于深拷貝,生成一個(gè)新的對(duì)象,地址不一樣。

  • =:
    同一個(gè)對(duì)象,改變?nèi)魏我粋€(gè),它倆都隨之改變.

  • 解釋改變其中一個(gè)另一個(gè)卻不改變的原因:
    當(dāng)對(duì)象為可變的對(duì)象,調(diào)用copy或者mutableCopy都會(huì)生成新的對(duì)象;
    當(dāng)對(duì)象為不可變的時(shí)候,使用copy,不能對(duì)copy后的對(duì)象進(jìn)行操作;使用mutableCopy,生成了新的對(duì)象.

    copy&mutableCopy.png

5. setvalue 與set object 字面量
  • setObject:ForKey: 是NSMutableDictionary特有的;setValue:ForKey:是KVC的主要方法;
  • setObject:ForKey:object對(duì)象不能為nil,不然會(huì)報(bào)錯(cuò);key的參數(shù)只要是對(duì)象就可以,一般是NSString;
  • setValue:ForKey:Value值可以為nil,此時(shí)會(huì)自動(dòng)調(diào)用removeObject:forKey:方法;key的參數(shù)只能是NSString類型;
  • setValue:ForKey:是在NSObject對(duì)象中創(chuàng)建的,即所有的對(duì)象都有這個(gè)方法,可以用于任何類(方法調(diào)用者是對(duì)象的時(shí)候);
  • 注意:
    • [imageDictionary setObject:[NSNullnull] forKey:indexNumber]; [NSNull null]表示的是一個(gè)空對(duì)象,并不是nil,
    • 首先不可變字典可以調(diào)起setValue:forKey:,但不能真正的進(jìn)行操作,這取決與不可變字典不可增刪改的特性。
  • setValue:forKey:setValue:forKeyPath:
  • 動(dòng)態(tài)設(shè)置: setValue:屬性值 forKey:屬性名(用于簡(jiǎn)單路徑)、setValue:屬性值 forKeyPath:屬性路徑(用于復(fù)合路徑,例如Person有一個(gè)Account類型的屬性,那么person.account就是一個(gè)復(fù)合屬性)
  • 動(dòng)態(tài)讀取: valueForKey:屬性名 、valueForKeyPath:屬性名(用于復(fù)合路徑)
Amodel *modelA = [[Amodel alloc]init];
    SubAmodel *modela = [[SubAmodel alloc]init];
    modela.str = @"qq.com";
    modelA.submodel = modela;
    NSLog(@"%@",modelA.submodel.str);
    [modelA setValue:@"QQ.com" forKeyPath:@"submodel.str"];
    NSLog(@"%@",modelA.submodel.str);
  • 建議在 NSDictionary 下只用 objectForKey: 來(lái)取值。
6. NSNull NULL nil
  • nil:指向oc中對(duì)象的空指針,針對(duì)對(duì)象。指針為空,不會(huì)發(fā)送消息的;return NO
    Nil:指向oc中類的空指針,針對(duì)類。
    NULL:指向其他類型的空指針,如一個(gè)c類型的內(nèi)存指針,基本數(shù)據(jù)類型為空,基本類型。
    null,占位空對(duì)象,即野指針,指向垃圾內(nèi)存,造成crash。拋出異常NSException
    NSNull:類名,它的實(shí)例就是null,空值對(duì)象。
        NSArray *arr1 = [NSNull null];
        NSArray * arr2 = nil;
        NSLog(@"%@", arr1);  <null>
        NSLog(@"%@", arr2);  (null)
        NSLog(@"%p", arr1);   0x10cf4bd80
        NSLog(@"%p", arr2);   0x0
    if ([arr1 isKindOfClass:[NSArray class]]) {
    }
    if (arr1 == NULL) {
    }
    if (arr1 == nil) {
    }
    if ([arr1 isKindOfClass:[NSNull class]]) {
    //arr1 只走這個(gè)+1
    }
        if ([arr2 isKindOfClass:[NSArray class]]) {
        }
        
        if (arr2 == NULL) {
        //arr2 走這個(gè)+1

        }
        if (arr2 == nil) {
        //arr2 走這個(gè)+2
        }
        if ([arr2 isKindOfClass:[NSNull class]]) {
        }
        [arr1 count]; //會(huì)crash。
        [arr2 count];//不會(huì)crash。
  • 僵尸對(duì)象:被釋放的對(duì)象為僵尸對(duì)象, 已經(jīng)被銷毀的對(duì)象(不能再使用的對(duì)象).
    野指針: 指向僵尸對(duì)象(不可用內(nèi)存)的指針 給野指針發(fā)消息會(huì)報(bào)EXC_BAD_ACCESS錯(cuò)誤
    空指針: 沒(méi)有指向存儲(chǔ)空間的指針(里面存的是nil, 也就是0) 給空指針發(fā)消息是沒(méi)有任何反應(yīng)的,空指針是把指針為nil.
    為了避免野指針錯(cuò)誤的常見(jiàn)辦法: 在對(duì)象被銷毀之后, 將指向?qū)ο蟮闹羔樧優(yōu)榭罩羔?br> 接受null數(shù)據(jù)并打印并不會(huì)造成crash,造成crash的原因是發(fā)送消息
  • 服務(wù)器返回的數(shù)據(jù),有null,還有niliOS是使用的OC語(yǔ)言, 跟C語(yǔ)言略有不同, 在OC中打印出(nill)<null>兩種情況是不同的, <null>的判斷方法是
 - (id) setNoNull:(id)aValue{
    if (aValue == nil) {
        aValue = @"";//為null時(shí),直接賦空
    } else if ((NSNull *)aValue == [NSNull null]) {
        aValue = @"";
        if ([aValue isEqual:nil]) {
            aValue = @"";
        }
    }
    return aValue;
}

既然它老出bug ,為什么還在oc里還有它的存在
NSNullnil以及NULL不同,因?yàn)樗且粋€(gè)實(shí)際的對(duì)象,而不是一個(gè)零值。
nil null 其實(shí)就是0
NSNullFoundation和其它框架中被廣泛的使用,以解決如NSArrayNSDictionary之類的集合不能有nil值的缺陷。
你可以將NSNull理解為有效的將NULL或者nil值封裝boxing,以達(dá)到在集合中使用它們的目的:

NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionary];
mutableDictionary[@"someKey"] = [NSNull null]; // Sets value of NSNull singleton for `someKey`
NSLog(@"Keys: %@", [mutableDictionary allKeys]); // @[@"someKey"]
7. 字面量
  • 字面數(shù)值
    需要把整數(shù)、浮點(diǎn)數(shù)、布爾值封入到對(duì)象里。通常情況下會(huì)用到如下方法:
    NSNumber *number = [NSNumber numberWithInt:8];
    使用字面量語(yǔ)法后,不僅語(yǔ)法更簡(jiǎn)潔,還有很多好處。
    NSNumber *number = @(8);
    能夠用以NSNumber實(shí)例表示的所有數(shù)據(jù)類型,都可以使用字面量語(yǔ)法。。。
  • 字面量數(shù)組
    數(shù)組的常用創(chuàng)建方法如下:
NSArray *array = [NSArray arrayWithObjects:@"obj1", @"obj2", nil];

而使用字面量語(yǔ)法則是:

NSArray *array = @[@"obj1", @"obj2"];

數(shù)組的取下標(biāo)也有字面量語(yǔ)法:
NSString *obj = [array objectAtIndex:1];
使用字面量:
NSString *obj = array[1];
不過(guò)使用字面量數(shù)組時(shí),要注意不要把nil加入到數(shù)組中,否則會(huì)拋出異常。

  • 字面量字典
    常用創(chuàng)建方式如下:
    NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"obj1", @"value1", @"obj2", @"value2", nil];
    而使用字面量語(yǔ)法,就比較簡(jiǎn)潔了。
    NSDictionary *dictionary = @{@"obj1": @"value1",
    @"obj1": @"value1"};
    字面量語(yǔ)法清晰表示出了,key和value的一一對(duì)應(yīng)關(guān)系。但是與數(shù)組一樣,字面量字典的value不能為nil,否則會(huì)出現(xiàn)異常。

  • 字面量可變數(shù)組與字典
    對(duì)于可變的數(shù)組與字典,同樣可以使用自變量語(yǔ)法對(duì)自變量數(shù)組,字典進(jìn)行操作。
    NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:@{@"obj1": @"value1", @"obj1": @"value1"}];mutableDictionary[@"obj3"] = @"value3";

  • ** 注意用字面量語(yǔ)法創(chuàng)建數(shù)組及字典時(shí)要注意,若數(shù)組元素對(duì)象中有nil,則會(huì)拋出異常**
    使用字面量語(yǔ)法創(chuàng)建出來(lái)的字符串、數(shù)組、字典對(duì)象都是不可變的(immutable)。若想要可變版本的對(duì)象,則需復(fù)制一份:

NSMutableArray *mutableArray = [@[@1, @2, @3, @4, @5]mutableCopy];
mutableArray[3] = @33;
NSMutableDictionary* mutableDic = [@{@"name":@"song",
                                 @"age":@"28",
                                  @"tel":@"1234567"}mutableCopy];
mutableDic[@"age"]=@"30";
  • 總結(jié)
  1. Foundation框架 是在iOS開(kāi)發(fā)中 用到的最頻繁的基礎(chǔ)框架,它提供了幾個(gè)最基本的類:NSString、NSNumberNSArray、NSDictionary. 在這個(gè)框架下,盡量使用對(duì)象字面量語(yǔ)法創(chuàng)建字符串, 數(shù)字, 數(shù)組和字典等.其他自定義的對(duì)象不可使用字面量。
  2. 在數(shù)組和字典中, 要使用關(guān)鍵字和索引做下標(biāo)來(lái)獲取數(shù)據(jù)
  3. 使用對(duì)象字面量語(yǔ)法時(shí), 容器類里不可是nil, 否則運(yùn)行時(shí)貴拋出異常.
8. UILabel 黑線問(wèn)題

偶爾發(fā)現(xiàn)UILabel右邊緣出現(xiàn)黑線,iPhone6P、6sP最為明顯:
使用循環(huán)計(jì)算label尺寸, 循環(huán)創(chuàng)建label時(shí)有可能出現(xiàn)右邊緣黑線的問(wèn)題, 且有時(shí)在iPhone5s一下機(jī)型不會(huì)出現(xiàn), 只在iPhone6以上出現(xiàn) ,這是因?yàn)橛?jì)算出得size可能的值會(huì)是30.31123323…… 這樣的數(shù)。
猜想: 而像素值顯示的時(shí)候不可能出現(xiàn)顯示半個(gè)像素的情況, 那么不足一個(gè)像素的值就會(huì)被忽略掉, 在分辨率較低的機(jī)型上不會(huì)出現(xiàn), 而分辨率較高的則不會(huì)忽略, 就出現(xiàn)了黑線。
解決方法
計(jì)算出來(lái)的UILabel尺寸,向上取整

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping ;
[paragraphStyle setLineSpacing:4];
NSDictionary *attributes = @{NSFontAttributeName:kDesFont, NSParagraphStyleAttributeName:paragraphStyle.copy};
CGSize size = [text boundingRectWithSize:CGSizeMake(cellWidth, 0) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil ].size ;
size.width = ceil(size.width);
size.height = ceil(height);
9. nullable和nonnull

Xcode 6.3新特性:Nullability Annotations,這一新特性的核心是兩個(gè)新的類型注釋:nullable和nonnull。從字面上我們可以猜到,nullable表示對(duì)象可以是NULL或nil,而nonnull表示對(duì)象不應(yīng)該為空。當(dāng)我們不遵循這一規(guī)則時(shí),編譯器就會(huì)給出警告。
事實(shí)上,在任何可以使用const關(guān)鍵字的地方都可以使用nullable和nonnull,不過(guò)這兩個(gè)關(guān)鍵字僅限于使用在指針類型上。而在方法的聲明中,我們還可以使用不帶下劃線的nullable和nonnull,如下所示:

- (nullable id)itemWithName:(NSString * nonnull)name

在屬性聲明中,也增加了兩個(gè)相應(yīng)的特性,因此上例中的items屬性可以如下聲明:

@property (nonatomic, copy, nonnull) NSArray * items;

也可以用以下這種方式:

@property (nonatomic, copy) NSArray * __nonnull items;

如果需要每個(gè)屬性或每個(gè)方法都去指定nonnull和nullable,是一件非常繁瑣的事。蘋果為了減輕我們的工作量,專門提供了兩個(gè)宏:NS_ASSUME_NONNULL_BEGIN,NS_ASSUME_NONNULL_END。在這兩個(gè)宏之間的代碼,所有簡(jiǎn)單指針對(duì)象都被假定為nonnull,因此我們只需要去指定那些nullable的指針。

NS_ASSUME_NONNULL_BEGIN

@interface TestNullabilityClass ()
@property (nonatomic, copy) NSArray * items;
- (id)itemWithName:(nullable NSString *)name;
@end

NS_ASSUME_NONNULL_END
最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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