2014-01-10 155 views
2

根據Apple's documentation,Interface Builder實例化對象,然後在設計時將對象序列化並打包到NIB/XIB文件中。在運行時,整個對象圖通過initWithCoder:進行反序列化。Interface Builder編碼

這裏的文檔:

認爲是在Interface Builder創建不叫initWithFrame實例:當他們的筆尖文件被加載,這往往會導致混亂。請記住,Interface Builder在保存一個nib文件時存檔一個對象,所以視圖實例已經被創建並且initWithFrame:已經被調用。

作爲對象通過的initWithCoder實例:,我認爲對象圖是通過其對應encodeWithCoder序列:。然而,考慮下面的代碼:

@interface CustomView : UIView 
@end 

@implementation CustomView 

-(id)initWithCoder:(NSCoder *)aDecoder{ 
    if(self = [super initWithCoder:aDecoder]){ 
     NSNumber * n = [aDecoder decodeObjectForKey:@"DummyKey"]; 
     NSLog(@"%@", n); 
    } 
    return self; 
} 

-(void)encodeWithCoder:(NSCoder *)aCoder{ 
    [super encodeWithCoder:aCoder]; 
    [aCoder encodeObject:@YES forKey:@"DummyKey"]; 
} 

@end 

如果我把這個CustomView在Interface Builder的故事板,它打印代替「YES」 「(空)」。這是爲什麼發生? Interface Builder如何序列化對象圖?我誤解了文檔?

+0

請注意,您可以在IB中添加「用戶定義的運行屬性」(選擇視圖並轉至檢查器的第三個選項卡)。當它被取消存檔IIRC(使用你的屬性的setter方法)時,這些將被設置在你的對象上。 – Taum

回答

0

encoderWithCoder:方法不會被調用,因爲XCode將對象圖編碼到xib中的時間不是運行時間,它不能調用您的encoderWithCoder:方法。

How does Interface Builder serialize the object graph?

如果打開廈門國際銀行作爲源代碼,你可以看到它是這樣的:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none"> 
    <dependencies> 
     <deployment defaultVersion="1536" identifier="iOS"/> 
     <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/> 
    </dependencies> 
    <objects> 
     <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="EMXibViewController"> 
      <connections> 
       <outlet property="view" destination="1" id="3"/> 
      </connections> 
     </placeholder> 
     <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> 
     <view contentMode="scaleToFill" id="1"> 
      <rect key="frame" x="0.0" y="0.0" width="320" height="568"/> 
      <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> 
      <subviews> 
       <view contentMode="scaleToFill" id="XyJ-CF-vRx"> 
        <rect key="frame" x="68" y="102" width="204" height="403"/> 
        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> 
        <color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/> 
       </view> 
      </subviews> 
      <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> 
      <simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/> 
      <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/> 
     </view> 
    </objects> 
</document> 

我們可以看到,廈門國際銀行只保留對象的非默認值之間的關係他們。

的廈門國際銀行的UIViewController中,有隻有兩個UI對象,一個是UIViewController的觀點,另一個是它的子視圖讓我們說這mysubview和有關會談如何XCode的存檔mysubview

我已經改變其的backgroundColor,幀和mysubview autoresizingMask屬性,採取backgroundColor屬性作爲例子,backgroundColor屬性被保存爲「彩色鍵=」的backgroundColor「白色=‘0.0’阿爾法=‘1’色彩空間=」 calibratedWhite 「」。它將歸檔mysubview的backgroundColor。

Xib只是歸檔了mysubview對象的backgroundColor和autoresizingMask和frame屬性,當加載xib時,它會調用UIView的initWithCoder方法。在該方法中,它將獲得用於關鍵字@「backgroundColor」的UIColor對象和用於關鍵字@「frame」的CGRect以及用於關鍵字「@ autoresizingMask」的UIViewAutoresizing,而UIView的任何其他屬性都被分配了默認值。

- (id)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super initWithCoder:aDecoder] ; 
    UIColor * backgroundColor = [aDecoder decodeIntegerForKey:@"backgroundColor"] ; 
    if (backgroundColor) { 
     self.backgroundColor = backgroundColor ; 
    } else { 
     self.backgroundColor = $(defaultColor) ; // if no key in xib, use the default value. 
    } 
    // more... 
    return self ; 
} 

這是一個不錯的問題,讓我多想一想。

+0

@TamásZahola我已經更新了我的答案,也許更清楚。 – KudoCC

0

Interface Builder不會使用您的代碼來生成xib。就這麼簡單。 Interface Builder不會調用encodeWithCoder。 Interface Builder不運行您的代碼。

+0

那麼爲什麼蘋果文檔會說以下內容:*「請記住,Interface Builder在保存一個nib文件時存檔一個對象,所以視圖實例已經創建並且initWithFrame:已經被調用。」*? 它明確指出視圖通過* initWithFrame:*實例化,然後存檔到NIB中。 –

+0

@TamásZahola請注意,Interface Builder不會創建自己的類實例。如果您從庫中選擇了「UIView」,並將其類更改爲「MyView」,則不會創建「MyView」。它仍然只是界面生成器的'UIView'。界面生成器不運行您的代碼。 – Sulthan

0

在簡單的一句話,如果你創建的廈門國際銀行或Storybord你的對象,然後initWithFrame的initWithCoder將無法​​通過您覆蓋,他們將通過框架調用,並從廈門國際銀行或Storybord創建對象屬性。