diff --git a/Source/ARTRealtimeChannel.m b/Source/ARTRealtimeChannel.m index e4510f3cf..5613b68a5 100644 --- a/Source/ARTRealtimeChannel.m +++ b/Source/ARTRealtimeChannel.m @@ -69,6 +69,10 @@ - (ARTRealtimeChannelState)state { return _internal.state; } +- (ARTChannelProperties *)properties { + return _internal.properties; +} + - (ARTErrorInfo *)errorReason { return _internal.errorReason; } @@ -1078,6 +1082,18 @@ - (ARTRealtimeChannelOptions *)getOptions_nosync { return (ARTRealtimeChannelOptions *)[self options_nosync]; } +- (ARTChannelProperties *)properties { + __block ARTChannelProperties *ret; + dispatch_sync(_queue, ^{ + ret = [self properties_nosync]; + }); + return ret; +} + +- (ARTChannelProperties *)properties_nosync { + return [[ARTChannelProperties alloc] initWithAttachSerial:_attachSerial channelSerial:_channelSerial]; +} + - (void)setOptions:(ARTRealtimeChannelOptions *_Nullable)options callback:(nullable ARTCallback)callback { if (callback) { ARTCallback userCallback = callback; @@ -1119,6 +1135,21 @@ - (void)setOptions_nosync:(ARTRealtimeChannelOptions *_Nullable)options callback @end +#pragma mark - Channel Properties (RTL15) + +@implementation ARTChannelProperties + +- (instancetype)initWithAttachSerial:(NSString *)attachSerial channelSerial:(NSString *)channelSerial { + self = [super init]; + if (self) { + _attachSerial = attachSerial; + _channelSerial = channelSerial; + } + return self; +} + +@end + #pragma mark - ARTEvent @implementation ARTEvent (ChannelEvent) diff --git a/Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h b/Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h index 15e9e0a0a..03dbbc572 100644 --- a/Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h +++ b/Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h @@ -34,6 +34,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSString * _Nullable)clientId_nosync; - (BOOL)canBeReattached; - (BOOL)shouldAttach; +- (ARTChannelProperties *)properties_nosync; @property (readonly, weak, nonatomic) ARTRealtimeInternal *realtime; // weak because realtime owns self @property (readonly, nonatomic) ARTRestChannelInternal *restChannel; @@ -95,4 +96,10 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface ARTChannelProperties () + +- (instancetype)initWithAttachSerial:(nullable NSString *)attachSerial channelSerial:(nullable NSString *)channelSerial; + +@end + NS_ASSUME_NONNULL_END diff --git a/Source/include/Ably/ARTRealtimeChannel.h b/Source/include/Ably/ARTRealtimeChannel.h index 6a153d8aa..ecf14de4a 100644 --- a/Source/include/Ably/ARTRealtimeChannel.h +++ b/Source/include/Ably/ARTRealtimeChannel.h @@ -11,6 +11,7 @@ NS_ASSUME_NONNULL_BEGIN @class ARTRealtimePresence; @class ARTRealtimeChannelOptions; +@class ARTChannelProperties; #if TARGET_OS_IPHONE @class ARTPushChannel; #endif @@ -25,6 +26,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (readonly) ARTRealtimeChannelState state; +/** + * An `ARTChannelProperties` object. + */ +@property (readonly) ARTChannelProperties *properties; + /** * An `ARTErrorInfo` object describing the last error which occurred on the channel, if any. */ @@ -145,6 +151,18 @@ ART_EMBED_INTERFACE_EVENT_EMITTER(ARTChannelEvent, ARTChannelStateChange *) @end +/** + * Describes the properties of the channel state. + */ +@interface ARTChannelProperties : NSObject +/** + * Starts unset when a channel is instantiated, then updated with the `channelSerial` from each `ARTChannelEventAttached` event that matches the channel. Used as the value for `ARTRealtimeHistoryQuery.untilAttach`. + */ +@property (nonatomic, readonly, nullable) NSString *attachSerial; // CP2a +@property (nonatomic, readonly, nullable) NSString *channelSerial; // CP2b + +@end + /** * Enables messages to be published and subscribed to. Also enables historic messages to be retrieved and provides access to the `ARTRealtimePresence` object of a channel. * Also implements `ARTEventEmitter` interface and emits `ARTChannelEvent` events, where a `ARTChannelEvent` is either a `ARTRealtimeChannelState` or an `ARTChannelEvent.ARTChannelEventUpdate`. diff --git a/Test/Tests/RealtimeClientChannelTests.swift b/Test/Tests/RealtimeClientChannelTests.swift index 752278d35..3db6ca63d 100644 --- a/Test/Tests/RealtimeClientChannelTests.swift +++ b/Test/Tests/RealtimeClientChannelTests.swift @@ -134,7 +134,7 @@ private func testWithUntilAttach(_ untilAttach: Bool, for test: Test, channelNam let queryString = testHTTPExecutor.requests.last!.url!.query if query.untilAttach { - expect(queryString).to(contain("fromSerial=\(channel.internal.attachSerial!)")) + expect(queryString).to(contain("fromSerial=\(channel.properties.attachSerial!)")) } else { expect(queryString).toNot(contain("fromSerial")) } @@ -4256,14 +4256,14 @@ class RealtimeClientChannelTests: XCTestCase { expect(error).to(beNil()) let attachMessage = transport.protocolMessagesReceived.filter { $0.action == .attached }[0] if attachMessage.channelSerial != nil { - expect(attachMessage.channelSerial).to(equal(channel.internal.channelSerial)) + expect(attachMessage.channelSerial).to(equal(channel.properties.channelSerial)) } partialDone() channel.subscribe { message in let messageMessage = transport.protocolMessagesReceived.filter { $0.action == .message }[0] if messageMessage.channelSerial != nil { - expect(messageMessage.channelSerial).to(equal(channel.internal.channelSerial)) + expect(messageMessage.channelSerial).to(equal(channel.properties.channelSerial)) } channel.presence.enterClient("client1", data: "Hey") partialDone() @@ -4271,7 +4271,7 @@ class RealtimeClientChannelTests: XCTestCase { channel.presence.subscribe { presenceMessage in let presenceMessage = transport.protocolMessagesReceived.filter { $0.action == .presence }[0] if presenceMessage.channelSerial != nil { - expect(presenceMessage.channelSerial).to(equal(channel.internal.channelSerial)) + expect(presenceMessage.channelSerial).to(equal(channel.properties.channelSerial)) } partialDone() }