Objective-C创建和访问可变数组

时间:2015-05-01 10:13:33

标签: objective-c nsmutablearray

我正在尝试创建一个NSMutableArray来保存一些对象,但我真的很难理解创建一个main.m中我的所有方法都可以添加和访问的正确语法。

我试过在我想要存储数组的对象的接口中使它成为@property,我也尝试创建一个自定义初始化方法,但是在创建对象的方法之外并将其添加到数组我在阵列名称上获得未声明的标识符错误。

我更习惯java,我可以创建所有方法都可以访问的数组,但我知道Objective-C不允许这样做。有人可以帮我一个方法并给我一个代码示例来创建一个NSMutableArraymain.m中的所有方法都可以访问吗?

3 个答案:

答案 0 :(得分:6)

免责声明:您在main.m中编写代码这一事实表明您已经在Xcode中启动了一个控制台应用程序项目,并且没有尝试编写Cocoa或Cocoa Touch应用程序。

如果您正在尝试为OS X或iOS编写Cocoa或Cocoa Touch应用程序,则main.m文件应如下所示:

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

在修改之前你应该知道你在做什么(99.999%的时间,你永远不需要为Cocoa / Cocoa Touch应用程序触摸这个文件)。

所以重申一下,这个答案假设你正在编写一个简单的控制台应用程序来教你自己一些Objective-C基础知识。

如果这个假设不正确,你的问题应该被关闭,因为你不清楚你在问什么。

答案

Objective-C是C的严格超集。因此,我们可以在C中做任何事情,我们也可以在Objective-C中做。这包括在全局范围内声明变量。这与Java不同。在Java中,一切都是对象 - 所有东西都驻留在类文件中。这包括main方法。例如:

public class MyApplication
{ 
    public static Object[] myArray;
    public static void main(String [] args)
    {
        // execution begins here
    }

}

这与Objective-C不同。并非所有内容都必须位于Objective-C中的类中。如果我们想在Objective-C中使用全局变量,我们只需在全局范围内声明它。例如:

的main.m

#import <Foundation/Foundation.h>

NSMutableArray * myArray;

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        myArray = [NSMutableArray array];
    }
    return 0;
}

我们可以在myArray内的任何地方使用main.m

让我们在这里注意一些事情......如果它不是一个类的成员,它被称为函数,而不是方法。所以我们也可以在这个全局范围内声明C风格的函数

NSMutableArray * myArray;

void appendHelloWorld() {
    [myArray addObject:@"Hello World"];
}

NSInteger myArrayCount() {
    return myArray.count;
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        myArray = [NSMutableArray array];
        while (myArrayCount() < 10) {
            appendHelloWorld();
        }
        NSLog(@"%@", myArray);
    }
    return 0;
}

这一切都很好。如果我们运行此程序,我们将得到以下输出:

2015-05-01 13:22:21.188 ObjC[18340:4210463] (
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World"
)

但......这不是正确的方法......

我只是向你展示了如何完全满足你的要求,但我们真的不希望以这种方式做事。这是使用全局变量作为一切答案的途径。这是使用单身人士作为一切答案的途径。这是编写具有12个不同单例类的应用程序的路径(我已经看过了)。这不是斯巴达的道路 - 这是疯狂的道路。

相反,我们应该处理对象的实例。

我们的函数(或者我们毕业于类,我们的方法)应该传递一个参数,我们不应该在全局范围内有变量。

所以,让我们摆脱全局变量并修改我们的方法:

void appendHelloWorld(NSMutableArray *array) {
    [array addObject:@"Hello World"];
}

NSInteger arrayCount(NSArray *array) {
    return array.count;
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSMutableArray *myArray = [NSMutableArray array];
        while (arrayCount(myArray) < 10) {
            appendHelloWorld(myArray);
        }
        NSLog(@"%@", myArray);
    }
    return 0;
}

运行此程序可为我们提供相同的输出:

2015-05-01 13:27:48.594 ObjC[18361:4213356] (
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World",
    "Hello World"
)

