2011-04-11 43 views
5

許多人都問過類似的問題,但反應是要麼只是含糊不足或沒有我需要的東西去的方向,所以我會嘗試儘可能具體地問這個。這個問題的背景是使用的XCode 4自定義的UIView配置了InterfaceBuilder的

我有一個應用程序,我用同樣的Widget無數次iOS開發。在這個簡單的練習中,小部件將是一個固定大小的紅色框,在頂部有一個標籤,根視圖控制器將會改變,但您可以想象它有很多ImageViews和ScrollViews,看起來很漂亮。最後一點是關鍵,因爲非編碼藝術設計師希望能夠全局調整此視圖,而不必在每個重複的用戶界面上反覆做同樣的事情。

在應用程序中,我用單個UIView替換了用於組成widget的ImageViews和ScrollView,並使用InterfaceBuilder將Custom Class設置爲Widget。我在根視圖控制器中爲這些Widget對象正確連接了插座。 Widget類是UIView的一個子類,代碼如下:

@interface Widget : UIView { 
    UILabel  *label; 
} 

@property (nonatomic, retain) IBOutlet UILabel *label; 
@property (nonatomic, copy) NSString *labelName; 
@end 


@implementation Widget 
@synthesize label, labelName; 

- (id)initWithCoder:(NSCoder *)aDecoder { 
    if ((self = [super initWithCoder:aDecoder])) { 
     // This is the code that I want to disappear  
     CGRect pos = CGRectMake(5, 5, 90, 30); 
     label = [[UILabel alloc] initWithFrame:pos]; 
     [self addSubview:label]; 
     self.backgroundColor = [UIColor redColor]; 
    } 
    return self; 
} 

- (NSString *)labelName { 
    return label.text; 
} 

// This live updates the label in this custom view 
- (void)setLabelName:(NSString *)name { 
    label.text = name; 
} 

- (void)dealloc { 
    [super dealloc]; 
} 
@end 

代碼的偉大工程,我能活更新從主視圖控制器的自定義視圖中的文本。但是,initWithCoder中的四行代碼是問題所在。還記得設計師嗎?我有他們的地方,他們可以用界面生成器來發揮他們的魔力,但是我不能爲我的生活弄清楚如何讓UIView從他們設計的筆尖加載自己。手動嘗試和複製單個項目的定位和屬性並不是非常令人興奮和相當耗時(如果我沒有寫這篇文章,我意識到現在我會完成)。

所以很乾脆,我怎麼能取任意的.xib文件,並將它做我的手卷中的initWithCoder的工作?我認爲在這一點上將微不足道的聯繫到UILabel的IBOutlet,但如果我過於樂觀,請對此評論。

作爲第二個問題,一旦啓動並在實際運行的UI,我會之類的東西,UIScrollViews勾搭上了。 Widget會成爲UIScrollViewDelegate還是代碼停放在哪裏?根視圖控制器應該忘記這一點,但將傳統上放在View Controller中的代碼放到UIView對象中感覺不合適。

+0

如果你的小部件對於它的視圖來說不僅僅是一個愚蠢的容器,爲什麼不把它變成視圖控制器呢? – jrturton 2013-01-14 07:36:56

回答

0

是的,您應該在標籤上掛上IBOutlet,然後設計人員可以從Interface Builder中定位標籤。

關於UIScrollViewDelegate,你也應該設置爲滾動視圖的IBOutlet,然後控制器裏面做widgetView.scrollView.delegate = self,設置你的電流控制器作爲滾動視圖的委託。

作爲一種替代方法,您可以使Widget查看滾動視圖的代理,但在我看來,您將通過這樣做(處理滾動視圖事件的代碼是控制器代碼)來打破MVC合規性。

+0

所以在創建包含位於UIView中的UILabel的UIView(比如說100x200)的.xib文件之後,我需要將它與'widget.h/.cpp'結合在一起。一個失敗的想法是在身份檢查員將文件所有者的**自定義類**設置爲'Widget'。然後,我可以將標籤上的**引用出口**設置爲文件所有者的'label'屬性。在註釋掉'initWithCoder'中的四行代碼後,我做的任何事情都不會讓.xib的內容出現在具有Widget對象的視圖控制器中。我只希望有一個明顯的最後一步,我失蹤了。 – Waldo 2011-05-18 03:31:05

0

關於你的第一個問題,我想你正在尋找的是這樣的:

Widget *widget = nil; 
NSArray *nibItems = [[NSBundle mainBundle] loadNibNamed:@"Widget" owner:self options:nil]; 
for (id o in nibItems) { 
    if ([o isTypeOfClass:[Widget class]]) { 
     widget = (Widget *)id; 
    } 
} 

// Do whatever you want with the Widget... 

通過束從筆尖加載它會保護你的設計師在界面生成器的工作,並會觸發撥號到initWithCoder。

至於第二個問題,你有兩個選擇。您可以在nib(它是IB可訪問的屬性)中設置UIScrollView的委託屬性,也可以在initWithCoder方法的代碼中手動設置它。這取決於期望的行爲。

4

在控制器中聲明一個IBOutlet(IBOutlet UIView * Widget;)。將Widget視圖(來自設計者)放在控制器的xib中(如果你的控制器沒有xib,那麼你可以爲你的控制器創建或指定一個新的xib)。然後將這個視圖連接到上面的IBOutlet。如果你想避免標籤的掛鉤,滾動視圖等等。每當設計者做出改變時,你必須替換整個xib,而不是僅僅替換視圖。