我希望得到如下结构:
struct foo {
NSString Title;
NSInteger numberOfBooks;
vector of NSStrings Books;
};
foo bar[50];
现在首先,我想知道如何创建一个字符串数组(每行包含一个书名)。
然后我想知道我写的代码是否正确。
最后,我可以使用bar [n] .Title?
访问结构的所述元素我按照你评论的内容,以及它的外观:
@interface Foo : NSObject {
NSString *name;
NSArray *books;
}
@end
A->name = @"Clancy, Thomas";
A->books = [[NSArray alloc] initWithObjects:@"Book 1"
@"Book2",nil];
self.authors = [[NSArray alloc] initWithObjects:A, nil];
现在它给了我实例变量'name'受保护。我尝试写公开:在定义Foo时,但它不接受。 (是的,我是Obj-C的新手)。
答案 0 :(得分:6)
不幸的是,启用了自动引用计数(ARC)的Objective C不允许C结构内的对象。 Objc也只允许NSArrays中的对象(向量的松散等价物)。
解决方案的第一步是创建一个类而不是结构:
// Foo.h
#import <Foundation/Foundation.h>
@interface Foo : NSObject
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSArray *books;
// no need to keep the number of items in an NSArray as a separate variable,
// NSArray does that for you.
- (id)initWithTitle:(NSString *)title books:(NSArray *)books;
@end
// Foo.m
#import "Foo.h"
@implementation Foo
@synthesize title;
@synthesize books;
- (id)initWithTitle:(NSString *)title books:(NSArray *)books
{
if (self = [super init]) {
self.title = title;
self.books = books;
}
return self;
}
@end
请注意,所有对象类型都是指针。这是因为objc中的所有对象都是堆分配的,因此您不能对不是指针的对象进行对象。另请注意,NSArray
类型未参数化。那是因为objc没有泛型模板的概念,所以数组的内容可以是任何对象。这通常不是问题,但偶尔会在编译时捕获类型错误。
保持这些Foo
对象的数组很简单。你可能只是像Foo *bar[50];
那样创建一个C数组,但我认为它不适用于ARC,并且它绝对不是在目标c中执行它的正确方法。正确的方法是使用另一个NSArray:NSArray *bar = [[NSArray alloc] init];
,或使用objc2.0语法:NSArray *bar = @[];
@property
和@synthesize
是用于为if创建实例变量和访问器方法的快捷方式。如果要从类外部(或更确切地说,实现文件)访问实例变量,则需要访问器方法。 strong
标志告诉引用计数器这是一个强引用,比如来自c ++ boost库的shared_ptr。我不知道nonatomic
做了什么,但我被告知你需要它。
方法initWithTitle:books:
就像一个构造函数,除了objc没有构造函数的概念。该实现使用self = [super init]
调用超类的构造函数(假设self是对象的c ++引用)。构造函数可以返回nil,这就是为什么你需要if块。
行self.title = title;
在技术上是[self setTitle:title];
的简写,它使用由@property
和@synthesize
自动生成的方法。
答案 1 :(得分:2)
可以将Objective-C中的C结构封装到通用NSValue
容器中。您可以使用[NSValue value:withObjCType:]
对值进行编码,使用[NSValue getValue:]
来获取该值。然后,您可以将新的NSValue *
对象添加到任何Objective-C容器中。
有关示例,请参阅this,有关类型编码的详细信息,请参阅this。
请注意,装箱/拆箱不是免费的,因此如果您正在编写性能关键型应用程序,我建议您使用std::vector
或其他C ++容器,以避免每次存储/获取项目时都执行此过程
答案 2 :(得分:0)
在Objective-C中,您最好使用NSDictionaries或自定义对象而不是结构。扩展H2CO3的注释 - 您可以声明一个BookCollection类
BookCollection.h
#import <Foundation/Foundation.h>
@interface BookCollection: NSObject
@property (nonatomic, strong) NSString* title
@property (nonatomic, strong) NSArray* books
//use NSArray* for a static array or NSMutableArray* for a dynamic array
@end
BookCollection.m
#import "BookCollection/BookCollection.h"
@implementation BookCollection
@end
您的实现为空,因为您的对象只有公共属性而没有自定义方法。我们使用@property语法来声明我们的实例变量,因为这带来了许多优点,例如内置的getter和setter。 (有关详细信息,请参阅我的回答here)
与C ++不同,您可以在集合类中混合对象类型,因此如果添加标题,书籍和其他书籍集,您的图书数组将不会抱怨:您的代码应该确保一致性。我们不声明数组大小。对于静态NSArray,创建时隐含大小,对于动态NSMutableArray,没有固定限制。对于五十本书籍集合的集合,创建一个由五十个预先存在的集合组成的NSArray。或者创建一个NSMutableArray,您可以逐步添加。
BookCollection* joyce = [[BookCollection alloc] init];
joyce.title = @"Books by James Joyce";
joyce.books = @["Ulysses",@"Finnegan's Wake"]; //using static NSArray
BookCollection* tolkein = [[BookCollection alloc] init];
tolkein.title = @"Books by J.R.R. Tolkein";
[tolkein.books addObject:@"The Hobbit"]; //using dynamic NSMutableArray
[tolkein.books addObject:@"Lord of the Rings"];
对于动态的集合数组:
NSMutableArray* collections = [[NSMutableArray alloc] init];
[collections addObject:joyce];
[collections addObject:tolkein];
对于固定数组,您可以使用文字语法:
NSArray* collections = @[joyce, tolkein];
对于numberOfBooks,只需使用数组的count
属性
int numberOfBooks = joyce.books.count;
如果您想确保使用标题和书籍创建集合,请根据adrusi的答案使用自定义初始化程序。这不是使对象起作用所必需的,但如果您想保证对象具有内容,则它非常有用。
要访问实例变量,请使用[message syntax]
(原始obj-C方式)或dot.syntax
(适用于@properties)
[tolkein books]
joyce.books
不要使用->
箭头语法。有关详细说明,请参阅here。