如何在Objective-C中实现C++的vector-pair功能及解决取值问题
解决Objective-C中存储类似C++ pair并取值、排序的问题
作为Objective-C新手,你遇到的核心问题是NSMutableArray只能存储Objective-C对象,不能直接存C语言结构体——你之前能存入是因为可能隐式做了包装,但取出时没正确还原结构体,导致取值错误。下面分两部分帮你解决:
一、正确取出结构体的方法
假设你定义的结构体是这样的(对应C++的pair<ll, int>):
typedef long long ll; typedef struct { ll first; int second; } MyPair;
存入时的正确操作
必须用NSValue把结构体包装成Objective-C对象,才能存入NSMutableArray:
NSMutableArray *pairArray = [NSMutableArray array]; // 创建结构体实例 MyPair pair1 = {123LL, 45}; // 用NSValue包装结构体 NSValue *pairValue1 = [NSValue valueWithBytes:&pair1 objCType:@encode(MyPair)]; [pairArray addObject:pairValue1]; // 可以继续添加更多结构体 MyPair pair2 = {78LL, 9}; NSValue *pairValue2 = [NSValue valueWithBytes:&pair2 objCType:@encode(MyPair)]; [pairArray addObject:pairValue2];
取出时的正确操作
从数组中拿到NSValue后,需要调用getValue:方法把结构体还原出来:
// 取出第一个元素 NSValue *targetValue = pairArray[0]; MyPair retrievedPair; // 把NSValue中的数据拷贝到结构体变量里 [targetValue getValue:&retrievedPair]; // 现在可以正常访问结构体的值了 NSLog(@"First: %lld, Second: %d", retrievedPair.first, retrievedPair.second);
二、更简便的实现方式
用NSValue包装结构体虽然可行,但步骤繁琐,对于新手来说,更推荐两种更直观的方案:
方案1:自定义Objective-C类(最推荐)
直接创建一个类来模拟pair,类型安全且操作简单:
// Pair.h #import <Foundation/Foundation.h> typedef long long ll; @interface Pair : NSObject @property (nonatomic, assign) ll first; @property (nonatomic, assign) int second; @end // Pair.m #import "Pair.h" @implementation Pair @end
存储与取值
NSMutableArray *pairArray = [NSMutableArray array]; // 创建对象并赋值 Pair *pair1 = [[Pair alloc] init]; pair1.first = 123LL; pair1.second = 45; [pairArray addObject:pair1]; // 取出直接访问属性 Pair *retrievedPair = pairArray[0]; NSLog(@"First: %lld, Second: %d", retrievedPair.first, retrievedPair.second);
排序(对应C++ vector的排序)
用sortUsingComparator:方法,通过block自定义排序规则(比如按first升序,first相同则按second升序):
[pairArray sortUsingComparator:^NSComparisonResult(Pair *obj1, Pair *obj2) { if (obj1.first != obj2.first) { return obj1.first > obj2.first ? NSOrderedDescending : NSOrderedAscending; } else { return obj1.second > obj2.second ? NSOrderedDescending : NSOrderedAscending; } }];
方案2:使用NSDictionary(快速实现,无需自定义类)
如果不想写额外的类,可以用字典存储键值对,缺点是类型不够安全(需要手动转换类型):
NSMutableArray *pairArray = [NSMutableArray array]; // 存储字典 NSDictionary *pairDict1 = @{@"first": @(123LL), @"second": @(45)}; [pairArray addObject:pairDict1]; // 取出并转换类型 NSDictionary *retrievedDict = pairArray[0]; ll first = [retrievedDict[@"first"] longLongValue]; int second = [retrievedDict[@"second"] intValue]; NSLog(@"First: %lld, Second: %d", first, second);
排序
同样用sortUsingComparator::
[pairArray sortUsingComparator:^NSComparisonResult(NSDictionary *d1, NSDictionary *d2) { ll f1 = [d1[@"first"] longLongValue]; ll f2 = [d2[@"first"] longLongValue]; if (f1 != f2) { return f1 > f2 ? NSOrderedDescending : NSOrderedAscending; } else { int s1 = [d1[@"second"] intValue]; int s2 = [d2[@"second"] intValue]; return s1 > s2 ? NSOrderedDescending : NSOrderedAscending; } }];
总结
- 如果追求类型安全和代码可读性,优先用自定义Objective-C类;
- 临时快速实现可以用
NSDictionary; - 坚持用结构体的话,务必记住用
NSValue包装/还原的步骤。
内容的提问来源于stack exchange,提问作者user6298177
相关产品推荐
相关产品推荐

