Equivalent of C++ STL container “pair<T1, T2>” in Objective-C?

a 夏天 提交于 2019-12-03 11:26:11

You can use the STL in Objective-C++. All you need to do is change the extension of your .m file to .mm and I would also advise you use #import instead of #include. That way you can use your pair STL container.

You can write your own data structure object - for such a simple case, it would be pretty easy:

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

And a matching implementation, then you stick your Pair objects into the NSArray problem free.

Using anonymous struct and struct literals, you might be able to do something like

NSValue * v = [NSValue valueWithBytes:(struct {NSInteger i; bool b;}){i,b} objCType:(struct {NSInteger i; bool b;})];

and then to read,

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

It's a bit cleaner if you name your struct though.

How about a Pair category on NSNumber that uses associated objects, something like the code below (untested, may require iOS4 as I'm not sure when associated objects were introduced).

#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

You would use it like so:

BOOL myBool = NO;

NSNumber *storedBool = [NSNumber numberWithBool:myBool];

[myOtherNumber pairNumber:storedBool];

And to get it out:

NSNumber *boolNumber = [myOtherNumber pairedNumber];

Yet another option, is to (ab)use a single-entry NSDictionary for storing the pair - since NSDictionary can now be defined to force typed "key" and "value" and also supports literals as syntactic sugar. The drawback - the pair can only hold NSObjects (instance references) and not primitive values.

A sample would look like this:

typedef NSDictionary<NSString *, NSDate *> *Pair;

And then in your code:

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

Go on and print the results:

NSLog(@"%@", myArrayOfPairs);

and it looks very much like what you'd expect.

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";
  }
)

Payback time comes as you try to extract values from the so-called "Pair". You have to actually dig that single entry from the NSDictionary, not by its "Key" as usual, but assuming there's only one entry, like this:

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

which finally yields:

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

I don't especially recommend this alternative, but it has its niceties and benefits.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!