Is there any assumption for using LiveQuery (without datasource)?

64 views
Skip to first unread message

SeanDev

unread,
Feb 25, 2015, 11:38:07 AM2/25/15
to mobile-c...@googlegroups.com
I've been following the example code in http://developer.couchbase.com/mobile/develop/guides/couchbase-lite/native-api/query/index.html

- (void) initializeQuery {
    // Set up my live query during view initialization:
    CBLQuery* query = [[self.db viewNamed: @"widgets"] createQuery];
    query.limit = 100;
    self.liveQuery = query.asLiveQuery;
    [self.liveQuery addObserver: self forKeyPath: @"rows"
                        options: 0 context: NULL];
    [self.liveQuery start];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context 
{
    if (object == self.liveQuery) {
        [self displayRows: self.liveQuery.rows]; // update the UI
    }
}

My code is slightly different in that:
  1. I get the query from CBLModel subclass. 
  2. addObserver method is called in viewDidLoad
I've been using break point to track debug the code, but observeValueForKeyPath is not called.

I've also tried to run the query manually like below, it works.

    CBLQueryEnumerator* result = [self.liveQuery run: &error];
   
for (CBLQueryRow* row in result) {

       
NSLog(@"found a row for mssession: %@, %@", row.key, row.value);

   
}

Since both row.key and row.value are up to date, I believe the query itself is valid. It's just that the observeValueForKeyPath was never called.

So, there must be something else needed for wiring this up.  Are there any assumptions made for using LiveQuery?

And the whole picture was a queue structure, the users are producers or consumers. 
To make it concrete, I am trying to maintain a doc which contains an array. And this array needs to be modified by different users simultaineously. So I need every user to monitor whether this doc is changed. 

I guess there must be some best practice for this. Anyone please lend a hand.


-Sean



Jens Alfke

unread,
Feb 25, 2015, 11:50:10 AM2/25/15
to mobile-c...@googlegroups.com

On Feb 25, 2015, at 8:38 AM, SeanDev <xyvict...@gmail.com> wrote:

  1. I get the query from CBLModel subclass. 
A CBLModel may have a very short lifetime, because the reference from the document to the model is weak. So it’s entirely possible your model goes away before the live query every updates, if there’s no other strong reference to that model object anywhere. You could check this by putting a breakpoint in your -dealloc method.

—Jens

SeanDev

unread,
Feb 25, 2015, 9:05:13 PM2/25/15
to mobile-c...@googlegroups.com
I implemented the 
- (void) dealloc {
 
NSLog(@"Dealloc of MSSession object");
}

It is not called either.

The query is fetched using a class method, like this one below:
+ (CBLQuery*) queryProfilesInDatabase: (CBLDatabase*)db {

 

   
CBLView* view = [db viewNamed: @"profiles"];

   
if (!view.mapBlock) {

       
// Register the map function, the first time we access the view:

       
[view setMapBlock: MAPBLOCK({

           
if ([doc[@"type"] isEqualToString:kType])

                emit
(doc[@"_id"], doc[@"queue"]);

       
}) reduceBlock: nil version: @"1"]; // bump version any time you change the MAPBLOCK body!

   
}

   
return [view createQuery];

}


Actually no instance of the CBLModel is created.

Since I'm using emit(doc[@"_id"], doc[@"queue"]); Is it possible that index is not refreshed when I modify ony the doc[@"queue"]?

-Sean

Jens Alfke

unread,
Feb 25, 2015, 11:01:01 PM2/25/15
to mobile-c...@googlegroups.com

> On Feb 25, 2015, at 6:05 PM, SeanDev <xyvict...@gmail.com> wrote:
>
> The query is fetched using a class method, like this one below:

That snippet doesn’t match the code you posted earlier — It’s a different view and different code to create the query. So I’m not sure what your code is actually doing.

In your initial post, I can’t tell what class contains the methods that create and run the query and observe the rows.

Could you please post a link to an entire source file that demonstrates the problem?

—Jens

SeanDev

unread,
Feb 26, 2015, 4:59:26 AM2/26/15
to mobile-c...@googlegroups.com


On Thursday, February 26, 2015 at 12:01:01 PM UTC+8, Jens Alfke wrote:

Could you please post a link to an entire source file that demonstrates the problem?


Thanks for responding, link below is the code to demo the problem.


The sync function is as below:
{
 
"log": ["CRUD", "REST+","HTTP+"],
 
"databases": {
 
"demoqueue": {
   
"server": "walrus:",
   
"bucket": "demoqueue",
   
"users": {
     
"GUEST": {"disabled": false, "admin_channels": ["*"] }
   
}
 
}
 
}
}


Any advice or suggestions are aprreciated.

Since -observeValueForKeyPath: is never called, I added a button to call -(IBAction)refreshLiveQuery: to run the query manually, and update the UI.

Jens Alfke

unread,
Feb 26, 2015, 1:34:32 PM2/26/15
to mobile-c...@googlegroups.com
The only code I saw that adds an observer is:

[self.queueLiveQuery addObserver: self forKeyPath: @"demoqueue"
options: 0 context: NULL];

But CBLLiveQuery doesn’t have any property named “demoqueue", so this isn’t going to do anything. The actual keyPath you should be observing is “rows”.

—Jens

SeanDev

unread,
Feb 27, 2015, 12:13:22 AM2/27/15
to mobile-c...@googlegroups.com
Yes, it changing to @"rows" works. Thanks a lot!

-Sean
Reply all
Reply to author
Forward
0 new messages