在Objective-C中,与C++ STL容器中的“pair<T1, T2>”等效的是什么?

15
我刚接触Objective-C,所以请不要过于苛刻地评价我。我想知道:在Objective-C中,是否有类似于C++ STL的pair容器可以使用?
我想构建一个数组,其中包含一个NSInteger和一个NSBool。我知道可以使用一个包含单个键值对的NSDictionary数组,但我认为这样有点过度了。
你有什么想法吗?
谢谢!

虽然在Objective-C(或实际上,Cocoa Foundation框架)中没有“Pair”的自然替代品,但下面的几个答案提供了可接受的解决方案。我还添加了一种有些强制的解决方案,它将以类似的方式行为 - 但选择正确的解决方案在很大程度上取决于您实际使用的情况。 - Motti Shneor
5个回答

16

您可以编写自己的数据结构对象 - 对于这种简单情况,这将非常容易:

@interface Pair : NSObject 
{
    NSInteger integer;
    BOOL      boolean;
}
@property (nonatomic, assign) integer;
@property (nonatomic, assign) boolean;
@end

然后使用相应的实现,你就可以毫无问题地将Pair对象放入NSArray中。


4
@Martin,完全正确。但是OP似乎表明他想要一个特定的属性对。将此处的两个属性替换为id即可完成任务。 - Carl Norum

7

您可以在 Objective-C++ 中使用 STL。您只需要将 .m 文件扩展名更改为 .mm,我还建议您使用 #import 而不是 #include。这样您就可以使用您的pair STL容器。


1
请记住,STL容器不会“保留”和“释放”对象。 - dreamlax

1
使用匿名结构体和结构体字面量,你可能能够像这样做一些事情
NSValue * v = [NSValue valueWithBytes:(struct {NSInteger i; bool b;}){i,b} objCType:(struct {NSInteger i; bool b;})];

然后进行阅读,

struct {NSInteger i; bool b;} foo;
[v getValue:&foo];

如果你给你的结构体命名,代码会更加清晰。


0

NSNumber上加一个Pair类别如何?使用关联对象,像下面的代码一样(未经测试可能需要iOS4,因为我不确定关联对象是什么时候引入的)。

#import <objc/runtime.h>

@implementation NSNumber(Pair)

#define PAIR_KEY 'p'

- (NSNumber *) pairNumber:(NSNumber *)second
{
    char secondKey = PAIR_KEY;
    objc_setAssociatedObject(self, &secondKey, second, OBJC_ASSOCIATION_RETAIN);
    return self;
}

- (NSNumber *) pairedNumber
{
    char secondKey = PAIR_KEY;
    NSNumber *associatedObject = (NSNumber *)objc_getAssociatedObject(self, &secondKey);    
    return associatedObject;
}

@end

你可以这样使用:

BOOL myBool = NO;

NSNumber *storedBool = [NSNumber numberWithBool:myBool];

[myOtherNumber pairNumber:storedBool];

并将其取出:

NSNumber *boolNumber = [myOtherNumber pairedNumber];

0
另一个选择是,滥用单条目NSDictionary来存储这对值 - 因为现在可以定义NSDictionary以强制类型化的“键”和“值”,并且还支持字面量作为语法糖。缺点是,这对值只能容纳NSObjects(实例引用),而不能容纳原始值。
示例如下:
typedef NSDictionary<NSString *, NSDate *> *Pair;

然后在你的代码中:

Pair myPair = @{@"my name": [NSDate date]};
Pair myOtherPair =  @{@"his name": [NSDate date]};
NSArray<Pair> *myArrayOfPairs = @[myPair, myOtherPair];

继续并打印结果:
NSLog(@"%@", myArrayOfPairs);

它看起来非常像你所期望的。

2019-03-18 16:08:21.740667+0200 TesterApp[23135:23269890] (
  {
    "my name" = "2019-03-18 14:08:21 +0000";
  },
  {
    "his name" = "2019-03-18 14:08:21 +0000";
  }
)

当你试图从所谓的“Pair”中提取值时,回报时间就到了。你必须实际从NSDictionary中挖掘这个单一的条目,而不是像通常那样通过它的“Key”,但假设只有一个条目,就像这样:

Pair somePair = myArrayOfPairs.lastObject;
NSString *name = somePair.allKeys.firstObject;
NSDate *date = somePair.allValues.firstObject;
NSLog(@"name: %@ date: %@", name, date);

最终产生:

name: his name date: Mon Mar 18 16:16:43 2019

我并不特别推荐这种替代方案,但它有其优点和好处。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接