以前整理在word文檔裡的,不過最近下重新整理資料,還是把這些東西放到博客裡吧,方便查找,在順帶撐撐門面
一storyboard連線問題
產生原因:將與storyboard關聯的屬性刪除了,但是storyboard中還保持之前所關聯的屬性。
解決:
1. 點擊view controller
2. 點擊這排最後一個按鈕
3. 會出現
4. 發現感歎號。點擊感歎號的左邊的x,取消關聯就不會報錯了。
解決:勾選這個
1.點擊
2.會顯示
3.選擇,表示當編輯的時候,會出出現X。
效果:
報錯原因:1.沒有實現btnClick這個方法。
解決方式一:添加這個btnClick這個方法
解決方式二:
1.點擊view controller
2.點擊這排最後一個按鈕
3.會出現
4.發現感歎號沒,和之前一樣,x了它,就哦了。
注意點;OC中冒號也算做方法名的一部分喔,記住!
報錯原因:OC語法規定:不允許直接修改某個對象的結構體屬性的成員
_btn 是個對象
frame是個結構體。
對象和結構體是不一樣的,結構體是C語言中的,裡面可以定義許多屬性,但是不能定義方法,而對象是即可以定義屬性又可以定義方法的,是典型的面向對象語法。
如何改變對象中結構體屬性的成員:
解決方法一:
// 既然不能直接修改對象中的結構體屬性成員
// 先取出結構體
CGRect frame = _btn.frame;
// 修改結構體
frame.origin.y -= 10;
// 將修改後的結構體重新賦值回去
_btn.frame = frame;
解決方法二:
// 先取出y值
CGFloat y = _btn.frame.origin.y;
// 修改y值
y -= 10;
// 重新設置_btn的y值,其他屬性和_btn保持不變
_btn.frame = CGRectMake(_btn.frame.origin.x, y, _btn.frame.size.width,_btn.frame.size.height);
報錯原因:id類型不能使用點語法
解決方式一:
// 利用get方法獲取tag值
NSInteger i = [sender tag];
解決方式二:
// 將id強轉為UIButton
UIButton *button = (UIButton *)sender;
// 就能使用點語法獲取tag,編譯器很笨的,他只會根據當前類型,去判斷是否能使用這個語法。一般強轉為對應類型,就能使用對應類型的方法了。
NSInteger i = button.tag;
解決方法:將這個選項取消勾選。
_btn.transform = CGAffineTransformMakeTranslation(0, 100);
_btn.transform = CGAffineTransformMakeScale(1.2, 1.2);
這樣操作是創建新的transform然後賦值,給按鈕的transform,第二次賦值的會把之前賦值的給覆蓋,所以會達不到想要的效果。
解決方法:
_btn.transform = CGAffineTransformMakeTranslation(0, 100);
// 在之前的transform情況下,繼續添加縮放的形變。
_btn.transform = CGAffineTransformScale(_btn.transform, 1.2, 1.2);
float i = 1.7;
// 會自動四捨五入,不保留小數
NSLog(@"%0.f",i); // 打印結果2
// 強轉類型不會四捨五入
int j = (int)i;
NSLog(@"%d",j); // 打印結果1
// int b = 2;
// int a = 4 *(b == 2? 1:2);
//NSLog(@"%d",a); 打印出4
// int a = 4 * b == 2? 1:2;
// NSLog(@"%d",a); 打印出2
// 由此得出 * 比== 優先級高,先算*,在算==
解決方法:
解決方法:
0. 點擊Preferences
1. 進入Text Editing
2. 勾選
解決辦法:User Interaction Enabled 必須勾選,否則控制器根視圖中所有子控件無法進行任何操作。
錯誤:
會報鏈接錯誤。
報錯原因,利用下劃線訪問了@package這個權限裡的東西。
被@package 修飾的成員屬性只能在同一個框架內部才允許訪問。否則會引發link erro。
@private 實例變量只能被聲明它的類訪問
@protected 實例變量能被聲明它的類和子類訪問。
@public 實例變量可以被任何類訪問。
問題原因:有時候應用程序的標示符一樣,會導致程序不能成功運行。
解決方式一:將模擬器之前的程序刪除。
解決方式二: 將模擬器還原
NSLog(@"%02d",cols);
錯誤原因:不要看到有很多元素的,就認為是數組。
這樣解析是錯誤的。
_dict = [NSArray arrayWithContentsOfFile:path];
這個pist文件是一個字典,正確的解析此plist文件。
// 2.根據文件路徑加載字典
_dict = [NSDictionary dictionaryWithContentsOfFile:path];
解決方式:
有時候我們需要禁用UITextField的雙擊出現copy paste的功能,然而UITextField本身沒有直接設置禁止用戶復制粘貼剪切操作等方法,但是可以重載canPerformAction方法來實現。
新建一個類繼承UITextField,然後實現canPerformAction方法:
只需覆蓋canPerformAction:withSender方法就可以,canPerformAction:withSender屬於UIResponder類的。
如下:
-(BOOL)canPerformAction:(SEL)actionwithSender:(id)sender {
UIMenuController*menuController = [UIMenuController sharedMenuController];
if (menuController){
[UIMenuControllersharedMenuController].menuVisible = NO;
}
returnNO;
}
原因: 1.UILabel是繼承UIView的,默認不能監聽點擊事件。UIButton是繼承UIControl能夠監聽點擊事件。
2.將UIButton添加到UILabel,他們之間的關系是UILabel是UIButton的父視圖,父視圖都不能監聽點擊事件,自然而然不會將事件傳遞給子視圖,因此UIButton也不能監聽點擊事件了。
思維指導:有些人會認為UIControl不是繼承UIView的嗎,都是繼承UIView,為什麼單獨繼承UIControl可以監聽點擊事件,繼承UIControl的父類UIView不能監聽事件了,這是因為我們一般在父類裡實現的都是一些共用的屬性和方法,而在子類中具體實現子類特有的方法。因此在UIControl實現了監聽點擊的特有方法,即繼承UIControl才能監聽點擊事件。
注意這個方法只有在內存發生警告的時候才會調用。
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
大部分成員屬性的初始化應該在viewDidLoad裡面進行。
- (void)viewDidLoad
{
[super viewDidLoad];
}
最牛解決方法:在一開始就將didReceiveMemoryWarning這個方法刪掉。刪掉不會影響程序運行。
當出現這個問題的時候,原因:沒有選擇模擬器。
解決辦法:
// 創建視圖的工廠方法
+ (UIView *)rowViewInitWithicon:(UIImage*)icon shuju:(NSString *)shuju
{
rowView *viewtext = [[NSBundlemainBundle]loadNibNamed:@"rowView" owner:nil options:nil][0];
[viewtext.btntouxiangsetBackgroundImage:icon forState:UIControlStateNormal];
viewtext.mingzilablexiao.text = shuju;
// 重點是這句
// 這是往通知中心添加一條通知指定通知名稱為 back 當觀察者self監聽到 back 通知是就調用callback
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(callback) name:@"back" object:nil];
/* 以下是報錯信息:
+[rowView callback]: unrecognizedselector sent to class 0x79d8
2013-11-26 15:31:02.581lianxirenlianxi[1266:c07] *** Terminating app due to uncaught exception'NSInvalidArgumentException', reason: '+[rowView callback]: unrecognizedselector sent to class 0x79d8'
*/
// reason: '+[rowView callback]: 看到報錯原因裡的+就想到沒有實現callback這個類方法。
// 由於self這個觀察者是在類方法中添加的,指的是一個類,所以在調用方法的時候,他會去類方法中找有沒有這個方法,不會去對象方法中找。因此我們也應該實現類方法。因此這裡的self也只能調用類方法
//由於實現的callback為對象方法 所以會報錯
// 解決方法 把callback 寫成類方法 供觀察者調用
return viewtext;
}
//callback方法
- (void)callback
{
NSLog(@"11111111111");
}
解決方法,將callback 寫成類方法供觀察者調用
//callback方法
+ (void)callback
{
NSLog(@"11111111111");
}
Xib中owner的class是用來告訴xib中的View需要調用哪個對象的方法,就填誰。比如需要調用dog類中的方法,就填dog。
注意:在連線選擇上別連錯了,
步驟一:先考慮自己是想給視圖添加控件了還是想給視圖添加事件
步驟二:添加控件就跟xib中的view連線。添加一些事件就給xib中的File’s Owner 連線。
[UIView animateWithDuration:0.5 animations:^{
CGRect tmpFrame = sender.superview.frame;
tmpFrame.origin.x = self.view.frame.size.width;
sender.superview.frame = tmpFrame;
sender.superview.alpha = 0;
} completion:^(BOOL finished) {
int index = [self.view.subviewsindexOfObject:sender.superview];
[sender.superview removeFromSuperview];
[UIView animateWithDuration:0.2 animations:^{
for (int i = index; i
{
UIView *chlid = self.view.subviews[i];
CGRect tmp = chlid.frame;
tmp.origin.y -=kViewH+1;
chlid.frame =tmp;
}
}];
// 在這判斷刪除按鈕是否允許點中,會在動畫執行完畢的時候,判斷。
_removeIteam.enabled = self.view.subviews.count>1;
}];
// 而在執行代碼塊之外,判斷刪除按鈕是否允許點中是不對的,因為動畫是在後台運行的,所以在執行動畫的時候,就已經執行完判斷語句了,而這時最後一個視圖還沒銷毀掉,因此刪除按鈕永遠不會不允許選中,也就不能在判斷刪除按鈕是否允許點中。
//_removeIteam.enabled = self.view.subviews.count>1;
刪完最後一行之後,正確的效果。
刪完最後一行之後,錯誤的效果。原因,判斷的位置放錯了。
1.出現的問題,創建xib描述的視圖時,將寬度設置為一個按鈕的寬度了,導致刪除按鈕不能點擊。
#pragma mark 添加聯系人
- (IBAction)AddPerson:(UIBarButtonItem *)sender {
NSString *imgName=[NSString stringWithFormat:@"01%d.png",arc4random_uniform(9)];
NSString *labelName = arr[arc4random_uniform(arr.count)];
RowView *rowView = [RowView rowViewWithIcon:imgName name:labelName];
UIView *lastView = [self.view.subviews lastObject];
int nextY = lastView.frame.origin.y + kSpace + kItemHW ;
// 設置rowView的位置和尺寸
CGRect cg =CGRectMake(0, nextY, kItemHW, kItemHW);
rowView.frame=cg;
[self.view addSubview:rowView];
}
錯誤原因:設置rowView的寬度為kItemHW,因此會有以上圖片的出現。
錯誤會導致刪除按鈕不能點擊,原因:父視圖的尺寸不夠,即父視圖能接收事件的尺寸只有一點點,也就導致超出父視圖尺寸的子視圖不能監聽點擊事件。還有一點需要注意,將子視圖添加到父視圖尺寸之外的位置,只要還在屏幕上就會顯示子視圖,只不過它不能接收任何事件。
解決方法:CGRect cg =CGRectMake(0, nextY,rowView.frame.size.width , kItemHW);
這樣設置就好了,因為xib裡面已經設置了rowView的尺寸了,外界不需要更改視圖的寬度了,直接獲取視圖的寬度即可。
正確效果:
注意UIToolBar中不能使用viewWithTag這個方法,獲取UIToolBar裡的子視圖。因為UIToolBar裡的子視圖都是UIBarButtonItem,而UIBarButtonItem是繼承NSObject的,因此不能使用viewWithTag獲取UIToolBar裡的子視圖,
viewWithTag:實現原理
- (UIView *)viewWithTag:(NSInteger)tag
{
// 1.如果當前tag和當前視圖tag相同,直接返回
if (self.tag == tag) return self;
// 2.如果和當前視圖tag不相同,遍歷當前視圖的所有子控件,查找對應的tag。
for (UIView *view in self.subviews) {
// 3.如果view不是UIView類或者UIView的子類直接返回nil
if (![view isKindOfClass:[UIView class]]) return nil;
if (tag == view.tag) {
// 4. 返回有相匹配的視圖
return view;
}
}
// 5.如果都沒有找到,返回nil.
return nil;
}
// 這樣定義是錯的,結構體不是對象,聲明變量是不需要加*
CGRect *frame = self.view.frame;
結構體變量正確定義:
CGRect frame = self.view.frame;
CGPoint center = self.view.center;
CGSize size = self.view.frame.size;
錯誤打印:
正確打印:
當對象被銷毀,一定會調用的方法,可以用這個方法,判斷對象在什麼時候銷毀,用這個調試。
// 工廠方法,簡化對象的實例化
+ (id)provinceWithName:(NSString *)name;
工廠方法好處:簡化對象的實例化,快速創建對象。
有些同學在創建項目的時候忘記點ARC了,導致一些成員屬性都莫名其妙的釋放了。然後出現了一系列莫名其妙的錯誤。
在滾動UITableView的時候出現野指針錯誤。
一出現這些野指針錯誤,首先應該想到某些對象被釋放了,然後發現代碼中,並沒有什麼造成對象被釋放的情況,這時候應該馬上想到很可能是非ARC弄的。下圖為怎麼查看項目是否是非ARC。
在非ARC中沒有強引用的概念,因此下圖的成員變量是沒有被強引用的。
在看看下圖,allPro數組沒有通過alloc調用,沒有調用alloc產生的對象都是自動釋放的
allPro=@[
@{
kCities:@[@"浦東",@"楊浦",@"閘北",@"闵行"],
kHeader:@"上海",
kFooter:@"上海不錯"
},
@{
kCities:@[@"海澱",@"昌平",@"天安門"],
kHeader:@"北京",
kFooter:@"北京很好"
}
];
所以在滾動的時候會出現野指針錯誤,因此需要將項目改成ARC。如下圖
兩個勾都得選中,然後一直點確認就OK了。
下圖就是數據模型中屬性用錯了策略導致,UITableViewcell重新出現到界面時,會導致數據丟失。
下面兩個方法太相似了,很容易選錯。
// 當點擊一行cell時,會調用這個方法
-(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath
// 當取消選擇一行cell時,會調用這個方法
- (void)tableView:(UITableView *)tableViewdidDeselectRowAtIndexPath:(NSIndexPath *)indexPath
當把一個字符串轉換成基本數據類型時,字符串打印有值,但是轉換成基本數據類型為0時,這個莫名其妙的問題,首先應該想到字符串中很可能有換行符合等,導致轉換不成功。
NSString *str = @"123";
NSInteger i = [str integerValue];
NSLog(@"%@",str);
NSLog(@"%d",i);
碰到這種情況,可以在打印字符串的時候在占位符兩邊各加一個數字.
NSLog(@"1%@1",str);
然後看打印結果就能知道有字符串中有多少空行了
只要將空行去掉就能轉換成功了。
字符串去掉空格的方法
// 此方法是通過什麼字符集裁剪字符串。
- (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)set;
NSCharacterSet對象可以通過類方法創建
// 創建空格和換行字符集
[NSCharacterSet whitespaceAndNewlineCharacterSet];
// 創建空格字符集
[NSCharacterSet whitespaceCharacterSet];
找到原因後,然後看person方法是怎麼聲明。
解決方式:將NSArray * 改成id。
1.1
錯誤原因:說YZViewController 沒有實現tableView:numberOfRowsInSection:
解決方式:實現tableView:numberOfRowsInSection:
1.2
這裡返回空,會報錯。
UITableView內部實現原理:
數據源實現了這個方法
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
tableView內部自動會調用以下方法添加cell。
[tableView addSubview:cell];
如果返回的cell為空,也就意味著生成下面一行代碼。
[tableView addSubview:nil];
而addSubview是將右邊參數添加到數組中保存起來,而數組是不能添加空值的。所有集合對象都不能出傳空。例如數組,字典,NSSet。
以上錯誤總結:作為tableView的數據源必須實現兩個方法。
返回行數
-(NSInteger)tableView:(UITableView*)tableViewnumberOfRowsInSection:(NSInteger)section;
返回每一行顯示的內容
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
另外返回每一行顯示的內容不能返回nil。
上面步驟二,僅僅是將模型從數組中銷毀,而模型並沒有被銷。
原因是:UITableViewController控制器不能加載UITableView,因為它會去加載stroyboard中的UIView。
解決方式:將stroyboard中的UIView改成UITableView
當發現自己描述的xib和運行的時候展現出來的不一樣的時候,這時候已經想到自己命名的屬性名稱和系統命名的沖突了。
錯誤原因
系統自帶的UITableViewCell中也有imageView這個屬性,因此沖突了。
解決辦法:將自定義視圖的imageView屬性名稱改成iconView.
注意:以後自定義屬性命名不要和系統自帶的屬性名稱相同。
以後看到duplicate這個詞語,錯誤原因就是重復定義了類,函數方法等等。
一般都是因為導入了.m文件
錯誤:
解決方式:將#import "newsCell.m"這一行刪掉。
看見這個錯誤,應該要想到初始化方法命名錯誤的問題。因為self只能在init開頭的方法中賦值,init必須是一個獨立的單詞,因此init後的第一個字母必須大寫。
一般情況:代理和控件使用weak
其他對象使用strong
基本數據類型使用assign
原因:由於代理方法中重新刷新了表格,也就意味著把之前的頭部視圖給替換了,因此沒有動畫了,不要創建新的頭部,才能讓舊的頭部執行動畫
解決方法:用一個數組或者字典保存所有的頭部視圖,重新刷新的時候,直接取就OK了。
報錯原因:xib是大寫的KeyboardTool,而加載的時候名字寫成小寫了。
解決方式:將加載的xib的名稱改成大寫。