【问题标题】:Program received signal "EXC_Bad_Access" NSMutableArray程序接收信号“EXC_Bad_Access”NSMutableArray
【发布时间】:2011-05-02 19:15:03
【问题描述】:

如果我尝试重新运行下面的代码,我会在 [categoryList count] 上收到一条 EXE_bad_access 消息

NSMutableArray *categoryList = [[CategoryItem alloc] getAll];
NSLog(@"number of items is %@", [categoryList count]);

类在下面

#import "CategoryItem.h"

#import "SQLite.h"

@interface CategoryItem : NSObject {
    NSInteger ID;
    NSInteger SortOrder;
    NSString *Name;
    NSString *ShoppingImage;

}

@property (nonatomic, nonatomic) NSInteger SortOrder;
@property (nonatomic, retain) NSString * Name;
@property (nonatomic, retain) NSString * ShoppingImage;
@property (nonatomic, nonatomic) NSInteger ID;

- (id)initWithObject:(NSInteger)itemID;
-(NSMutableArray *)getAll;

@end
@implementation CategoryItem


@synthesize ShoppingImage;
@synthesize Name;
@synthesize ID;
@synthesize SortOrder;

- (id)initWithObject:(NSInteger)itemID {

    if ((self = [super init])) {
        sqlite3 *database;
        // Open the database. The database was prepared outside the application.
        if (sqlite3_open([[SQLite fullFilePath] UTF8String], &database) == SQLITE_OK) {
            // Get the primary key for all books.
            const char *sql = "SELECT ID, Name, ShoppingImage, SortOrder FROM CategoryItem WHERE ID =?";
            sqlite3_stmt *statement;
            // Preparing a statement compiles the SQL query into a byte-code program in the SQLite library.
            // The third parameter is either the length of the SQL string or -1 to read up to the first null terminator.        
            if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
                // We "step" through the results - once for each row.
                sqlite3_bind_int(statement, 1, itemID);

                while (sqlite3_step(statement) == SQLITE_ROW) {
                    // The second parameter indicates the column index into the result set.
                    self.ID = itemID;
                    self.Name = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
                    self.ShoppingImage = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 2)];
                    self.SortOrder = sqlite3_column_int(statement, 3);
                }
            }
            // "Finalize" the statement - releases the resources associated with the statement.
            sqlite3_finalize(statement);
        } else {
            // Even though the open failed, call close to properly clean up resources.
            sqlite3_close(database);
            NSLog(@"Failed to open database with message '%s'.", sqlite3_errmsg(database));
            // Additional error handling, as appropriate...
        }

    }
    return self;
}

-(NSMutableArray*)getAll{

    NSMutableArray *listArray = [[[NSMutableArray alloc] init] autorelease];

    sqlite3 *database;
    // Open the database. The database was prepared outside the application.
    if (sqlite3_open([[SQLite fullFilePath] UTF8String], &database) == SQLITE_OK) {
        // Get the primary key for all books.
        const char *sql = "SELECT ID, Name, ShoppingImage, SortOrder FROM CategoryItem ORDER BY SortOrder";
        sqlite3_stmt *statement;
        // Preparing a statement compiles the SQL query into a byte-code program in the SQLite library.
        // The third parameter is either the length of the SQL string or -1 to read up to the first null terminator.

        if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) 
        {

            // We "step" through the results - once for each row.
            while (sqlite3_step(statement) == SQLITE_ROW)
            {
                // The second parameter indicates the column index into the result set.

                CategoryItem *categoryItem = [[CategoryItem alloc] init];

                categoryItem.ID = sqlite3_column_int(statement, 0);
                categoryItem.Name = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
                categoryItem.ShoppingImage = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 2)];
                categoryItem.SortOrder = sqlite3_column_int(statement, 3);

                [listArray addObject:categoryItem];

                [categoryItem release];
                categoryItem = nil;

            }


        }else{
            printf( "could not prepare statemnt: %s\n", sqlite3_errmsg(database) ); 
        }
        // "Finalize" the statement - releases the resources associated with the statement.
        sqlite3_finalize(statement);

    } else {
        // Even though the open failed, call close to properly clean up resources.
        sqlite3_close(database);
        NSLog(@"Failed to open database with message '%s'.", sqlite3_errmsg(database));
        // Additional error handling, as appropriate...
    }

    //NSLog(@"this is the list array count %@", [listArray count]);

    return listArray;
}



- (void)dealloc {
    [super dealloc];
    [Name release];
    [ShoppingImage release];

}


@end

【问题讨论】:

  • 只有受虐狂才直接在 Objective-C 中使用 SQLite C API。 Use FMDB(SQLite 包装器)或CoreData(对象图管理器)。
  • @Luke 你不应该初始化那个CategoryItem 吗?你打电话给alloc,但不是initWithObject...
  • 你还没有初始化CategoryList类,但是你在它上面调用了一个方法。似乎问题出在(不存在的)初始化中。
  • 确实,当您必须编写那么多 cmets 来回忆发生了什么时,这表明抽象层可能非常有用。
  • 请尝试 Core Data。设置工作大致相同,但使用起来容易得多。如果你做对了,你也可以很容易地准备一个数据集来与你的应用程序一起发布(“数据库是在应用程序之外准备好的。”)

标签: iphone objective-c arrays ios


【解决方案1】:

您创建CategoryItem 的方式似乎不正确。您正在调用 alloc 但不是任何 init... 方法。您可能希望使用您在实现中提供的initWithObject 方法。

来自Apple docs

创建一个对象需要两个步骤 使用Objective-C。你必须:

  • 动态分配内存 新对象

  • 初始化新的 将内存分配给适当的值

一个对象直到 两个步骤都已完成。每个 步骤是由一个单独的完成 方法,但通常在一行中 代码:

id anObject = [[矩形分配] 初始化];

编辑:

除了初始化问题,似乎还有一个概念问题(@Terry Wilcox 指出): 在实例上调用方法getAll似乎没有意义,因此应改为定义为类方法:

+ (NSMutableArray*)getAll;

应该这样调用:

NSMutableArray *categoryList = [CategoryItem getAll];

编辑 2:

您的日志语句似乎也不正确。 [categoryList count]returns a NSUInteger并且您正在尝试使用 %@ 打印对象。请改用%i

NSLog(@"number of items is %i", [categoryList count]);

【讨论】:

  • 代码不是在尝试创建 CategoryItem,而是在尝试创建 NSMutableArray。
  • @Luke 您还试图记录一个 int ,就好像它是一个对象一样(参见 EDIT 2)
  • 天哪,这是它自己的日志语句。非常感谢我昨天删除了日志语句,它开始工作,甚至没有考虑它。哦,那是我生命中永远不会回来的一个小时
【解决方案2】:

这段代码:

NSMutableArray *categoryList = [[CategoryItem alloc] getAll];

没有意义。如果 getAll 是 CategoryItem 上的类方法,那么它应该定义为

+ (NSMutableArray*)getAll;

你应该这样称呼它

NSMutableArray *categoryList = [CategoryItem getAll];

那么 categoryList 将是一个你不拥有的数组,所以你可能想在得到它时保留它。

【讨论】:

  • 感谢这么干净的代码!但仍然不能解决我的内存问题
  • 这不是更干净的代码,而是工作代码。您的原始代码无法正常工作,它没有调用 init,因此您的 getAll 方法可能不会返回任何内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 2012-10-05
  • 1970-01-01
  • 2011-03-06
  • 1970-01-01
相关资源
最近更新 更多