首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Nib中加载Nib

在Nib中加载Nib
EN

Stack Overflow用户
提问于 2009-08-18 22:25:35
回答 6查看 3.3K关注 0票数 2

我是界面构建器的新手,我希望有一个屏幕,它包含一个UIView的3x3网格,每个网格都包含一个UIImageView和4个UILabels。

我的逻辑可能有缺陷,但我试图做到这一点的方式是:

  1. 创建一个UIView Nib文件MyUIView.nib并在IB中使用imageView和4个标签进行布局
  2. 创建一个名为MyUIView.m的UIView子类,其中包含1个IBOutlet UIImageView和4个IBOutlet UILabels。将MyUIView.nib和MyUIView.m链接为文件所有者,并连接这些插座。
  3. 然后创建另一个nib MyGridViewController.nib,它在3x3网格中布局了9个MyUIView。
  4. 创建一个具有9 IBOutlet MyUIView的MyUIView,并通过Interface将它们连接起来。

是否有可能从InterfaceBuilder中以图形方式将一个nib加载到另一个nib中,如果是这样的话,我该如何做呢?我是否将“标准”UIView拖到画布上,然后将类更改为MyUIView?

还是需要在MyGridViewController.m中以编程方式完成这些操作,比如:

代码语言:javascript
复制
for (int i=0; i<9; i++)
{
    NSArray* nibViews =  [[NSBundle mainBundle] loadNibNamed:@"MyUIView" owner:self options:nil];
   [myViewArray addObject:[ nibViews objectAtIndex: 1]];
}

我让它工作的唯一方法是拥有一个Nib,并放置9 UIImageViews和36 UILabels,但是当我需要更新3x3“单元”时,这显然是一种痛苦。我认为在一个文件中修改它会更容易,并且所有的9个都会被更新。

EN

回答 6

Stack Overflow用户

发布于 2009-08-19 01:51:19

您不能在Interface中这样做。

我可能要做的是创建一个自定义视图,比如MyGridItem,在它醒来时将MyUIView.nib作为子视图加载,然后在您的MyGridView.nib中使用其中的9个。

