【问题标题】:Does the iOS SDK provide queues and stacks?iOS SDK 是否提供队列和堆栈?
【发布时间】:2011-04-08 20:07:04
【问题描述】:

我正在编写一个 iPhone 应用程序,我很惊讶 Apple 的 Foundation Framework 中似乎没有 NSQueue 或 NSStack 类。我发现自己推出自己的产品很容易,从NSMutableArray 开始,所以除非我错过了什么,否则我会这样做。我错过了什么吗?

【问题讨论】:

    标签: stack queue ios


    【解决方案1】:

    据我所知,没有可用的通用类。尝试使用 NSMutableArray,通过 addObject 添加并通过 objectAtIndex 和 removeObjectAtIndex 获取第一个/最后一个。

    【讨论】:

    • 请注意,removeObjectAtIndex 是一个 O(n) 操作,因此当项目数量预计很大时,这可能不是队列的最佳方法。使用链表(允许从任何点进行有效的添加和删除)可能要好得多,但不幸的是,这是基础中缺少的另一种常见集合类型,因此您也必须实现它。
    【解决方案2】:

    是的,NSMutableArray 兼作堆栈或队列。 (作为队列,效率会稍低。)

    您也可以使用 C++ 的 stackqueue 适配器,但是如果您想用它来存储 Objective-C 对象,它会使内存管理有点混乱。

    【讨论】:

      【解决方案3】:

      没有。你什么都没错过。就这样。 Objective-C 是高级语言,看起来像 C。不需要低级控制。

      Cocoa 类的设计目的是为了便于使用而不是提高效率。如果您想处理性能问题,您可以选择原始 C(或 C++)实现。否则,只需使用简单的方法。当然,早期优化是邪恶的。

      如果你想要一种封装,只需创建一个包含 NSMutableArray 的新类。隐藏内部 NSMutableArray 并公开您想要的内容。但你会意识到这是不必要的。

      【讨论】:

      • 谢谢。我担心的是代码重复,而不是封装。
      • 不使用队列是邪恶的!你知道它的影响吗? NSMutable 数组不仅仅是为了易于使用而设计的(顺便说一句,它们并不容易使用!),它们实际上是高效的,并且如上所述,可用于实现队列。
      • @PizzaiolaGorgonzola 很抱歉,但很难理解您在此评论中的真正意思。而且我从来没有告诉过 Cocoa 类是低效的。我说的是 Cocoa 类与 C(或 C++)级别的对应物相比效率相对较低且更易于使用。
      【解决方案4】:

      这是我的 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方法,使用[contents lastObject]可以节省一点打字。如果数组为空,则返回 nil。我最终将这些方法实现为 NSMutableArray 上的一个类别。感谢您的代码!
      • 就个人而言,我可能只是通过类别将pop 方法添加到NSMutableArray,并在需要堆栈的地方直接使用NSMutableArray,而不是创建一个全新的Stack班级。我以前使用过的大多数语言都没有专用的堆栈类,而是使用数组作为堆栈。不过,我想我可以从可读性的角度看到一个只能用作堆栈的类的优雅。
      【解决方案5】:

      我已经在 GitHub 上放置了一个可用的 iOS 目标 C 队列对象。代码取自各种帖子,绝不归我所有。

      https://github.com/esromneb/ios-queue-object/

      如果您发现任何问题,请分叉,并提出拉取请求!

      【讨论】:

        【解决方案6】:

        我参加这个聚会有点晚了,但你知道 CHDataStructures 吗?

        http://cocoaheads.byu.edu/code/CHDataStructures

        【讨论】:

        • 这太棒了!感谢分享!
        【解决方案7】:

        另一种简单的方法是通过使用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,并在该对象上调用 pushpop。不要忘记在这些文件中#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
        

        【讨论】:

          【解决方案8】:

          ObjectiveSugar 是一个非常受欢迎的 CocoaPod,它提供了许多其他很棒的东西,在 NSMutableArray 上的 pushpop API 调用。当然,它不在 iOS SDK 中,但我在这里分享它是因为我在寻找同样的东西,这就是我采用的解决方案(当然,我们已经在我们的代码库)。

          【讨论】:

            猜你喜欢
            • 2021-11-08
            • 2013-09-18
            • 2014-07-21
            • 2015-11-16
            • 2019-03-07
            • 2021-04-29
            • 1970-01-01
            • 2021-03-17
            • 2014-04-21
            相关资源
            最近更新 更多