Objective c Interface Builder中的IBMoutletCollection集合排序
我正在使用IBOutletCollections对几个类似UI元素的实例进行分组。特别是我将一些UIButton(类似于智力竞赛中的蜂鸣器)和一组UILabel(显示分数)分组。我想确保按钮正上方的标签更新分数。我认为通过索引访问它们是最容易的。不幸的是,即使我以相同的顺序添加它们,它们也不总是具有相同的索引。在Interface Builder中有没有设置正确顺序的方法。据我所知,没有 作为一种解决方法,您可以按顺序为它们中的每一个分配一个标记。让按钮范围为100、101、102等,标签范围为200、201、202等,然后将100添加到按钮的标签中,以获得相应的标签标签。然后可以使用Objective c Interface Builder中的IBMoutletCollection集合排序,objective-c,ios,xcode,interface-builder,iboutlet,Objective C,Ios,Xcode,Interface Builder,Iboutlet,我正在使用IBOutletCollections对几个类似UI元素的实例进行分组。特别是我将一些UIButton(类似于智力竞赛中的蜂鸣器)和一组UILabel(显示分数)分组。我想确保按钮正上方的标签更新分数。我认为通过索引访问它们是最容易的。不幸的是,即使我以相同的顺序添加它们,它们也不总是具有相同的索引。在Interface Builder中有没有设置正确顺序的方法。据我所知,没有 作为一种解决方法,您可以按顺序为它们中的每一个分配一个标记。让按钮范围为100、101、102等,标签范围为
viewForTag:
获取标签
或者,您可以将相应的对象分组到它们自己的
UIView
,这样每个视图只有一个按钮和一个标签。EDIT:一些评论者声称,最新版本的Xcode按照连接的顺序返回IBOutletCollections
。其他人则声称这种方法在情节提要中不适用于他们。我自己还没有测试过,但是如果你愿意依赖未记录的行为,那么你可能会发现我下面建议的显式排序不再是必要的
不幸的是,似乎没有任何方法可以控制IB中
IBOutletCollection
的顺序,因此需要根据视图的某些属性对加载后的数组进行排序。您可以根据视图的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)];
}];
}
不确定这到底是什么时候改变的,但至少从Xcode 4.2开始,这似乎不再是一个问题。IBMoutletCollections现在保留了在Interface Builder中添加视图的顺序 更新:
我做了一个测试项目来验证这种情况:我用cduhn的答案运行,并将这个NSArray分类。 如果现在xcode真的保留了设计时顺序,那么这段代码就不需要了,但是如果您发现自己必须在IB中创建/重新创建大型集合,并且不想担心弄糟,那么这可能会有所帮助(在运行时)。另请注意:对象添加到集合的顺序很可能与您在“标识检查器”选项卡中找到的“对象ID”有关,当您稍后编辑界面并向集合引入新对象时,该ID可能会变得零散 h m
IBMoutletCollection的订购方式似乎非常随意。也许我没有正确理解Nick Lockwood的方法,但我还是做了一个新项目,添加了一堆UILabel,并按照添加到视图中的顺序将它们连接到一个集合 登录之后,我得到了一个随机订单。这非常令人沮丧 我的解决方法是在IB中设置标记,然后按如下方式对集合进行排序:
[self setResultRow1:[self sortCollection: [self resultRow1]]];
这里,resultRow1是一个大约7个标签的iOutletCollection,标签通过IB设置。下面是排序方法:
-(NSArray *)sortCollection:(NSArray *)toSort {
NSArray *sortedArray;
sortedArray = [toSort sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSNumber *tag1 = [NSNumber numberWithInt:[(UILabel*)a tag]];
NSNumber *tag2 = [NSNumber numberWithInt:[(UILabel*)b tag]];
return [tag1 compare:tag2];
}];
return sortedArray;
}
为此,我现在可以使用
[resultRow1 objectAtIndex:I]
或类似工具访问对象。这节省了每次需要访问元素时必须迭代和比较标记的开销。我需要对UITextField对象集合进行排序,以设置键盘上的“下一步”按钮将导致的位置(字段选项卡)。这将是一个国际应用程序,所以我希望语言方向是模糊的
h
我发现Xcode使用连接ID按字母顺序对集合进行排序。 如果在nib文件上打开版本编辑器,您可以轻松编辑id(确保它们是唯一的,否则Xcode将崩溃)
如果您首先在IB的文档大纲中手动对对象进行排序,以便它们在xml代码中按顺序显示,这会有所帮助。我在
数组上创建了一个扩展,用于按标记进行排序,例如,在使用w/IBOutletCollection
时很有用
extension Array where Element: UIView {
/**
Sorts an array of `UIView`s or subclasses by `tag`. For example, this is useful when working with `IBOutletCollection`s, whose order of elements can be changed when manipulating the view objects in Interface Builder. Just tag your views in Interface Builder and then call this method on your `IBOutletCollection`s in `viewDidLoad()`.
- author: Scott Gardner
- seealso:
* [Source on GitHub](http://bit.ly/SortUIViewsInPlaceByTag)
*/
mutating func sortUIViewsInPlaceByTag() {
sortInPlace { (left: Element, right: Element) in
left.tag < right.tag
}
}
}
扩展数组,其中元素:UIView{
/**
按“标记”对“UIView”数组或子类进行排序。例如,这在使用“IBMoutletCollection”时非常有用,在界面生成器中操作视图对象时,可以更改其元素顺序。只需在界面生成器中标记视图,然后在“viewDidLoad()”中对“IBMoutletCollection”调用此方法即可。
-作者:斯科特·加德纳
-另见:
*[来源于GitHub](http://bit.ly/SortUIViewsInPlaceByTag)
*/
变异func sortUIViewsInPlaceByTag(){
sortInPlace{(左:元素,右:元素)位于
left.tag
由@scott gardner提出的扩展非常好,解决了[ui按钮]集合未按预期顺序显示等问题。以下代码仅为Swift 5更新。真的非常感谢斯科特!
扩展数组,其中元素:UIView{
/**
Sorts an array of `UIView`s or subclasses by `tag`. For example, this is useful when working with `IBOutletCollection`s, whose order of elements can be changed when manipulating the view objects in Interface Builder. Just tag your views in Interface Builder and then call this method on your `IBOutletCollection`s in `viewDidLoad()`.
- author: Scott Gardner
- seealso:
* [Source on GitHub](bit dot ly/SortUIViewsInPlaceByTag)
*/
mutating func sortUIViewsInPlaceByTag() {
sort { (left: Element, right: Element) in
left.tag < right.tag
}
}
}
/**
按“标记”对“UIView”数组或子类进行排序。例如,这在使用“IBMoutletCollection”时非常有用,在界面生成器中操作视图对象时,可以更改其元素顺序。只需在界面生成器中标记视图,然后在“viewDidLoad()”中对“IBMoutletCollection”调用此方法即可。
-作者:斯科特·加德纳
-另见:
*[GitHub上的源](位dotly/SortUIViewsInPlaceByTag)
*/
变异func sortUIViewsInPlaceByTag(){
在中排序{(左:元素,右:元素)
left.tag
我使用@scott gardner建议的扩展来排序图像视图,以便使用单个p来显示计数器
-(NSArray *)sortCollection:(NSArray *)toSort {
NSArray *sortedArray;
sortedArray = [toSort sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSNumber *tag1 = [NSNumber numberWithInt:[(UILabel*)a tag]];
NSNumber *tag2 = [NSNumber numberWithInt:[(UILabel*)b tag]];
return [tag1 compare:tag2];
}];
return sortedArray;
}
#import <Foundation/Foundation.h>
@interface NSArray (UIViewSort)
- (NSArray *)sortByUIViewOrigin;
@end
#import "NSArray+UIViewSort.h"
@implementation NSArray (UIViewSort)
- (NSArray *)sortByUIViewOrigin {
NSLocaleLanguageDirection horizontalDirection = [NSLocale characterDirectionForLanguage:[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]];
NSLocaleLanguageDirection verticalDirection = [NSLocale lineDirectionForLanguage:[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]];
UIView *window = [[UIApplication sharedApplication] delegate].window;
return [self sortedArrayUsingComparator:^NSComparisonResult(id object1, id object2) {
CGPoint viewOrigin1 = [(UIView *)object1 convertPoint:((UIView *)object1).frame.origin toView:window];
CGPoint viewOrigin2 = [(UIView *)object2 convertPoint:((UIView *)object2).frame.origin toView:window];
if (viewOrigin1.y < viewOrigin2.y) {
return (verticalDirection == kCFLocaleLanguageDirectionLeftToRight) ? NSOrderedDescending : NSOrderedAscending;
}
else if (viewOrigin1.y > viewOrigin2.y) {
return (verticalDirection == kCFLocaleLanguageDirectionLeftToRight) ? NSOrderedAscending : NSOrderedDescending;
}
else if (viewOrigin1.x < viewOrigin2.x) {
return (horizontalDirection == kCFLocaleLanguageDirectionTopToBottom) ? NSOrderedDescending : NSOrderedAscending;
}
else if (viewOrigin1.x > viewOrigin2.x) {
return (horizontalDirection == kCFLocaleLanguageDirectionTopToBottom) ? NSOrderedAscending : NSOrderedDescending;
}
else return NSOrderedSame;
}];
}
@end
- (void)viewDidAppear:(BOOL)animated {
_availableTextFields = [_availableTextFields sortByUIViewOrigin];
UITextField *previousField;
for (UITextField *field in _availableTextFields) {
if (previousField) {
previousField.nextTextField = field;
}
previousField = field;
}
}
<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"/>
extension Array where Element: UIView {
/**
Sorts an array of `UIView`s or subclasses by `tag`. For example, this is useful when working with `IBOutletCollection`s, whose order of elements can be changed when manipulating the view objects in Interface Builder. Just tag your views in Interface Builder and then call this method on your `IBOutletCollection`s in `viewDidLoad()`.
- author: Scott Gardner
- seealso:
* [Source on GitHub](http://bit.ly/SortUIViewsInPlaceByTag)
*/
mutating func sortUIViewsInPlaceByTag() {
sortInPlace { (left: Element, right: Element) in
left.tag < right.tag
}
}
}
/**
Sorts an array of `UIView`s or subclasses by `tag`. For example, this is useful when working with `IBOutletCollection`s, whose order of elements can be changed when manipulating the view objects in Interface Builder. Just tag your views in Interface Builder and then call this method on your `IBOutletCollection`s in `viewDidLoad()`.
- author: Scott Gardner
- seealso:
* [Source on GitHub](bit dot ly/SortUIViewsInPlaceByTag)
*/
mutating func sortUIViewsInPlaceByTag() {
sort { (left: Element, right: Element) in
left.tag < right.tag
}
}
}
self.dayDigits.sortUIViewsInPlaceByTag()
func updateDayDigits(countString: String){
for i in 0...4 {
dayDigits[i].image = offDigitImage
}
let length = countString.count - 1
for i in 0...length {
let char = Array(countString)[length-i]
dayDigits[i].image = digitImages[char.wholeNumberValue!]
}
}