I am trying to follow along with the steps for creating a Peer-to-Peer replication, but the start method of CBLListener is not implemented in the CouchbaseLiteListener framework. Here is the Couchbase Wiki I am following - https://github.com/couchbase/couchbase-lite-ios/wiki/Guide:-REST
The two header files in the framework are CBLListener.h and CouchbaseLiteListener.h. Here is my implementation:
CBLManager* manager = [CBLManager sharedInstance];
CBLListener *listener = [CBLListener alloc];
[listener initWithManager: manager port: 0];
//listener.readOnly = YES; // Do this to prevent writes to your databases
//listener.passwords = @{@"naomi": @"letmein"};
NSError* error;
[listener start:&error];
if ([listener start:&error])
{
if (error) {
NSLog(@"%@", error.localizedDescription);
return NO;
}
NSLog(@"%@", manager.internalURL);
UInt16 actualPort = listener.port; // the actual TCP port it's listening on
NSLog(@"%hu", actualPort);
}
return NO;
The following line throws an error:
[listener start:&error];
I receive the following error:
2016-05-20 13:18:23.617 CouchbaseEvents[18564:934579] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Class CBLListener forgot to implement abstract method start:'
When I look at the Couchbase GitHub repo, the CBLListener.m does not implement ‘start’. However, CBLHTTPListener, for example, extends CBLListener and implements start.
The issue is that the CBLHTTListener.h & all of its dependency headers, are not included in the CouchbaseLiteListener.Framework.
Can someone please let me know how I can get a Framework that has this method implemented?
That’s incorrect for any Objective-C class; you’d probably run into similar problems if you did it with NSString, for example. In general, an -init... method is allowed to, and often does, return a different instance than the one alloced. In this case it returns an instance of one of the two concrete subclasses of CBLListener. But your code never assigned that object back to the listener variable.
Thanks for letting me know; I’ve fixed it. Looks like that code sample was broken by some random Github user three years ago, in an attempt to make the lines shorter. Sigh.
iOS will kill open TCP listener sockets when an app is backgrounded. If you’re using the listener in an iOS app, you’ll need to stop it when the app is backgrounded and restart it when it foregrounds again.
I tried stopping the listener but it hasn’t worked. I noticed that after calling stop and then start on the listener that start was failing with the message Address already in use. I took a look at the code for CBLListener.m and saw this:
- (void) stop { /* no-op*/ }
So it doesn’t look like it can be stopped!
Although it probably doesn’t matter. It seems that the behaviour on a simulator is different to a device. The stop method isn’t actually needed because as you say, the OS kills the listener. This doesn’t happen on a simulator, so restarting the listener when the app resumes results in an Address already in use exception.
CBLListener is an abstract superclass. The actual implementation of -stop is in CBLHTTPListener.
after calling stop and then start on the listener that start was failing with the message Address already in use
Hm. By default the kernel won’t allow a new listener socket to be opened on a port that was just closed, to avoid confusion. But there’s a flag to override that, and I thought we were setting it.
Anyway, we’re having a parallel discussion on Github issues, and over there I said you probably shouldn’t use the listener; instead use the internalURL of the CBLManager and just point your JS code at that.