我在NSArray
上编写了一个类别,以便将JavaScript数组方法添加到NSArray
。在JavaScript中,splice()
方法向数组添加/删除项目。但是添加到阵列的对象数量可能会有所不同。所以我使用va_list
来允许更灵活地输入对象值。
目前,该方法需要计数输入值。如果没有一个我怎么能重写呢?
接口
@interface NSArray (JavaScriptArray)
- (NSArray *)splice:(NSUInteger)index remove:(NSUInteger)remove count:(NSUInteger)count arguments:(id)firstObject,...;
@end
实施
@implementation NSArray (JavaScriptArray)
- (NSArray *)splice:(NSUInteger)index remove:(NSUInteger)remove count:(NSUInteger)count arguments:(id)firstObject,...
{
NSMutableArray *mSplice = [NSMutableArray arrayWithArray:self];
if (remove != 0) {
NSUInteger removeIndex = index;
for (NSUInteger i = 0; i < remove; i++) {
[mSplice removeObjectAtIndex:removeIndex];
removeIndex = removeIndex + 1;
}
}
if (count != 0) {
NSUInteger addIndex = index;
id eachObject;
va_list argumentList;
if (firstObject) {
[mSplice insertObject:firstObject atIndex:addIndex];
addIndex = addIndex + 1;
va_start(argumentList, firstObject);
eachObject = va_arg(argumentList, id);
for (NSUInteger i = 0; i < count; i++) {
[mSplice insertObject:eachObject atIndex:addIndex];
addIndex = addIndex + 1;
}
va_end(argumentList);
}
}
return [NSArray arrayWithArray:mSplice];
}
@end
调用方法
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *fruit = @[@"Banana", @"Orange", @"Apple", @"Mango"];
NSArray *fruitSplice = [fruit splice:2 remove:0 count:4 arguments:@"Lemon", @"Kiwi", @"Kiwi", @"Kiwi"];
NSLog(@"fruitSplice %@", fruitSplice);
}
@end
调试器窗口
fruitSplice (
Banana,
Orange,
Lemon,
Kiwi,
Kiwi,
Kiwi,
Kiwi,
Apple,
Mango
)
答案 0 :(得分:1)
删除count
参数没有问题,因为实际上你的&#34;添加&#34;循环似乎不正确。在您使用va_list
从eachObject = va_arg(argumentList, id);
获得第二项后,您永远不会得到另一个对象。您的示例有效的唯一原因是所有后续项目都相同:@"Kiwi"
。如果您的测试呼叫是
NSArray *fruitSplice = [fruit splice:2
remove:0
count:4
arguments:@"Lemon", @"Albatross", @"Kiwi", @"Kiwi"];
你看
fruitSplice (
Banana,
Orange,
Lemon,
Albatross,
Albatross,
Albatross,
Albatross,
Apple,
Mango
)
作为输出。
您需要重新打开va_list
的解包,并且在重复迭代时可以保留自己的计数器,但问题是必须有哨兵值:一个无法显示为有效列表值的值,表示您已经到了最后。对于对象类型可变参数,通常使用nil
作为标记。
当您使用va_list
时,您必须 一个哨兵或一个计数。你不知道何时停止弹出论据。
您的签名可以变成*:
- (NSArray *)KRSpliceAt:(NSUInteger)index
removingCount:(NSUInteger)remove
addingObjects:(id)firstObject, ... NS_REQUIRES_NIL_TERMINATION;
NS_REQUIRES_NIL_TERMINATION
是严格可选的,但如果在没有标记的情况下调用该方法,编译器会通知您。
然后你的添加循环改变了:
// Insertion index starts at given splice point
NSUInteger addIndex = index;
// Initialize the va_list
va_list objs;
va_start(objs, firstObj);
// Start at the beginning
id nextObj = firstObj;
// Test for sentinel nil
while( nextObj ){
[mSplice insertObject:nextObj atIndex:addIndex];
// Update insertion point
addIndex++;
// Get next argument
nextObj = va_arg(objs, id);
}
// Signal completion of list
va_end(objs);
*您添加到您不拥有的课程的方法应始终加上前缀。这有点令人讨厌,但如果您碰巧选择与其他方法相同的名称,那么防止发生灾难性冲突是一种很好的做法。