Bring MZFayeClient from CocoaPods to project

If you manually add MZFayeClient to the Podfile, remove Base64 & SocketRocket.
This commit is contained in:
Cee
2016-02-01 15:05:05 +08:00
parent ea0dfda9a4
commit 4799bb0b9b
8 changed files with 978 additions and 10 deletions
+3 -1
View File
@@ -17,7 +17,9 @@ def pods
pod 'Kingfisher'
pod 'TPKeyboardAvoiding', '~> 1.2'
pod 'pop'
pod 'MZFayeClient', :path => '../CatchLib-iOS/MZFayeClient/'
# pod 'MZFayeClient', :path => '../CatchLib-iOS/MZFayeClient/'
pod 'Base64'
pod 'SocketRocket'
pod 'RealmSwift'
pod 'MonkeyKing', '0.0.2'
pod 'JPush-iOS-SDK'
+2 -9
View File
@@ -15,9 +15,6 @@ PODS:
- KeyboardMan (0.5.2)
- Kingfisher (1.9.1)
- MonkeyKing (0.0.2)
- MZFayeClient (1.0.1):
- Base64 (~> 1.0.1)
- SocketRocket (~> 0.4)
- Navi (0.3.9)
- pop (1.0.8)
- Proposer (0.7.1)
@@ -34,6 +31,7 @@ DEPENDENCIES:
- 1PasswordExtension (~> 1.5)
- Alamofire
- APAddressBook/Swift
- Base64
- Crashlytics
- DeviceGuru
- Fabric
@@ -43,18 +41,14 @@ DEPENDENCIES:
- KeyboardMan
- Kingfisher
- MonkeyKing (= 0.0.2)
- MZFayeClient (from `../CatchLib-iOS/MZFayeClient/`)
- Navi
- pop
- Proposer
- RealmSwift
- Ruler
- SocketRocket
- TPKeyboardAvoiding (~> 1.2)
EXTERNAL SOURCES:
MZFayeClient:
:path: ../CatchLib-iOS/MZFayeClient/
SPEC CHECKSUMS:
1PasswordExtension: a22573ad528dd63bd79c1f3b3813b17c2f86b91b
Alamofire: fbc829692f351fa1d8a31dd75fd7f7f56fea31fb
@@ -69,7 +63,6 @@ SPEC CHECKSUMS:
KeyboardMan: b081c254c5c0adc794a49b4e97a86cb4ac917a66
Kingfisher: 98fedd5d44d982b331fc7303f9f6144b7d8ba289
MonkeyKing: 9be24307843a80f4cd3eca66adc12c67aefb83bb
MZFayeClient: 65e7ef67e61fbe7a7a8b196130541c9f06bcb5d8
Navi: 24f5c81aeb46b89d27168ec1d459581230ae2675
pop: bb773ae2c791ca2629de13b347e7a8b450fa6a57
Proposer: e9759ad71a6702fd94315a0bff1f8c116edf6f07
+28
View File
@@ -358,6 +358,8 @@
848806B41B7B4E2E000C5424 /* Show.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 848806B31B7B4E2E000C5424 /* Show.storyboard */; };
848806B61B7B4F53000C5424 /* ShowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848806B51B7B4F53000C5424 /* ShowViewController.swift */; };
84C959891B731FD20017D3ED /* ChatBaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C959881B731FD20017D3ED /* ChatBaseCell.swift */; };
92E0FFE71C5F38E400226B96 /* MZFayeClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 92E0FFE41C5F38E400226B96 /* MZFayeClient.m */; };
92E0FFE81C5F38E400226B96 /* MZFayeMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 92E0FFE61C5F38E400226B96 /* MZFayeMessage.m */; };
B00500D7E943DDD27CF9C562 /* Pods_Yep.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3146F0F60F2A38BC6E0FA66 /* Pods_Yep.framework */; };
/* End PBXBuildFile section */
@@ -733,6 +735,10 @@
848806B51B7B4F53000C5424 /* ShowViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShowViewController.swift; path = ViewControllers/Show/ShowViewController.swift; sourceTree = "<group>"; };
84C959881B731FD20017D3ED /* ChatBaseCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChatBaseCell.swift; path = Views/Cells/ChatBaseCell/ChatBaseCell.swift; sourceTree = "<group>"; };
88C96122C478C4D134F634F6 /* Pods-Yep.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Yep.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Yep/Pods-Yep.debug.xcconfig"; sourceTree = "<group>"; };
92E0FFE31C5F38E400226B96 /* MZFayeClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MZFayeClient.h; sourceTree = "<group>"; };
92E0FFE41C5F38E400226B96 /* MZFayeClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MZFayeClient.m; sourceTree = "<group>"; };
92E0FFE51C5F38E400226B96 /* MZFayeMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MZFayeMessage.h; sourceTree = "<group>"; };
92E0FFE61C5F38E400226B96 /* MZFayeMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MZFayeMessage.m; sourceTree = "<group>"; };
C3146F0F60F2A38BC6E0FA66 /* Pods_Yep.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Yep.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
@@ -832,6 +838,7 @@
848806B21B7B0230000C5424 /* Yep.entitlements */,
0A8F54B01AB67D11004AD60E /* AppDelegate.swift */,
0AD7EA581AC3EAF300617758 /* Yep-Bridging-Header.h */,
92E0FFE11C5F38E400226B96 /* Vendors */,
50AFBF4F1BB3A5A1007D19DA /* Sounds */,
50E114F51ABBF9D100F13000 /* Realm */,
502AE53B1AB871C5005BD199 /* Helpers */,
@@ -2338,6 +2345,25 @@
name = ChatBase;
sourceTree = "<group>";
};
92E0FFE11C5F38E400226B96 /* Vendors */ = {
isa = PBXGroup;
children = (
92E0FFE21C5F38E400226B96 /* MZFayeClient */,
);
path = Vendors;
sourceTree = "<group>";
};
92E0FFE21C5F38E400226B96 /* MZFayeClient */ = {
isa = PBXGroup;
children = (
92E0FFE31C5F38E400226B96 /* MZFayeClient.h */,
92E0FFE41C5F38E400226B96 /* MZFayeClient.m */,
92E0FFE51C5F38E400226B96 /* MZFayeMessage.h */,
92E0FFE61C5F38E400226B96 /* MZFayeMessage.m */,
);
path = MZFayeClient;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -2682,6 +2708,7 @@
502AE51B1AB70DDB005BD199 /* WelcomeViewController.swift in Sources */,
50894D071AEDFDA2000981AF /* EditProfileMoreInfoCell.swift in Sources */,
502C24831C1034000074A1BA /* UIImageView+Yep.swift in Sources */,
92E0FFE71C5F38E400226B96 /* MZFayeClient.m in Sources */,
5080EB1C1B93F43A006F3C2D /* PodsHelpYepViewController.swift in Sources */,
0A1CAC731AFA526200826B45 /* SkillHomeSectionButton.swift in Sources */,
50E392BC1C22752C00C0CECB /* FeedNormalImagesCell.swift in Sources */,
@@ -2719,6 +2746,7 @@
50AFBF5F1BB4F332007D19DA /* FeedsViewController.swift in Sources */,
50EB8CBF1AE89ED8001AC1EE /* ChatLeftVideoCell.swift in Sources */,
502AE5331AB86020005BD199 /* RegisterVerifyMobileViewController.swift in Sources */,
92E0FFE81C5F38E400226B96 /* MZFayeMessage.m in Sources */,
5064F6541B0B0E160089FAD4 /* AddFriendSearchCell.swift in Sources */,
504CBA3D1B3D04B800663A90 /* ChatTextView.swift in Sources */,
0A1CAC6E1AFA42D400826B45 /* SkillHomeViewController.swift in Sources */,
+151
View File
@@ -0,0 +1,151 @@
//
// MZFayeClient.h
// MZFayeClient
//
// Created by Michał Zaborowski on 12.12.2013.
// Copyright (c) 2013 Michał Zaborowski. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
#import <SocketRocket/SRWebSocket.h>
#import "MZFayeMessage.h"
@class MZFayeClient;
extern NSString *const MZFayeClientBayeuxChannelHandshake;
extern NSString *const MZFayeClientBayeuxChannelConnect;
extern NSString *const MZFayeClientBayeuxChannelDisconnect;
extern NSString *const MZFayeClientBayeuxChannelSubscribe;
extern NSString *const MZFayeClientBayeuxChannelUnsubscribe;
extern NSString *const MZFayeClientWebSocketErrorDomain;
extern NSTimeInterval const MZFayeClientDefaultRetryInterval;
extern NSInteger const MZFayeClientDefaultMaximumAttempts;
typedef void(^MZFayeClientSubscriptionHandler)(NSDictionary *message);
typedef void(^MZFayeClientPrivateHandler)(MZFayeMessage *message);
@protocol MZFayeClientDelegate <NSObject>
@optional
- (void)fayeClient:(MZFayeClient *)client didConnectToURL:(NSURL *)url;
- (void)fayeClient:(MZFayeClient *)client didDisconnectWithError:(NSError *)error;
- (void)fayeClient:(MZFayeClient *)client didUnsubscribeFromChannel:(NSString *)channel;
- (void)fayeClient:(MZFayeClient *)client didSubscribeToChannel:(NSString *)channel;
- (void)fayeClient:(MZFayeClient *)client didFailWithError:(NSError *)error;
- (void)fayeClient:(MZFayeClient *)client didFailDeserializeMessage:(NSDictionary *)message
withError:(NSError *)error;
- (void)fayeClient:(MZFayeClient *)client didReceiveMessage:(NSDictionary *)messageData fromChannel:(NSString *)channel;
@end
@interface MZFayeClient : NSObject <SRWebSocketDelegate>
/**
* WebSocket client
*/
@property (nonatomic, readonly, strong) SRWebSocket *webSocket;
/**
* The URL for the faye server
*/
@property (nonatomic, readonly, strong) NSURL *url;
/**
* Uniquely identifies a client to the Bayeux server.
*/
@property (nonatomic, readonly, strong) NSString *clientId;
/**
* The number of sent messages
*/
@property (nonatomic, readonly) NSInteger sentMessageCount;
/**
* Returns whether the faye client is connected to server
*/
@property (nonatomic, readonly, assign, getter = isConnected) BOOL connected;
/**
* The channels the client wishes to subscribe
*/
@property (nonatomic, readonly) NSSet *subscriptions;
@property (nonatomic, readonly) NSSet *pendingSubscriptions;
@property (nonatomic, readonly) NSSet *openSubscriptions;
/**
* Returns list of extensions per channel.
* The contents of ext may be arbitrary values that allow extensions to be negotiated
* and implemented between server and client implementations.
*/
@property (nonatomic, readonly) NSDictionary *extensions;
/**
* Returns whether the faye client should auto retry connection
* By default, this is YES
*/
@property (nonatomic, assign) BOOL shouldRetryConnection;
/**
* How often should retry connection
*/
@property (nonatomic, assign) NSTimeInterval retryInterval;
/**
* Actual retry connection attempt number
*/
@property (nonatomic, assign) NSInteger retryAttempt;
/**
* Maximum retry connection attments
*/
@property (nonatomic, assign) NSInteger maximumRetryAttempts;
/**
* The object that acts as the delegate of the receiving faye client events.
*/
@property (nonatomic, weak) id <MZFayeClientDelegate> delegate;
- (instancetype)init;
+ (instancetype)client;
- (instancetype)initWithURL:(NSURL *)url;
+ (instancetype)clientWithURL:(NSURL *)url;
- (void)setExtension:(NSDictionary *)extension forChannel:(NSString *)channel;
- (void)removeExtensionForChannel:(NSString *)channel;
- (void)sendMessage:(NSDictionary *)message toChannel:(NSString *)channel;
- (void)sendMessage:(NSDictionary *)message toChannel:(NSString *)channel usingExtension:(NSDictionary *)extension;
- (void)sendMessage:(NSDictionary *)message toChannel:(NSString *)channel usingExtension:(NSDictionary *)extension usingBlock:(MZFayeClientPrivateHandler)subscriptionHandler;
- (void)subscribeToChannel:(NSString *)channel;
- (void)subscribeToChannel:(NSString *)channel usingBlock:(MZFayeClientSubscriptionHandler)subscriptionHandler;
- (void)unsubscribeFromChannel:(NSString *)channel;
- (BOOL)connectToURL:(NSURL *)url;
- (BOOL)connect;
- (void)disconnect;
@end
+690
View File
@@ -0,0 +1,690 @@
//
// MZFayeClient.m
// MZFayeClient
//
// Created by Michał Zaborowski on 12.12.2013.
// Copyright (c) 2013 Michał Zaborowski. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "MZFayeClient.h"
#import "MZFayeMessage.h"
#import "MF_Base64Additions.h"
NSString *const MZFayeClientBayeuxChannelHandshake = @"/meta/handshake";
NSString *const MZFayeClientBayeuxChannelConnect = @"/meta/connect";
NSString *const MZFayeClientBayeuxChannelDisconnect = @"/meta/disconnect";
NSString *const MZFayeClientBayeuxChannelSubscribe = @"/meta/subscribe";
NSString *const MZFayeClientBayeuxChannelUnsubscribe = @"/meta/unsubscribe";
NSString *const MZFayeClientBayeuxMessageChannelKey = @"channel";
NSString *const MZFayeClientBayeuxMessageClientIdKey = @"clientId";
NSString *const MZFayeClientBayeuxMessageIdKey = @"id";
NSString *const MZFayeClientBayeuxMessageDataKey = @"data";
NSString *const MZFayeClientBayeuxMessageSubscriptionKey = @"subscription";
NSString *const MZFayeClientBayeuxMessageExtensionKey = @"ext";
NSString *const MZFayeClientBayeuxMessageVersionKey = @"version";
NSString *const MZFayeClientBayeuxMessageMinimuVersionKey = @"minimumVersion";
NSString *const MZFayeClientBayeuxMessageSupportedConnectionTypesKey = @"supportedConnectionTypes";
NSString *const MZFayeClientBayeuxMessageConnectionTypeKey = @"connectionType";
NSString *const MZFayeClientBayeuxVersion = @"1.0";
NSString *const MZFayeClientBayeuxMinimumVersion = @"1.0beta";
NSString *const MZFayeClientBayeuxConnectionTypeLongPolling = @"long-polling";
NSString *const MZFayeClientBayeuxConnectionTypeCallbackPolling = @"callback-polling";
NSString *const MZFayeClientBayeuxConnectionTypeIFrame = @"iframe";
NSString *const MZFayeClientBayeuxConnectionTypeWebSocket = @"websocket";
NSString *const MZFayeClientWebSocketErrorDomain = @"com.mzfayeclient.error";
NSTimeInterval const MZFayeClientDefaultRetryInterval = 1.0f;
NSInteger const MZFayeClientDefaultMaximumAttempts = 5;
@interface MZFayeClient ()
@property (nonatomic, readwrite, strong) SRWebSocket *webSocket;
@property (nonatomic, readwrite, strong) NSMutableSet *openChannelSubscriptions;
@property (nonatomic, readwrite, strong) NSMutableSet *pendingChannelSubscriptions;
@property (nonatomic, readwrite, strong) NSMutableDictionary *subscribedChannels;
@property (nonatomic, readwrite, strong) NSMutableDictionary *privateChannels;
@property (nonatomic, readwrite, strong) NSMutableDictionary *channelExtensions;
@property (nonatomic, readwrite, strong) NSString *clientId;
@property (nonatomic, strong) NSTimer *reconnectTimer;
@property (nonatomic, readwrite, assign) NSInteger sentMessageCount;
@property (nonatomic, readwrite, assign, getter = isConnected) BOOL connected;
@property (nonatomic, readonly, assign, getter = isWebSocketOpen) BOOL webSocketOpen;
@property (nonatomic, readonly, assign, getter = isWebSocketClosed) BOOL webSocketClosed;
@end
@implementation MZFayeClient
#pragma mark - Getters
- (NSSet *)subscriptions
{
return [NSSet setWithArray:[self.subscribedChannels allKeys]];
}
- (NSSet *)pendingSubscriptions
{
return [self.pendingChannelSubscriptions copy];
}
- (NSSet *)openSubscriptions
{
return [self.openChannelSubscriptions copy];
}
- (NSDictionary *)extensions
{
return [self.channelExtensions copy];
}
- (BOOL)isWebSocketOpen
{
if (!self.webSocket)
return NO;
return self.webSocket.readyState == SR_OPEN;
}
- (BOOL)isWebSocketClosed
{
if (!self.webSocket)
return YES;
return self.webSocket.readyState == SR_CLOSED;
}
#pragma mark - Dealloc
- (void)dealloc
{
[self.subscribedChannels removeAllObjects];
[self clearSubscriptions];
[self invalidateReconnectTimer];
[self disconnectFromWebSocket];
}
#pragma mark - Initializers
- (instancetype)init
{
if (self = [super init]) {
_channelExtensions = [NSMutableDictionary dictionary];
_subscribedChannels = [NSMutableDictionary dictionary];
_privateChannels = [NSMutableDictionary dictionary];
_pendingChannelSubscriptions = [NSMutableSet set];
_openChannelSubscriptions = [NSMutableSet set];
_maximumRetryAttempts = MZFayeClientDefaultMaximumAttempts;
_retryInterval = MZFayeClientDefaultRetryInterval;
_shouldRetryConnection = YES;
_sentMessageCount = 0;
_retryAttempt = 0;
}
return self;
}
- (instancetype)initWithURL:(NSURL *)url
{
if (self = [self init]) {
_url = url;
}
return self;
}
+ (instancetype)client
{
return [[[self class] alloc] init];
}
+ (instancetype)clientWithURL:(NSURL *)url
{
return [[[self class] alloc] initWithURL:url];
}
#pragma mark - Bayeux procotol messages
/**
* A handshake request MUST contain the message fields:
*
* channel - value "/meta/handshake"
* version - The version of the protocol supported by the client.
*
* supportedConnectionTypes - An array of the connection types supported by the client for
* the purposes of the connection being negotiated (see section 3.4). This list MAY be a subset
* of the connection types actually supported if the client wishes to negotiate a specific connection type.
*/
- (void)sendBayeuxHandshakeMessage
{
NSArray *supportedConnectionTypes = @[MZFayeClientBayeuxConnectionTypeLongPolling,
MZFayeClientBayeuxConnectionTypeCallbackPolling,
MZFayeClientBayeuxConnectionTypeIFrame,
MZFayeClientBayeuxConnectionTypeWebSocket];
NSMutableDictionary *message = [@{MZFayeClientBayeuxMessageChannelKey : MZFayeClientBayeuxChannelHandshake,
MZFayeClientBayeuxMessageVersionKey : MZFayeClientBayeuxVersion,
MZFayeClientBayeuxMessageMinimuVersionKey : MZFayeClientBayeuxMinimumVersion,
MZFayeClientBayeuxMessageSupportedConnectionTypesKey : supportedConnectionTypes
} mutableCopy];
NSDictionary *extension = self.channelExtensions[@"handshake"];
if (extension) {
[message setObject:extension forKey:MZFayeClientBayeuxMessageExtensionKey];
}
[self writeMessageToWebSocket:message];
}
/**
* A connect request MUST contain the message fields:
* channel - value "/meta/connect"
* clientId - The client ID returned in the handshake response
* connectionType - The connection type used by the client for the purposes of this connection.
*/
- (void)sendBayeuxConnectMessage
{
NSMutableDictionary *message = [@{MZFayeClientBayeuxMessageChannelKey : MZFayeClientBayeuxChannelConnect,
MZFayeClientBayeuxMessageClientIdKey : self.clientId,
MZFayeClientBayeuxMessageConnectionTypeKey : MZFayeClientBayeuxConnectionTypeWebSocket
} mutableCopy];
NSDictionary *extension = self.channelExtensions[@"connect"];
if (extension) {
[message setObject:extension forKey:MZFayeClientBayeuxMessageExtensionKey];
}
[self writeMessageToWebSocket:message];
}
/**
* A connect request MUST contain the message fields:
* channel - value "/meta/connect"
* clientId - The client ID returned in the handshake response
*/
- (void)sendBayeuxDisconnectMessage
{
NSDictionary *message = @{MZFayeClientBayeuxMessageChannelKey : MZFayeClientBayeuxChannelDisconnect,
MZFayeClientBayeuxMessageClientIdKey : self.clientId
};
[self writeMessageToWebSocket:message];
}
/**
* A subscribe request MUST contain the message fields:
* channel - value "/meta/subscribe"
* clientId - The client ID returned in the handshake response
* subscription - a channel name or a channel pattern or an array of channel names and channel patterns.
*/
- (void)sendBayeuxSubscribeMessageWithChannel:(NSString *)channel
{
NSMutableDictionary *message = [@{
MZFayeClientBayeuxMessageChannelKey : MZFayeClientBayeuxChannelSubscribe,
MZFayeClientBayeuxMessageClientIdKey : self.clientId,
MZFayeClientBayeuxMessageSubscriptionKey : channel
} mutableCopy];
NSDictionary *extension = self.channelExtensions[channel];
if (extension) {
[message setObject:extension forKey:MZFayeClientBayeuxMessageExtensionKey];
}
[self writeMessageToWebSocket:[message copy]];
[self.pendingChannelSubscriptions addObject:channel];
}
/**
* An unsubscribe request MUST contain the message fields:
* channel - value "/meta/unsubscribe"
* clientId - The client ID returned in the handshake response
* subscription - a channel name or a channel pattern or an array of channel names and channel patterns.
*/
- (void)sendBayeuxUnsubscribeMessageWithChannel:(NSString *)channel
{
NSDictionary *message = @{
MZFayeClientBayeuxMessageChannelKey : MZFayeClientBayeuxChannelUnsubscribe,
MZFayeClientBayeuxMessageClientIdKey : self.clientId,
MZFayeClientBayeuxMessageSubscriptionKey : channel
};
[self writeMessageToWebSocket:message];
}
/**
* A publish event message MUST contain the message fields:
* channel
* data - The message as an arbitrary JSON encoded object
*/
- (void)sendBayeuxPublishMessage:(NSDictionary *)messageDictionary withMessageUniqueID:(NSString*)messageId toChannel:(NSString *)channel usingExtension:(NSDictionary *)extension
{
if (!(self.isConnected && self.isWebSocketOpen)) {
[self didFailWithMessage:@"FayeClient not connected to server."];
return;
}
NSMutableDictionary *message = [@{
MZFayeClientBayeuxMessageChannelKey : channel,
MZFayeClientBayeuxMessageClientIdKey : self.clientId,
MZFayeClientBayeuxMessageDataKey : messageDictionary,
MZFayeClientBayeuxMessageIdKey : messageId
} mutableCopy];
if (extension) {
[message setObject:extension forKey:MZFayeClientBayeuxMessageExtensionKey];
} else {
NSDictionary *extensionForChannel = self.channelExtensions[channel];
if (extensionForChannel) {
[message setObject:extensionForChannel forKey:MZFayeClientBayeuxMessageExtensionKey];
}
}
[self writeMessageToWebSocket:[message copy]];
}
- (void)clearSubscriptions
{
[self.pendingChannelSubscriptions removeAllObjects];
[self.openChannelSubscriptions removeAllObjects];
}
#pragma mark - Helper methods
- (NSString *)generateUniqueMessageId
{
self.sentMessageCount++;
return [[NSString stringWithFormat:@"%@", [NSNumber numberWithInteger: self.sentMessageCount]] base64String];
}
#pragma mark - Public methods
- (void)setExtension:(NSDictionary *)extension forChannel:(NSString *)channel
{
[self.channelExtensions setObject:extension forKey:channel];
}
- (void)removeExtensionForChannel:(NSString *)channel
{
[self.channelExtensions removeObjectForKey:channel];
}
- (void)sendMessage:(NSDictionary *)message toChannel:(NSString *)channel
{
NSString *messageId = [self generateUniqueMessageId];
[self sendBayeuxPublishMessage:message withMessageUniqueID:messageId toChannel:channel usingExtension:nil];
}
- (void)sendMessage:(NSDictionary *)message toChannel:(NSString *)channel usingExtension:(NSDictionary *)extension
{
NSString *messageId = [self generateUniqueMessageId];
[self sendBayeuxPublishMessage:message withMessageUniqueID:messageId toChannel:channel usingExtension:extension];
}
- (void)sendMessage:(NSDictionary *)message toChannel:(NSString *)channel usingExtension:(NSDictionary *)extension usingBlock:(MZFayeClientPrivateHandler)subscriptionHandler
{
NSString *messageId = [self generateUniqueMessageId];
if (subscriptionHandler && self.privateChannels[messageId] && messageId) {
self.privateChannels[messageId] = subscriptionHandler;
} else if (self.privateChannels[messageId] || !messageId) {
return;
}
if (subscriptionHandler) {
[self.privateChannels setObject:subscriptionHandler forKey:messageId];
} else {
[self.privateChannels setObject:[NSNull null] forKey:messageId];
}
[self sendBayeuxPublishMessage:message withMessageUniqueID:messageId toChannel:channel usingExtension:extension];
}
- (BOOL)connectToURL:(NSURL *)url
{
if (self.isConnected || self.isWebSocketOpen) {
return NO;
}
_url = url;
return [self connect];
}
- (BOOL)connect
{
if (self.isConnected || self.isWebSocketOpen) {
return NO;
}
[self connectToWebSocket];
return YES;
}
- (void)disconnect
{
[self sendBayeuxDisconnectMessage];
}
- (void)subscribeToChannel:(NSString *)channel
{
[self subscribeToChannel:channel usingBlock:nil];
}
- (void)subscribeToChannel:(NSString *)channel usingBlock:(MZFayeClientSubscriptionHandler)subscriptionHandler
{
if (subscriptionHandler && self.subscribedChannels[channel] && channel) {
self.subscribedChannels[channel] = subscriptionHandler;
} else if (self.subscribedChannels[channel] || !channel) {
return;
}
if (subscriptionHandler) {
[self.subscribedChannels setObject:subscriptionHandler forKey:channel];
} else {
[self.subscribedChannels setObject:[NSNull null] forKey:channel];
}
if (self.isConnected) {
[self sendBayeuxSubscribeMessageWithChannel:channel];
}
}
- (void)unsubscribeFromChannel:(NSString *)channel
{
if (!self.subscribedChannels[channel] || !channel) {
return;
}
[self.subscribedChannels removeObjectForKey:channel];
[self.pendingChannelSubscriptions removeObject:channel];
if (self.isConnected) {
[self sendBayeuxUnsubscribeMessageWithChannel:channel];
}
}
#pragma mark - Private methods
- (void)subscribePendingSubscriptions
{
for (NSString *channel in self.subscribedChannels) {
if (![self.pendingChannelSubscriptions containsObject:channel] && ![self.openChannelSubscriptions containsObject:channel]) {
[self sendBayeuxSubscribeMessageWithChannel:channel];
}
}
}
- (void)reconnectTimer:(NSTimer *)timer
{
if (self.isConnected) {
[self invalidateReconnectTimer];
} else {
if (self.shouldRetryConnection && self.retryAttempt < self.maximumRetryAttempts) {
self.retryAttempt++;
[self connect];
} else {
[self invalidateReconnectTimer];
}
}
}
- (void)invalidateReconnectTimer
{
[self.reconnectTimer invalidate];
self.reconnectTimer = nil;
}
- (void)reconnect
{
if (self.shouldRetryConnection && self.retryAttempt < self.maximumRetryAttempts) {
self.reconnectTimer = [NSTimer scheduledTimerWithTimeInterval:self.retryInterval target:self selector:@selector(reconnectTimer:) userInfo:nil repeats:NO];
}
}
#pragma mark - SRWebSocket
- (void)writeMessageToWebSocket:(NSDictionary *)object
{
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object options:0 error:&error];
if (error) {
if ([self.delegate respondsToSelector:@selector(fayeClient:didFailDeserializeMessage:withError:)]) {
[self.delegate fayeClient:self didFailDeserializeMessage:object withError:error];
}
} else {
NSString *JSON = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
[self.webSocket send:JSON];
}
}
- (void)connectToWebSocket
{
[self disconnectFromWebSocket];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:self.url];
self.webSocket = [[SRWebSocket alloc] initWithURLRequest:request];
self.webSocket.delegate = self;
[self.webSocket open];
}
- (void)disconnectFromWebSocket
{
self.webSocket.delegate = nil;
[self.webSocket close];
self.webSocket = nil;
}
- (void)didFailWithMessage:(NSString *)message
{
if ([self.delegate respondsToSelector:@selector(fayeClient:didFailWithError:)] && message) {
NSError *error = [NSError errorWithDomain:MZFayeClientWebSocketErrorDomain code:-100 userInfo:@{NSLocalizedDescriptionKey : message}];
[self.delegate fayeClient:self didFailWithError:error];
}
}
- (void)handleFayeMessages:(NSArray *)messages
{
for (NSDictionary *message in messages) {
if (![message isKindOfClass:[NSDictionary class]]) {
if ([self.delegate respondsToSelector:@selector(fayeClient:didFailWithError:)]) {
NSError *error = [NSError errorWithDomain:MZFayeClientWebSocketErrorDomain code:-100 userInfo:@{NSLocalizedDescriptionKey : @"Message is not kind of NSDicitionary class"}];
[self.delegate fayeClient:self didFailWithError:error];
}
return;
}
MZFayeMessage *fayeMessage = [MZFayeMessage messageFromDictionary:message];
if ([fayeMessage.channel isEqualToString:MZFayeClientBayeuxChannelHandshake]) {
if ([fayeMessage.successful boolValue]) {
self.retryAttempt = 0;
self.clientId = fayeMessage.clientId;
self.connected = YES;
if ([self.delegate respondsToSelector:@selector(fayeClient:didConnectToURL:)]) {
[self.delegate fayeClient:self didConnectToURL:self.url];
}
[self sendBayeuxConnectMessage];
[self subscribePendingSubscriptions];
} else {
[self didFailWithMessage:[NSString stringWithFormat:@"Faye client couldn't handshake with server. %@",fayeMessage.error]];
}
} else if ([fayeMessage.channel isEqualToString:MZFayeClientBayeuxChannelConnect]) {
if ([fayeMessage.successful boolValue]) {
self.connected = YES;
[self sendBayeuxConnectMessage];
} else {
[self didFailWithMessage:[NSString stringWithFormat:@"Faye client couldn't connect to server. %@",fayeMessage.error]];
}
} else if ([fayeMessage.channel isEqualToString:MZFayeClientBayeuxChannelDisconnect]) {
if ([fayeMessage.successful boolValue]) {
[self disconnectFromWebSocket];
self.connected = NO;
[self clearSubscriptions];
if ([self.delegate respondsToSelector:@selector(fayeClient:didDisconnectWithError:)]) {
[self.delegate fayeClient:self didDisconnectWithError:nil];
}
} else {
[self didFailWithMessage:[NSString stringWithFormat:@"Faye client couldn't disconnect from server. %@",fayeMessage.error]];
}
} else if ([fayeMessage.channel isEqualToString:MZFayeClientBayeuxChannelSubscribe]) {
[self.pendingChannelSubscriptions removeObject:fayeMessage.subscription];
if ([fayeMessage.successful boolValue]) {
[self.openChannelSubscriptions addObject:fayeMessage.subscription];
if ([self.delegate respondsToSelector:@selector(fayeClient:didSubscribeToChannel:)]) {
[self.delegate fayeClient:self didSubscribeToChannel:fayeMessage.subscription];
}
} else {
[self didFailWithMessage:[NSString stringWithFormat:@"Faye client couldn't subscribe channel %@ with server. %@",fayeMessage.subscription, fayeMessage.error]];
}
} else if ([fayeMessage.channel isEqualToString:MZFayeClientBayeuxChannelUnsubscribe]) {
if ([fayeMessage.successful boolValue]) {
[self.subscribedChannels removeObjectForKey:fayeMessage.subscription];
[self.pendingChannelSubscriptions removeObject:fayeMessage.subscription];
[self.openChannelSubscriptions removeObject:fayeMessage.subscription];
if ([self.delegate respondsToSelector:@selector(fayeClient:didUnsubscribeFromChannel:)]) {
[self.delegate fayeClient:self didUnsubscribeFromChannel:fayeMessage.subscription];
}
} else {
[self didFailWithMessage:[NSString stringWithFormat:@"Faye client couldn't unsubscribe channel %@ with server. %@",fayeMessage.subscription, fayeMessage.error]];
}
} else if ([self.openChannelSubscriptions containsObject:fayeMessage.channel]) {
if (self.subscribedChannels[fayeMessage.channel] &&
self.subscribedChannels[fayeMessage.channel] != [NSNull null]) {
MZFayeClientSubscriptionHandler handler = self.subscribedChannels[fayeMessage.channel];
handler(fayeMessage.data);
} else if ([self.delegate respondsToSelector:@selector(fayeClient:didReceiveMessage:fromChannel:)]) {
[self.delegate fayeClient:self didReceiveMessage:fayeMessage.data fromChannel:fayeMessage.channel];
}
} else {
// No match for channel
NSLog(@"Recieved message %@", fayeMessage.ext);
//Handle For Private
if (self.privateChannels[fayeMessage.Id] &&
self.privateChannels[fayeMessage.Id] != [NSNull null]) {
MZFayeClientPrivateHandler handler = self.privateChannels[fayeMessage.Id];
handler(fayeMessage);
}
}
}
}
#pragma mark - SRWebSocket Delegate
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message
{
id recivedMessage = message;
if ([recivedMessage isKindOfClass:[NSString class]]) {
recivedMessage = [recivedMessage dataUsingEncoding:NSUTF8StringEncoding];
}
NSError *error = nil;
NSArray *messages = [NSJSONSerialization JSONObjectWithData:recivedMessage options:0 error:&error];
if (error && [self.delegate respondsToSelector:@selector(fayeClient:didFailDeserializeMessage:withError:)]) {
[self.delegate fayeClient:self didFailDeserializeMessage:recivedMessage withError:error];
} else {
[self handleFayeMessages:messages];
}
}
- (void)webSocketDidOpen:(SRWebSocket *)webSocket
{
[self sendBayeuxHandshakeMessage];
}
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error
{
self.connected = NO;
[self clearSubscriptions];
if ([self.delegate respondsToSelector:@selector(fayeClient:didFailWithError:)]) {
[self.delegate fayeClient:self didFailWithError:error];
}
[self reconnect];
}
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code
reason:(NSString *)reason wasClean:(BOOL)wasClean
{
self.connected = NO;
[self clearSubscriptions];
if ([self.delegate respondsToSelector:@selector(fayeClient:didDisconnectWithError:)]) {
NSError *error = nil;
if (reason) {
error = [NSError errorWithDomain:MZFayeClientWebSocketErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : reason}];
}
[self.delegate fayeClient:self didDisconnectWithError:error];
}
[self reconnect];
}
@end
+47
View File
@@ -0,0 +1,47 @@
//
// MZFayeMessage.h
// MZFayeClient
//
// Created by Michał Zaborowski on 12.12.2013.
// Copyright (c) 2013 Michał Zaborowski. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
@interface MZFayeMessage : NSObject
@property (nonatomic, strong) NSString *Id;
@property (nonatomic, strong) NSString *channel;
@property (nonatomic, strong) NSString *clientId;
@property (nonatomic, strong) NSNumber *successful;
@property (nonatomic, strong) NSNumber *authSuccessful;
@property (nonatomic, strong) NSString *version;
@property (nonatomic, strong) NSString *minimumVersion;
@property (nonatomic, strong) NSArray *supportedConnectionTypes;
@property (nonatomic, strong) NSDictionary *advice;
@property (nonatomic, strong) NSString *error;
@property (nonatomic, strong) NSString *subscription;
@property (nonatomic, strong) NSDate *timestamp;
@property (nonatomic, strong) NSDictionary *data;
@property (nonatomic, strong) NSDictionary *ext;
+ (instancetype)messageFromDictionary:(NSDictionary *)dictionary;
@end
+56
View File
@@ -0,0 +1,56 @@
//
// MZFayeMessage.m
// MZFayeClient
//
// Created by Michał Zaborowski on 12.12.2013.
// Copyright (c) 2013 Michał Zaborowski. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "MZFayeMessage.h"
@implementation MZFayeMessage
- (instancetype)initFromDictionary:(NSDictionary *)dictionary
{
if (self = [super init]) {
self.Id = dictionary[@"id"];
self.channel = dictionary[@"channel"];
self.clientId = dictionary[@"clientId"];
self.successful = @([dictionary[@"successful"] boolValue]);
self.authSuccessful = @([dictionary[@"authSuccessful"] boolValue]);
self.version = dictionary[@"version"];
self.minimumVersion = dictionary[@"minimumVersion"];
self.supportedConnectionTypes = dictionary[@"supportedConnectionTypes"];
self.advice = dictionary[@"advice"];
self.error = dictionary[@"error"];
self.subscription = dictionary[@"subscription"];
self.timestamp = [NSDate dateWithTimeIntervalSince1970:[dictionary[@"timestamp"] timeInterval]];
self.data = dictionary[@"data"];
self.ext = dictionary[@"ext"];
}
return self;
}
+ (instancetype)messageFromDictionary:(NSDictionary *)dictionary
{
return [[[self class] alloc] initFromDictionary:dictionary];
}
@end
+1
View File
@@ -4,3 +4,4 @@
#import <UIKit/UIKit.h>
#import "APService.h"
#import "MZFayeClient.h"