1. 程式人生 > IOS開發 >幾個iOS開發的小tips

幾個iOS開發的小tips

clipsToBounds vs masksToBounds

clipsToBounds

clipsToBounds 決定子檢視的顯示範圍:設定為YES時,子檢視超出部分將被剪裁,不會顯示;設定為NO則不會剪裁。 clipsToBounds的預設值為NO,但是在UIScrollview中為YES。

比如view2新增到view1上,即view2為view1的subview。

UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(50,150,100,100)];
view1.backgroundColor = [UIColor blueColor];
[self.view addSubview:view1];
    
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(50,50,100)];
view2.backgroundColor = [UIColor redColor];
[view1 addSubview:view2];
複製程式碼

view1的clipsToBounds設定為NO時,view2超出view1的部分將不會剪裁,如圖左,紅色部分不會被剪裁。

view1.clipsToBounds = NO;
複製程式碼

view1的clipsToBounds設定為YES時,view2超出view1的部分將會被剪裁,如圖右,紅色部分被剪掉了。

view1.clipsToBounds = YES;
複製程式碼

clipsToBounds

在Apple的Prefetching Collection View Data 示例程式碼中就是將UICollectionView 的 clipsToBounds 設定為 NO以顯示 cell 超出 UICollectionView 時的狀態,來觀察UICollectionViewCell的生命週期。

masksToBounds

masksToBounds的功能和clipsToBounds類似,但是clipsToBounds是CALayer的屬性,clipsToBounds是UIView新的屬性,clipsToBounds會呼叫maskToBounds方法。

通常使用在設定cornerRadius不能達到圓角效果的控制元件上,如UIImageView、UILabel等。

imageView.layer.cornerRadius = 5.f;
imageView.layer.masksToBounds = YES;
複製程式碼

需要注意,設定maskToBounds = YES可能會觸發離屏渲染。關於可參考

關於iOS離屏渲染的深入研究

UITextField && UITextView 輸入限制

限制文字輸入可以監聽UIKeyboardWillChangeFrameNotification通知,在其中判斷文字長度。但需要注意的是:不要把高亮的部分,即聯想輸入的部分記入到字數統計中,因為這部分不是我們真正要輸入的內容。比如在中文情況下,輸入拼音時,還沒有選中文字就會被鍵盤當作字母輸入到UITextField/UITextView中,比如可輸入字元還剩下1個,此時想打一個“吃”字,輸入拼音“chi”,則會將計算的是“chi”三個字元的長度。

- (void)textViewDidChange:(UITextView *)textView {
    if (textView.text.length > self.maxInputWords && !textView.markedTextRange) { // 防止把高亮的部分計入
        textView.text = [textView.text substringToIndex:self.maxInputWords];
    }
    // 顯示已經輸入文字個數
    self.wordsLabel.text = [NSString stringWithFormat:@"%lu/%ld",(long)textView.text.length,(long)self.maxInputWords];
}
複製程式碼

UITextView return鍵隱藏鍵盤

UITextView 不像 UITextfield 一樣提供了 textFieldShouldReturn:方法實現,可以通過 UITextViewDelegate 中的textView:shouldChangeTextInRange:replacementText代理方法實現:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if ([text isEqualToString:@"\n"]){ // 判斷輸入的字是否是回車,即按下 return
        [textView resignFirstResponder];
        return NO;
    }
    return YES;
}
複製程式碼

UISwitch 開關保持原來的狀態

UISwitch在點選時狀態即會改變,如果想讓它點選時不馬上改變狀態,而是進行其他操作之後再響應,可以在UISwitch的target方法中這樣操作:

[switch addTarget:self action:@selector(switchAction:) forControlEvents:UIControlEventValueChanged];

- (void)switchAction:(UISwitch *)sender {
		// 讓開關狀態不變
		[sender setOn:!sender.on animated:YES];

		// 其他操作...

		// 修改開關狀態
		sender.on = ...;
}
複製程式碼

注意:是把animated設定為YES。原因推測可能是animated有延時。

UITableView 單選多選實現

UITableview提供了單選和多選機制,分別是allowsSelectionallowsMultipleSelection屬性,但是當你想要在一個TabelView的不同section中分別使用單選和多選(比如第一個section支援單選,第二個 section 支援多選)就需要自己實現了。在 section 不多的情況下,這裡提供一種快速的方案:讓 UITableview 開啟多選,即allowsMultipleSelection=YES,用變數記錄單選section中上一次選中的行,在tableView:didSelectRowAtIndexPath中進行判斷,如果選擇的是不同行,則取消上一次選中。

self.tableView.allowsMultipleSelection = YES; // 允許多選

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    BBASuggestFeedbackHeaderModel *headerModel;

    if (indexPath.section == 0) {
         // 取消上一次選中
         if (self.lastSelectedIndex != indexPath.row) { // 點選同一個不做處理
              NSIndexPath *lastIndex = [NSIndexPath indexPathForRow:self.lastSelectedIndex inSection:indexPath.section];
              [tableView deselectRowAtIndexPath:lastIndex animated:YES];
              self.lastSelectedIndex = indexPath.row;
         }
    }
}
複製程式碼

獲取選中狀態的cell,即可通過indexPathsForSelectedRows獲取。

UICollectionViewCell 高亮和點選態

UICollectionView不像UITableView一樣預設有高亮狀態,可以通過設定 UICollectionViewCell 的selectedBackgroundView實現。並且UICollectionView也提供幾個高亮的代理方法

  • collectionView:shouldHighlightItemAtIndexPath:
  • collectionView:didHighlightItemAtIndexPath:
  • collectionView:didUnhighlightItemAtIndexPath:

但是如果這個時候的需求是需要在高亮的時候讓cell上的其他子控制元件也改變alph值,單純的設定selectedBackgroundView的不能滿足。 可以通過重寫Cell的兩個方法setHighlighted:setSelected:

  • setHighlighted: 高亮狀態,即按在cell上不鬆開的效果
  • setSelected: 選中狀態,點選一個cell即選中
 - (void)setHighlighted:(BOOL)highlighted {
    [super setHighlighted:highlighted];
    
    if (highlighted) {
    	// 高亮狀態下的子控制元件顏色設定
    } else {
    	// 普通狀態的子控制元件顏色設定
    }
}

 - (void)setSelected:(BOOL)selected {
    [super setSelected:selected];

    if (selected) {
   	 	// 高亮狀態下的子控制元件顏色設定
    } else {
		// 普通狀態的子控制元件顏色設定
    }
}
複製程式碼

Cell上UIImageView的圖片不顯示

如果cell上的UIImageView在不同情況下會size不同,圓角不同,cell複用是需要更新UIImageView的約束。遇到UIImageView中圖片不顯示的情況,可以從以下幾個方面排查:

  • imageView 的 frame 是否設定正確,比如採用initWithImage:方法初始化時,會根據圖片的大小來設定imageView的frame可以不用初始化尺寸,但是大小不可控。
  • image view 的 hidden 是否設定
  • 是否新增到父 view 上
  • 是否設定 imageView 的 image
  • imageView 的 image 是否是從網路獲取的,是否採用佔點陣圖片
  • imageView是否在設定圓角,圓角是否過大,比如ImageView的size為20 * 20,而圓角大小為40,則不會顯示。