最近在做項目的時候遇到一個挺坑的崩潰問題,是由于NSDictionary初始化時nil指針引起的崩潰。假設我們現在要初始化一個{key1 : value1, key2 : value2, key3 : value3}的NSDictionary,一般有兩種初始化方法:
1、使用標準的初始化方法:
NSDictionary *dictionary =[[NSDictionaryalloc]initWithObjectsAndKeys:value1,@"key1",value2,@"key2", value3 ,@"value3",nil];
2、使用ios6.0以后新支持的初始化方法:
NSDictionary *dictionary =@{@"key1" : value1,@"key2" : value2,@"key3" : value3};
現在我們對value1 value2 value3進行賦值,并把value2設為nil指針:
NSString *value1 =@"value1";NSString *value2 =nil;NSString *value3 =@"value3";
這時如果使用第二種初始化方法,運行程序會發現崩潰,日志如下:
DictionaryTextDemo[29390:1329578]Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[1]'
發現系統會阻止你向object[1]插入一個nil指針,查詢蘋果官方文檔得到
Discussion
This method steps through the objects andkeys arrays, creating entries in the new dictionary as it goes. AnNSInvalidArgumentException is raised if a key or value object isnil.
也就是說使用這種初始化方法的時候必須保證key跟value都不為nil,因此我們需要在初始化之前對其進行判斷,如果為nil就不加入字典。但是如果有需求讓value必須為空的時候,可以將value賦值為[NSNull null]這樣就可以成功插入字典,最后打印出來的結果是
DictionaryTextDemo[29510:1338517] dictionary : {key1 = value1;key2 = "";value3 = value3;}
另一種解決方法就是使用標準的初始化方法,即第一種初始化方法。但同時也要注意一個問題,使用
NDictionary *dictionary = [[NSDictionaryalloc]initWithObjectsAndKeys:value1,@"key1",value2,@"key2", value3 ,@"value3",nil];
如果我們把其中一個key或者value設為nil指針,那么系統會判斷為全部對象插入完成,即相當于我們初始化數組及字典時最后的nil。因此這種方法雖然能避免插入nil指針時拋出的異常,但可能會成為一個工程中很大的安全隱患,并且難以發現。所以推薦使用第二種初始化方法,并對nil指針進行必要的判斷,選擇性使用[NSNull null]來實現特點的需求。同理,使用NSArray時也應該注意這類問題。
思考:想使用?{key1:value1,key2 "",key3:value3} ?但是要判斷沒個value 不能為nil;相當麻煩。而使用,initWithObjectsAndKeys:value1;不會崩潰,但是 系統會認為是末尾的nil,造成參數不完整。調試時難以發現。
1.注意對變量初始化。
2.賦值操作時,對=號后面的對象判斷。
其實想寫個類別是想實現,對nil 校驗,nil 自動轉換為@“”;還沒想好!