为啥要更改此实例对象?
Posted
技术标签:
【中文标题】为啥要更改此实例对象?【英文标题】:Why is this instance object being changed?为什么要更改此实例对象? 【发布时间】:2012-03-13 20:39:39 【问题描述】:我对目标 C 很陌生,我只是在学习。我完成了 techotopia 教程“An_Example_SQLite_based_ios_4_iPhone_Application_(Xcode_4)”,然后尝试使用 FMDB 再次实现它。 (我会发布教程的链接,但我最多只能发布 2 个链接)
问题:在initWithFrame
我创建eventDB
。然后在addEvent
中,在按键之后,eventDB.database
的内容发生了变化。 This 是 eventDB
在 initWithFrame
和 this 是在 addEvent
。
#import "appTracker.h"
@implementation appTracker
- (id) initWithFrame:(NSRect)frameRect
self = [super initWithFrame:frameRect];
eventDB = [[appTrackerDB alloc] init];
return self;
- (void) keyDown: (NSEvent *) event
NSString *chars = [event characters];
unichar character = [chars characterAtIndex: 0];
if (character == 'A')
NSLog (@"Adding event");
[self addEvent:@"test_arg"];
- (void) addEvent: (NSString *) name
[eventDB setName:name];
[eventDB setPhone:name];
[eventDB setAddress:name];
[eventDB setStatus:name];
[eventDB saveData];
...
@end
使用 GDB,我发现它在 main.m
(由 XCode4 自动生成)中发生了变化:(不太确定这段代码的作用或它为什么存在)
#import <Cocoa/Cocoa.h>
int main(int argc, char *argv[])
return NSApplicationMain(argc, (const char **)argv);
我不熟悉目标 C。有人可以帮我弄清楚为什么我的 eventDB.database
对象被更改了吗?我可能没有正确管理一些内存或完全误解了您应该如何执行此操作。任何帮助将不胜感激。
eventDB
是一个实例:
#import <Foundation/Foundation.h>
#import "FMDatabase.h"
@interface appTrackerDB : NSObject
NSString *name;
NSString *address;
NSString *phone;
NSString *status;
NSString *databasePath;
FMDatabase *database;
谢谢!
还有 [eventDB saveData] 是:
- (void) saveData
[database executeUpdate:@"insert into user (name, address, phone) values(?,?,?)",
name, address, phone,nil];
并使用以下命令创建数据库:
@implementation appTrackerDB
@synthesize name,address,status,phone;
- (id)init
self = [super init];
if (self)
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *path = [docsPath stringByAppendingPathComponent:@"database.sqlite"];
database = [FMDatabase databaseWithPath:path];
[database open];
[database executeUpdate:@"create table IF NOT EXISTS user(ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, ADDRESS TEXT, PHONE TEXT)"];
if ([database hadError])
NSLog(@"DB Error %d: %@", [database lastErrorCode], [database lastErrorMessage]);
name = @"TEST";
return self;
【问题讨论】:
你不想改变它吗?我的意思是您在调用 addEvent 时设置名称和地址属性,这会更改对象。还是您在谈论替换对象? (例如指针值发生变化)也许你应该详细说明你的问题到底是什么。 我不希望eventDB.database
的内容发生变化。我不会改变那些。
aehm... 那么 [eventDB saveData];如果它没有将数据保存到数据库中,该怎么办?
对不起,我看到了混乱。问题不是数据库的内容发生了变化,而是对数据库的引用发生了变化。如果您查看问题中的两张图片,您就会明白我的意思。也只是为了完整性,我添加了 saveData 的代码。
好的,我明白你的意思了。你是如何初始化实际的 FMDatabase 的?该文档提出了三种不同的方法,可以解释您的问题。
【参考方案1】:
您实际上并没有保留数据库。在 Objective-C 中,您需要手动保留对象,尤其是当它们不是属性时。 (例如,name
被声明为属性,database
不是)
保留意味着您拥有该对象。 databaseWithObject
保留了数据库,但在上面调用了autorelease
,这通常意味着调用方法完成后,它会尽快删除引用。
取决于您的平台,例如OS X 而不是 iOS,您可以启用 GarbageCollection 功能。这意味着,OSX/Objective-C 环境将为您完成大量的内存管理。但是要使这有任何用途,您需要将相关的实例变量声明为属性并在它们上使用适当的 setter 和 getter 方法。
这是一个属性声明的示例 (appTrackerDB.h):
#import <Foundation/Foundation.h>
#import "FMDatabase.h"
@interface appTrackerDB : NSObject
/*
These are only necessary when
using iOS-Versions prior to
iOS 4, or if you really
need to manipulate the values
without utilizing the setter-/getter-
methods.
*/
NSString *name;
NSString *address;
NSString *phone;
NSString *status;
NSString *databasePath;
FMDatabase *database;
@property (retain) NSString *name,*address;
@property (retain) NSString *phone,*status,*databasePath;
@property (retain) FMDatabase *database;
appTrackerDB.m:
@implementation appTrackerDB
@synthesize name,address,status,phone;
@synthesize databasePath,database;
您可以调用而不是手动分配的示例 setter 方法是:
[self setDatabase:...];
而不是直接赋值database = ...
像setVariableName
这样的setter 方法和像variableName
这样的getter 方法
由@synthesize
指令为您合成。
【讨论】:
我用@property (retain, nonatomic) FMDatabase *database;
把它变成了一个属性,合成了它,但问题仍然存在。我现在必须手动保留它吗?
您必须在 init 中调用 [self setDatabase:[FMDatabase databaseWithPath:path]];
而不是 database =..
变体
做到了!谢谢。这有什么不同?
此方法称为 setter,可以像手动设置变量一样设置变量,但也保留对象。对于不想深入了解 Objective-c 机制的人来说,这是一种更简单的方法(大多数人不需要)
由于这是在 OSX 上,是否有一些垃圾收集设置我可以启用,这样我就不必使用[self setDatabase:...];
?以上是关于为啥要更改此实例对象?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在我的反应形式中此 FormArray 更改后,我从 JSON 文件中检索对象时收到此错误消息?
GCP 计算实例上的部署失败,为啥从 Gitlab 推送更改