按鈕點擊需創建不定數量的 UIView,舊寫法在 .h 中聲明 UIView *_view1, *_view2… 並用 KVC valueForKey: 拼接字符串取值,極其脆弱且不可維護。
- (IBAction)addSubViews:(id)sender {
for (NSInteger i = 0; i < 5; i++) {
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(20 + i*60, 100, 50, 50)];
subView.backgroundColor = [UIColor colorWithHue:(arc4random()%256)/255.0 saturation:0.7 brightness:0.9 alpha:1];
subView.tag = 1000 + i; // 唯一標識
subView.layer.cornerRadius = 8;
[self.view addSubview:subView];
}
}
- (IBAction)operateSecondView:(id)sender {
UIView *target = (UIView *)[self.view viewWithTag:1001]; // 獲取第 2 個
if (target) {
[UIView animateWithDuration:0.3 animations:^{
target.transform = CGAffineTransformMakeRotation(M_PI_4);
target.backgroundColor = [UIColor redColor];
}];
}
}
當邏輯複雜時,引入數據模型數組:
@property (nonatomic, strong) NSMutableArray *items;
- (void)reloadViews {
// 1. 移除舊子視圖(保留 tag ≥ 1000 的)
for (UIView *v in self.view.subviews) {
if (v.tag >= 1000) [v removeFromSuperview];
}
// 2. 根據模型重建
for (NSInteger i = 0; i < self.items.count; i++) {
ItemModel *m = self.items[i];
UIView *v = [[UIView alloc] initWithFrame:m.frame];
v.tag = 1000 + i;
v.backgroundColor = m.color;
[self.view addSubview:v];
}
}
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| KVC 拼接字符串 | 快速驗證 | 編譯期不報錯、重構地獄、內存洩漏風險 | 拋棄 |
| Tag 查找 | 零額外屬性、O(1) 查找、簡單直觀 | Tag 魔術數字、層級深時需遞歸查找 | 少量動態視圖、原型開發 |
| IBOutletCollection | Interface Builder 可視化連接、類型安全 | 數量固定、不支持動態增減 | 靜態佈局 |
| 模型驅動 + 自定義 ContainerView | 關注點分離、可測試、支撐無限動態、配合 Diffable Data Source | 初始代碼量大 | 生產級複雜動態 UI |
動態創建 UI **拒絕 KVC 字符串拼接**。簡單場景用 **Tag**,複雜場景上 **模型驅動 + 容器視圖**,代碼清晰、可維護、易擴展。