它还使我们的代码更加灵活。我们的函数appendHelloWorld基于代码的没有紧密耦合。它可以从这里进入其他任何地方并完全按照预期执行。它没有任何东西。它会将字符串@"Hello World"放到它传递的任何可变数组上。虽然arrayCount()实际上是不必要的(仅仅使用它作为例子),但我们可以说它的所有相同的东西。

我们不想使用全局变量,我们不希望函数或方法与全局变量紧密耦合。我们需要熟悉实例化对象实例并将这些对象传递给需要它们的方法或函数的想法。

当多个类访问某些共享内存存储非常重要时,应使用而不是单身人士 - - 这不是单身人士的目的。当你需要确定在应用程序的生命周期中只有一个类实例被实例化时,应该使用单例。

答案 1 :(得分:1)

不是我真的明白为什么你想在main.m中有很多功能。实现你想做的,但可能不想做的一种方法是创建一个带有静态实例的类

@interface GlobalArrayHolder

@property (nonatomic, readonly) NSMutableArray *globalArray;

+ (instancetype)sharedGlobalArrayHolder;

@end

使用类似

的实现
@implementation GlobalArrayHolder

@synthesize globalArray = _globalArray

- (instancetype) init {
   self = [super init];
   if (self) {
      _globalArray = [NSMutableArray arrayWithCapacity:5];
   }

   return self;
}

+ (instancetype) sharedGlobalArrayHolder {
    static GlobalArrayHolder *localGlobalArrayHolder = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
      localGlobalArrayHolder = [[GlobalArrayHolder alloc] init];
    });

    return localGlobalArrayHolder;
}

@end

您想要了解iOS或OS X应用程序的实际工作方式并了解应用程序代理。在main.m中添加很多功能听起来真的很糟糕。

如果@nhgrif是正确的,你只想开始使用Objective-C,你可以在main.m的文件范围内将数组声明为静态

#import <Foundation/Foundation.h>

static NSMutableArray *globalArray = nil;

int main(int argc, const char *argv[])
{
   globalArray = [NSMutableArray arrayWithCapacity:5];

   return 0;
}

请注意,这绝对不是编写iOS或OS X应用程序的方法。主要应该做的唯一事情是调用UIApplicationMainNSApplicationMain,可能在@autoreleasepool { }内。然后XXApplicationMain方法在调用应用程序委托之前进行设置,然后开始实现实际工作。

使用命令行中的clang进行编译:{{1​​}}

答案 2 :(得分:0)

我认为这是一个初学者的问题。但是,MutableArrays有时候会很棘手。

首先要提到的是:NSMutableArrays不是线程安全的。如果将它们存储为属性,请记住这一点。

如果您想要从ALL方法访问的内容,您有很多选择。这取决于您所需的软件架构。

全局可访问数据最简单的方法是NSUserDefaults(对于偏好等值,不常存储)。

如果您需要处理该数据,您可以简单地创建一个所谓的单例。单例是一个只存在一次的类实例。这个类的行为就像你的java例子。如果您访问该类,则所有值都无处不在。一般来说,使用objC进行java风格开发并不是一个好建议。编写好的代码总是有另一种选择。要将数据从类传输到另一个类,您可以使用NSNotifications。另一个好处是使用委托(搜索委托和@protocol)。

在您的特殊情况下,以下代码应该有效。我们称之为单身人士。它是一个只有一个实例并且可以从任何地方访问的类:

.h文件:

#import <Foundation/Foundation.h>
@interface MySingletonClass : NSObject

@property(nonatomic, strong) NSMutableArray *list;
+(MySingletonClass*) sharedInstance;
@end

.m文件:

#import "MySingletonClass.h"

@implementation MySingletonClass

+(MySingletonClass*) sharedInstance {

    static MySingletonClass* theInstance = nil;
    if (!theInstance) {

        theInstance = [[MySingletonClass alloc] init];

        // The following line initializes an empty array
        theInstance.list = [NSMutableArray array];
    }

    return theInstance;
}
@end

现在您可以在任何地方导入此类

#import "MySingletonClass.h"

并像这样使用它:

[[MySingletonClass sharedInstance].list addObject:@"Example object"]; 

如果你习惯了java&#39;你可能会切换到swift。语法更类似于java。