小心awakeFromNib,因为如果在加载两个不同的nib时涉及到视图,则可以调用它两次(例如,如果MyGridItem是加载MyGridView.nib时的所有者,那么MyGridItem awakeFromNib将在作为加载MyUIView.nib的一部分加载时调用一次,在加载MyGridView.nib时调用一次。

另外,由于要加载nib 9次,所以您可能需要使用

代码语言:javascript
复制
NSNib* theNib = [[NSNib alloc] initWithNibNamed:@"MyGridItem" bundle:nil];

装载以下内容:

代码语言:javascript
复制
if ( [theNib instantiateNibWithOwner:self topLevelObjects:NULL] ) {

然后,在加载了所有9个子视图之后,您可能需要释放它。

票数 3
EN

Stack Overflow用户

发布于 2012-06-07 15:34:42

“是的,你(几乎)可以。”

我使用Interface在我的项目中这样做。

唯一的缺陷是,您看到一个白色区域来表示Interface中的“嵌套nib”。假设同时(我主要在等待苹果在XCode中添加此功能),我在这里介绍的解决方案是可以接受的。

首先阅读以下内容:https://blog.compeople.eu/apps/?p=142

然后,如果您做了ARC,按照这些说明,并抓取我的UIVIew+Util类别包括在这里。

对于ARC,您必须允许这种“自我”分配。(https://blog.compeople.eu/apps/?p=142声明它不需要,但它是需要的。如果不这样做,您将得到一些“发送到已分配实例的消息”)

要在ARC项目中实现这一点,请在文件中添加‘-fno-objc-圆弧’标志编译器设置。然后在这个文件中不进行ARC编码(比如dealloc设置nils,调用等等)

此外,客户端nib的视图控制器应该使用强属性来保存awakeFromNib返回的实例。在我的示例代码中,引用customView如下所示:

@property (strong,非原子) IBOutlet CustomView* customView;

最后,我使用定义在我的copyUIPropertiesTo: UIView+Util类别中的loadNibNamed对属性处理和nib加载添加了一些其他改进。

所以awakeAfterUsingCoder:代码现在是

代码语言:javascript
复制
#import "UIView+Util.h"
...
- (id) awakeAfterUsingCoder:(NSCoder*)aDecoder
{
    // are we loading an empty “placeholder” or the real thing?
    BOOL theThingThatGotLoadedWasJustAPlaceholder = ([[self subviews] count] == 0);

    if (theThingThatGotLoadedWasJustAPlaceholder)
    {
        CustomView* customView = (id) [CustomView loadInstanceFromNib];
        // copy all UI properties from self to new view!
        // if not, property that were set using Interface buider are lost!
        [self copyUIPropertiesTo:customView];

        [self release];
        // need retain to avoid deallocation
        self = [customView retain];
    }
    return self;
}

UIView+Util类别代码是

代码语言:javascript
复制
@interface UIView (Util)
   +(UIView*) loadInstanceFromNib;
   -(void) copyUIPropertiesTo:(UIView *)view;
@end

连同它的实施

代码语言:javascript
复制
#import "UIView+Util.h"
#import "Log.h"

@implementation UIView (Util)

+(UIView*) loadInstanceFromNib
{ 
    UIView *result = nil; 
    NSArray* elements = [[NSBundle mainBundle] loadNibNamed: NSStringFromClass([self class]) owner: nil options: nil];
    for (id anObject in elements)
    { 
        if ([anObject isKindOfClass:[self class]])
        { 
            result = anObject;
            break; 
        } 
    }
    return result; 
}

-(void) copyUIPropertiesTo:(UIView *)view
{
    // reflection did not work to get those lists, so I hardcoded them
    // any suggestions are welcome here

    NSArray *properties =
    [NSArray arrayWithObjects: @"frame",@"bounds", @"center", @"transform", @"contentScaleFactor", @"multipleTouchEnabled", @"exclusiveTouch", @"autoresizesSubviews", @"autoresizingMask", @"clipsToBounds", @"backgroundColor", @"alpha", @"opaque", @"clearsContextBeforeDrawing", @"hidden", @"contentMode", @"contentStretch", nil];

    // some getters have 'is' prefix
    NSArray *getters =
    [NSArray arrayWithObjects: @"frame", @"bounds", @"center", @"transform", @"contentScaleFactor", @"isMultipleTouchEnabled", @"isExclusiveTouch", @"autoresizesSubviews", @"autoresizingMask", @"clipsToBounds", @"backgroundColor", @"alpha", @"isOpaque", @"clearsContextBeforeDrawing", @"isHidden", @"contentMode", @"contentStretch", nil];

    for (int i=0; i<[properties count]; i++)
    {
        NSString * propertyName = [properties objectAtIndex:i];
        NSString * getter = [getters objectAtIndex:i];

        SEL getPropertySelector = NSSelectorFromString(getter);

        NSString *setterSelectorName =
            [propertyName stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[propertyName substringToIndex:1] capitalizedString]];

        setterSelectorName = [NSString stringWithFormat:@"set%@:", setterSelectorName];

        SEL setPropertySelector = NSSelectorFromString(setterSelectorName);

        if ([self respondsToSelector:getPropertySelector] && [view respondsToSelector:setPropertySelector])
        {
            NSObject * propertyValue = [self valueForKey:propertyName];

            [view setValue:propertyValue forKey:propertyName];
        }
    }    
}

Tadaaaa :-)

https://stackoverflow.com/users/45018/yang获得初始解决方案的学分。我只是改进了一下。

票数 2
EN

Stack Overflow用户

发布于 2011-10-31 14:38:52

如果使用一个nib中的1个图像视图和4个标签创建视图(我将此视图称为“网格单元格”),则可以为网格创建另一个nib,并拖动网格单元格的9个实例。这9个实例在IB中只显示为占位符(空白视图),但当您运行应用程序时,它们将工作。

这篇文章告诉你如何去做。请查看名为“可重用子视图”的部分。既然你正在用9个相同的单元格构建一个网格,那么使用AQGridView可能是有意义的--参见“可重用的AQGridViewCell”一节。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1296903

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档