IBOutletCollection在Interface Builder中设置排序

geb*_*bel 46 xcode objective-c interface-builder iboutlet ios

我正在使用IBOutletCollections来分组几个类似UI元素的实例.特别是我将一些UIButton(类似于测验游戏中的蜂鸣器)和一组UILabels(显示分数)组合在一起.我想确保按钮上方的标签更新分数.我认为通过索引访问它们是最容易的.不幸的是,即使我以相同的顺序添加它们,它们并不总是具有相同的索引.Interface Builder中是否有一种方法可以设置正确的顺序.

cdu*_*uhn 74

编辑:一些评论者声称更新版本的Xcode IBOutletCollections按顺序返回连接.其他人声称这种方法在故事板中对他们不起作用.我自己没有对此进行测试,但如果您愿意依赖未记录的行为,那么您可能会发现我在下面提出的显式排序不再是必需的.


遗憾的是,似乎没有任何方法可以控制IBOutletCollectionIB中的顺序,因此您需要在根据视图的某些属性加载数组之后对其进行排序.您可以根据tag属性对视图进行排序,但在IB中手动设置标记可能相当繁琐.

幸运的是,我们倾向于按照我们想要访问它们的顺序布置我们的视图,因此通常基于x或y位置对数组进行排序就像这样:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Order the labels based on their y position
    self.labelsArray = [self.labelsArray sortedArrayUsingComparator:^NSComparisonResult(UILabel *label1, UILabel *label2) {
        CGFloat label1Top = CGRectGetMinY(label1.frame);
        CGFloat label2Top = CGRectGetMinY(label2.frame);

        return [@(label1Top) compare:@(label2Top)];
    }];
}
Run Code Online (Sandbox Code Playgroud)

  • 为了这个问题的新访问者的利益,Xcode现在似乎可靠地保留了IBOutletCollection视图的顺序. (7认同)
  • @NickLockwood我不认为使用故事板时就是这种情况. (6认同)
  • return [[NSNumber numberWithFloat:[obj1 frame] .origin.x] compare:[NSNumber numberWithFloat:[obj2 frame] .origin.x]]; - 这将按x排序 (3认同)

Iva*_*sev 23

我跑了cduhn的答案并制作了这个NSArray类别.如果现在xcode确实保留了设计时顺序,那么这个代码并不是真的需要,但是如果你发现自己不得不在IB中创建/重新创建大型集合并且不想担心搞乱,这可能会有所帮助(在运行时).另外一个注意事项:很可能是对象添加到集合中的顺序与您在Identity Inspector选项卡中找到的"对象ID"有关,当您编辑界面并将新对象引入时,它可能会偶发.以后收集.

.H

@interface NSArray (sortBy)
- (NSArray*) sortByObjectTag;
- (NSArray*) sortByUIViewOriginX;
- (NSArray*) sortByUIViewOriginY;
@end
Run Code Online (Sandbox Code Playgroud)

.M

@implementation NSArray (sortBy)

- (NSArray*) sortByObjectTag
{
    return [self sortedArrayUsingComparator:^NSComparisonResult(id objA, id objB){
        return(
            ([objA tag] < [objB tag]) ? NSOrderedAscending  :
            ([objA tag] > [objB tag]) ? NSOrderedDescending :
            NSOrderedSame);
    }];
}

- (NSArray*) sortByUIViewOriginX
{
    return [self sortedArrayUsingComparator:^NSComparisonResult(id objA, id objB){
        return(
            ([objA frame].origin.x < [objB frame].origin.x) ? NSOrderedAscending  :
            ([objA frame].origin.x > [objB frame].origin.x) ? NSOrderedDescending :
            NSOrderedSame);
    }];
}

- (NSArray*) sortByUIViewOriginY
{
    return [self sortedArrayUsingComparator:^NSComparisonResult(id objA, id objB){
        return(
            ([objA frame].origin.y < [objB frame].origin.y) ? NSOrderedAscending  :
            ([objA frame].origin.y > [objB frame].origin.y) ? NSOrderedDescending :
            NSOrderedSame);
    }];
}

@end
Run Code Online (Sandbox Code Playgroud)

然后在您选择命名时包含头文件,代码可以是:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Order the labels based on their y position
    self.labelsArray = [self.labelsArray sortByUIViewOriginY];
}
Run Code Online (Sandbox Code Playgroud)


Nic*_*ood 6

不确定这是什么时候改变了,但至少从Xcode 4.2开始,这似乎不再是一个问题.IBOutletCollections现在保留在Interface Builder中添加视图的顺序.

更新:

我做了一个测试项目来验证是这种情况:IBOutletCollectionTest


Jim*_*Jim 5

不是我所知道的.

作为一种解决方法,您可以按顺序为每个标记分配一个标记.按钮范围为100,101,102等,标签为200,201,202等.然后在按钮的标签上添加100以获取其对应的标签标签.然后,您可以使用获取标签viewForTag:.

或者,您可以将相应的对象分组到自己的对象中UIView,因此每个视图只有一个按钮和一个标签.


mas*_*bio 5

我发现Xcode使用连接的ID按字母顺序对集合进行排序.如果你在你的nib文件上打开版本编辑器,你可以轻松编辑id(确保它们是唯一的,否则Xcode会崩溃).

<outletCollection property="characterKeys" destination="QFa-Hp-9dk" id="aaa-0g-pwu"/>
<outletCollection property="characterKeys" destination="ahU-9i-wYh" id="aab-EL-hVT"/>
<outletCollection property="characterKeys" destination="Kkl-0x-mFt" id="aac-0c-Ot1"/>
<outletCollection property="characterKeys" destination="Neo-PS-Fel" id="aad-bK-O6z"/>
<outletCollection property="characterKeys" destination="AYG-dm-klF" id="aae-Qq-bam"/>
<outletCollection property="characterKeys" destination="Blz-fZ-cMU" id="aaf-lU-g7V"/>
<outletCollection property="characterKeys" destination="JCi-Hs-8Cx" id="aag-zq-6hK"/>
<outletCollection property="characterKeys" destination="DzW-qz-gFo" id="aah-yJ-wbx"/>
Run Code Online (Sandbox Code Playgroud)

如果您首先在IB的文档大纲中手动订购对象,这将有助于它们在xml代码中按顺序显示.