【问题标题】:Populate and bind an NSTableView to multiple array controllers填充 NSTableView 并将其绑定到多个数组控制器
【发布时间】:2012-07-30 02:08:24
【问题描述】:

我有一个 API 为 NSArray 提供了一堆内容对象——我们称之为acquiredFruit——和一个名为likedFruit 的空 NSMutableArray。

我已经为这两个数组创建了 NSArrayControllers 并将我的 TableView 绑定到 acquiredFruit.arrangedObjects。 tableView 的第一列绑定了arrangedObjects.name,并正确显示了所有美味的水果。

我创建了带有复选框的第二列 - 当用户填写该框时,我想将水果添加到我的 likedFruit 数组中。取消选中该框应该会从 likedFruit 数组中删除水果对象。

基本上我希望我的 NSTableView 加入两个数组控制器之间。我觉得我应该为此制作一个单独的控制器,但我不确定如何解决这个问题。

我还应该提到,我知道我可以遍历我的数组并使用我需要的字段构造另一个对象,但我的目标是尽可能使用绑定来做到这一点。

想法?

【问题讨论】:

  • 您是在另一个表中显示这些 likeFruits,还是只需要将它们放在一个数组中?
  • 我希望我的 acquireFruits 绑定表中的行的选中状态代表水果在 likeFruits 中的存在 - 我不需要另一个 tableVlew,但我计划在应用程序的其他地方迭代 likeFruits .

标签: objective-c macos cocoa cocoa-bindings nsarraycontroller


【解决方案1】:

我认为你应该使用一个数组控制器。

您可以在 Fruit 上拥有一个名为 liked 的属性。现在您的“喜欢”复选框列已连接到arrangedObjects.liked。稍后,当你想确定所有喜欢的水果的集合时,你可以查询你的 fruits 数组:

NSArray * likedFruits = [ allFruitsArray filteredArrayUsingPredicate:[ NSPredicate predicateWithFormat:@"liked = YES"] ] ;

如果在您的 UI 的另一部分中您只显示喜欢的水果,您可以将数组控制器的 filterPredicate 设置为上面的谓词以仅获取那些水果。

编辑:假设 NSFruit 是通过其他人的 API 提供的。让我们使用“为别人的类添加属性的通用技术”:

@interface NSFruit (Liking)
@property ( nonatomic ) BOOL liked ;
@end

@implementation NSFruit (Liking)

-(BOOL)liked
{
    return [ objc_getAssociatedObject( self, "_abliked" ) boolValue ] ;
}

-(void)setLiked:(BOOL)b
{
    objc_setAssociatedObject( self, "_abliked", [ NSNumber numberWithBool:b ], OBJC_ASSOCIATION_RETAIN_NONATOMIC ) ;
}

@end

(我最近为大约 100 个帖子编写了相同的代码!)

【讨论】:

  • 啊,这很有道理。如果 NSFruit 实际上是第三方 API 提供给我的对象?我需要包装它还是写一个类别?我想我可以创建自己的 ABFruit……
  • 我已经编辑了我的帖子以显示通过类别将“喜欢”作为属性添加到 NSFruit...
  • 酷,我实际上对类别很熟悉,只是总是犹豫要不要使用它们。我听到关于何时合适的相互矛盾的答案。
  • 好酷。就个人而言,我尽可能避免子类化。例如,我很少制作自定义视图,我只是组合现有视图的集合。我发现这有助于避免在架构上“把自己画到一个角落”,节省重构,保持你的类层次结构平坦等。我想听听人们何时使用类别的原因,因为我认为这些确实是罕见的情况..我想最好留给聊天讨论?
【解决方案2】:

我现在不在我的 Xcode 计算机上,所以我无法对此进行测试,但您似乎并不真的需要另一个阵列控制器,而只需要另一个阵列来保存 likeFruits。我认为您需要从您获取的Fruits 数组中创建一个字典数组,该数组将有一个用于水果名称的键和另一个带有布尔值的键,用于是否选中复选框-此布尔值将绑定到您的第二列。我不确定下一步如何告诉 likeFruit 数组它需要添加一个新水果——我认为该复选框可能有一个操作方法,您可以使用该方法让 likeFruit 数组将对象添加到单击复选框的行。

编辑后:

这是一个如何按照我的建议进行操作的示例。我将水果数组转换为字典数组(称为 theData),其中包含复选框值的键(在 IB 中,数组控制器的内容数组绑定到 theData,列绑定到数组 Controller.arrangedObjects.fruitName 和数组 Controller.arrangedObjects.isLiked)。 checkChanged 是一个连接到复选框的 IBAction(但请注意,发送者实际上是表格视图),我使用复选框的值来确定是添加一个水果到 likeFruits 还是删除一个。我又放了一个方法,连接到一个按钮,只是为了检查 likeFruits 中的值。

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    self.theData = [NSMutableArray array];
    self.likedFruit =[NSMutableArray array];
    NSArray *acquiredFruits = @[@"Apple",@"Orange",@"Pear",@"Peach"];
    for (NSString *aFruit in acquiredFruits) {
        NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:aFruit,@"fruitName",[NSNumber numberWithBool:NO],@"isLiked", nil];
        [self.theData addObject:[dict mutableCopy]];
    }
    self.theData = _theData;
   // NSLog(@"%@",self.theData);
}



-(IBAction)checkChanged:(NSTableView *)sender { //connected to the button cell in the table view (but sender is the table view)
    NSString *theFruit = [[self.controller.arrangedObjects objectAtIndex:sender.clickedRow ] valueForKey:@"fruitName"];
    BOOL doWeLikeIt = [[[self.controller.arrangedObjects objectAtIndex:sender.clickedRow] valueForKey:@"isLiked"] boolValue];
    if (doWeLikeIt) {
        [self.likedFruit addObject:theFruit];
    }else{
        [self.likedFruit removeObject:theFruit];
    }
}

-(IBAction)logLikedFruits:(id)sender {
     NSLog(@"%@",self.likedFruit);
}

【讨论】:

  • 你觉得可以详细说明一下吗?
  • 感谢@rdelmar,这个答案很有意义。这是从多个来源组成阵列控制器的一个很好的例子。我认为 Category 方法更适合我的用例,让我绑定到 API 提供的数组。对于其他情况,我一定会牢记这一点!
  • 也许我不明白您所说的 API 提供的数组是什么意思。虽然我的方法不允许您直接绑定到数组,但它允许您从该数组创建一个新的字典数组。
猜你喜欢
  • 1970-01-01
  • 2016-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多