【发布时间】:2011-04-08 20:07:04
【问题描述】:
我正在编写一个 iPhone 应用程序,我很惊讶 Apple 的 Foundation Framework 中似乎没有 NSQueue 或 NSStack 类。我发现自己推出自己的产品很容易,从NSMutableArray 开始,所以除非我错过了什么,否则我会这样做。我错过了什么吗?
【问题讨论】:
我正在编写一个 iPhone 应用程序,我很惊讶 Apple 的 Foundation Framework 中似乎没有 NSQueue 或 NSStack 类。我发现自己推出自己的产品很容易,从NSMutableArray 开始,所以除非我错过了什么,否则我会这样做。我错过了什么吗?
【问题讨论】:
据我所知,没有可用的通用类。尝试使用 NSMutableArray,通过 addObject 添加并通过 objectAtIndex 和 removeObjectAtIndex 获取第一个/最后一个。
【讨论】:
removeObjectAtIndex 是一个 O(n) 操作,因此当项目数量预计很大时,这可能不是队列的最佳方法。使用链表(允许从任何点进行有效的添加和删除)可能要好得多,但不幸的是,这是基础中缺少的另一种常见集合类型,因此您也必须实现它。
是的,NSMutableArray 兼作堆栈或队列。 (作为队列,效率会稍低。)
您也可以使用 C++ 的 stack 和 queue 适配器,但是如果您想用它来存储 Objective-C 对象,它会使内存管理有点混乱。
【讨论】:
没有。你什么都没错过。就这样。 Objective-C 是高级语言,看起来像 C。不需要低级控制。
Cocoa 类的设计目的是为了便于使用而不是提高效率。如果您想处理性能问题,您可以选择原始 C(或 C++)实现。否则,只需使用简单的方法。当然,早期优化是邪恶的。
如果你想要一种封装,只需创建一个包含 NSMutableArray 的新类。隐藏内部 NSMutableArray 并公开您想要的内容。但你会意识到这是不必要的。
【讨论】:
这是我的 Stack 课程,以防它对追随我的人有用。如您所见,pop 方法包含足够多的代码,您需要将其分解出来。
堆栈.h:
#import <Foundation/Foundation.h>
@interface Stack : NSObject {
NSMutableArray *contents;
}
- (void)push:(id)object;
- (id)pop;
@end
堆栈.m
#import "Stack.h"
@implementation Stack
// superclass overrides
- (id)init {
if (self = [super init]) {
contents = [[NSMutableArray alloc] init];
}
return self;
}
- (void)dealloc {
[contents release];
[super dealloc];
}
// Stack methods
- (void)push:(id)object {
[contents addObject:object];
}
- (id)pop {
id returnObject = [[contents lastObject] retain];
if (returnObject) {
[contents removeLastObject];
}
return [returnObject autorelease];
}
@end
【讨论】:
pop 方法添加到NSMutableArray,并在需要堆栈的地方直接使用NSMutableArray,而不是创建一个全新的Stack班级。我以前使用过的大多数语言都没有专用的堆栈类,而是使用数组作为堆栈。不过,我想我可以从可读性的角度看到一个只能用作堆栈的类的优雅。
我已经在 GitHub 上放置了一个可用的 iOS 目标 C 队列对象。代码取自各种帖子,绝不归我所有。
https://github.com/esromneb/ios-queue-object/
如果您发现任何问题,请分叉,并提出拉取请求!
【讨论】:
我参加这个聚会有点晚了,但你知道 CHDataStructures 吗?
【讨论】:
另一种简单的方法是通过使用Objective C 的类别来扩展NSMutableArray 的功能。您可以通过向项目中添加两个文件来做到这一点:
NSMutableArray+Stack.h
@interface NSMutableArray (StackExtension)
- (void)push:(id)object;
- (id)pop;
@end
NSMutableArray+Stack.m
#import "NSMutableArray+Stack.h"
@implementation NSMutableArray (StackExtension)
- (void)push:(id)object {
[self addObject:object];
}
- (id)pop {
id lastObject = [self lastObject];
[self removeLastObject];
return lastObject;
}
@end
现在您可以在项目的每个其他文件(如堆栈)中使用常规 NSMutableArray,并在该对象上调用 push 或 pop。不要忘记在这些文件中#import NSMutableArray+Stack.h。以下是一些示例代码,您可以如何将新的 NSMutableArray 用作堆栈:
NSMutableArray *myStack = [[NSMutableArray alloc] init]; // stack size = 0
NSString *aString = @"hello world";
[myStack push:myString]; // stack size = 1
NSString *anotherString = @"hello universe";
[myStack push:anotherString]; // stack size = 2
NSString *topMostStackObject;
topMostStackObject = [myStack pop]; // stack size = 1
NSLog("%@",topMostStackObject);
topMostStackObject = [myStack pop]; // stack size = 0
NSLog("%@",topMostStackObject);
日志输出将是:
hello universe
hello world
【讨论】:
ObjectiveSugar 是一个非常受欢迎的 CocoaPod,它提供了许多其他很棒的东西,在 NSMutableArray 上的 push 和 pop API 调用。当然,它不在 iOS SDK 中,但我在这里分享它是因为我在寻找同样的东西,这就是我采用的解决方案(当然,我们已经在我们的代码库)。
【讨论】: