2011-04-11 59 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,而不是仅仅替换视图。