Reputation: 1102
Everytime i run the code it run in infinite loop and call the function myProperty
over and over again. What should i do to overcome this..I have written the following code in viewDidLoad function of the viewController.
[self.model addObserver:self forKeyPath:@"myProperty" options:NSKeyValueObservingOptionNew context:NULL];
[self.model myProperty];
here i have a Model
class and it has a property named myProperty
and a method or a getter myProperty
.I am usingmyProperty
to connect to a database a collect all the values of a column and store it in myProperty
. I have checked myProperty
method..it is doing fine without KVO. But when i add this KVO this goes into infinite loop.
again i have also used
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if([keyPath isEqualToString:@"myProperty"])
NSLog(@"called");
}
and my myProperty
method is
- (void) myProperty
{
NSString *file = [[NSBundle mainBundle] pathForResource:@"MyDatabase" ofType:@"db"];
sqlite3 *database = NULL;
sqlite3_stmt *stmt;
NSMutableArray *availableNames=[NSMutableArray array];
if (sqlite3_open([file UTF8String], &database) == SQLITE_OK)
{
NSString *query=[NSString stringWithFormat:@"select * from Names"];
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &stmt, NULL)==SQLITE_OK)
{
while (sqlite3_step(stmt)==SQLITE_ROW) {
[availableNames addObject:[[NSString alloc]initWithUTF8String:(char *)sqlite3_column_text(stmt,1 )]];
}
sqlite3_finalize(stmt);
}
}
sqlite3_close(database);
self.myProperty = availableNames;
}
Thank you in advance
Upvotes: 1
Views: 629
Reputation: 162712
First, rename getMyProperty
to simply myProperty
. Methods should not be prefixed with get
.
Secondly, you need to post the implementation of getMyProperty
and post part of the backtrace of the infinite loop. Most likely, your getter is triggering a mutation which is triggering KVO which triggers the getter which triggers the mutation which triggers KVO....
self.myProperty = availableNames;
That's your problem right there; you are changing state from your getter which leads to the infinite loop described above. Getters really shouldn't be that complex; do you really want to open a database connection and read from disk every single time you ask for the available names? Slow!
Split that out; create a loadAvailableNames
method that can be called at an appropriate time (if (self.needsLoading) [self loadAavailableNames]; return _myProperty;
, etc...).
Also -- writing against the raw SQLite API is both a waste of time and really hard to get right. If you need portability of database, use something like FMDB. If you want to maximally leverage system capabilities, use Core Data.
Upvotes: 1