7

我创建了以下自定义视图:

@interface TNGalleryView : UIView

@property (assign, nonatomic) id <TNGalleryViewDelegate> delegate;
@property (assign, nonatomic) id <TNGalleryViewDataSource> dataSource;

@end

我可以在代码中分配它的委托,但是当我想在 IB 中分配委托时,我不能。我必须将我的代码更改为:

@interface TNGalleryView : UIView

@property (assign, nonatomic) IBOutlet id <TNGalleryViewDelegate> delegate;
@property (assign, nonatomic) IBOutlet id <TNGalleryViewDataSource> dataSource;

@end

然后我可以在 IB 中分配委托和数据源。

为什么如果我想在 IB 中分配委托和数据源,我必须添加 IBOutlet 标识符,但在 apple sdk 中没有任何 IBOutlets?例如这部分 UICollectionView 声明:

NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionView : UIScrollView

- (id)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout; // the designated initializer

@property (nonatomic, retain) UICollectionViewLayout *collectionViewLayout;
@property (nonatomic, assign) id <UICollectionViewDelegate> delegate;
@property (nonatomic, assign) id <UICollectionViewDataSource> dataSource;

没有任何 IBOutlet,但我可以在 IB 中分配 dataSource 并委托给它。

4

4 回答 4

2

装饰器IBOutlet是为了让 Interface builder 知道它可以连接到属性。这只是一个不产生代码的提示。

只有那些将连接到接口元素的属性才需要 IBOutlet。那是您通过在 GUI 对象和代码之间拖动来连接的对象。这是对接口构建器的提示,代码中的属性可以连接到。

于 2013-11-14T13:51:34.703 回答
2

很好的问题!

用文本编辑器打开你的storyboard/xib,搜索“TNGalleryView”,你会发现这样的xml标签:

<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ke7-rk-01e" customClass="TNGalleryView">
    <rect key="frame" x="86" y="309" width="160" height="252"/>
    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>

请注意:TNGalleryView 被包装在带有属性的“view”标签中:customClass="TNGalleryView"

现在在storyboard/xib中添加一个UICollectionView,用文本编辑器保存并重新打开storyboard/xib,搜索“collectionView”,你会发现xml标签是这样的:

<collectionView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" minimumZoomScale="0.0" maximumZoomScale="0.0" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="ouM-xa-T6a">
   <rect key="frame" x="93" y="72" width="160" height="252"/>
   <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
   <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="Cv0-O7-zGY">
   <size key="itemSize" width="50" height="50"/>
   <size key="headerReferenceSize" width="0.0" height="0.0"/>
   <size key="footerReferenceSize" width="0.0" height="0.0"/>
   <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
    </collectionViewFlowLayout>

</collectionView>

现在,你会发现不同的,collectionView 被包裹在一个“collectionView”标签中

我想这就是为什么如果不将自定义委托设置为 IBOutlet 就无法在 IB 中分配自定义委托的原因。

更新

没有足够的声誉来评论其他人的回答。所以我在这里说点什么:清楚地阅读问题,并在 xcode 中进行测试,你会意识到 Sergey Demchenko 的问题是什么:

首先,如果 TNGalleryViewDelegate 是这样声明的:

@property (assign, nonatomic) id <TNGalleryViewDelegate> delegate;

xcode 屏幕截图: 在此处输入图像描述

现在如果 TNGalleryViewDelegate 以这种方式声明:

@property (assign, nonatomic) IBOutlet id <TNGalleryViewDelegate> delegate;

xcode 屏幕截图: 在此处输入图像描述

于 2013-11-14T14:34:49.340 回答
1

其实这是一个很好的问题。由于 Xcode 和 IB 是不透明的——这意味着除了 Apple 之外没有人拥有源代码,我们所能做的就是猜测。我的猜测是,鉴于接受委托和数据源的 UIView 子类数量相对较少,Apple 刚刚将这些知识硬编码到 IB 中。

原因之一是 IB 不想在您每次切换到 Storyboard 或 NIB 视图时解析所有这些 UIView 子类。

无论如何,我们所能做的就是推测。将 IBOutlet 关键字添加到您自己的文件中并不难。

于 2013-11-14T13:59:15.170 回答
0

出口不一定暴露在头文件中。您可以通过在 .m 文件中定义插座来在自己的类中执行相同的操作。

于 2013-11-14T13:53:56.963 回答