pbind 0.6.2 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,6 +15,8 @@
15
15
 
16
16
  @interface PBLLInspectorController : UIViewController
17
17
 
18
+ + (void)presentFromViewController:(UIViewController *)viewController;
19
+
18
20
  @end
19
21
 
20
22
  #endif
@@ -11,8 +11,21 @@
11
11
 
12
12
  #import "PBLLInspector.h"
13
13
  #import "PBLLRemoteWatcher.h"
14
+ #import "PBLLResource.h"
14
15
  #import <Pbind/Pbind.h>
15
16
 
17
+ @interface _PBLLWrapperNavigationController : UINavigationController
18
+
19
+ @end
20
+
21
+ @implementation _PBLLWrapperNavigationController
22
+
23
+ - (UIStatusBarStyle)preferredStatusBarStyle {
24
+ return UIStatusBarStyleLightContent;
25
+ }
26
+
27
+ @end
28
+
16
29
  @interface PBLLInspectorController () <UISearchBarDelegate>
17
30
  {
18
31
  UISearchBar *_searchBar;
@@ -25,27 +38,77 @@
25
38
  - (void)viewDidLoad {
26
39
  [super viewDidLoad];
27
40
  // Do any additional setup after loading the view.
41
+ self.title = [PBLLResource pbindTitle];
42
+ UIColor *primaryColor = [PBLLResource pbindColor];
43
+ UINavigationBar *navigationBar = self.navigationController.navigationBar;
44
+ [navigationBar setBarTintColor:primaryColor];
45
+ [navigationBar setTintColor:[UIColor whiteColor]];
46
+ [navigationBar setBackgroundImage:[UIImage new] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
47
+ [navigationBar setShadowImage:[UIImage new]];
48
+ [navigationBar setTranslucent:NO];
49
+ [navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}];
50
+ self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self action:@selector(dismiss)];
51
+
28
52
  self.edgesForExtendedLayout = UIRectEdgeNone;
29
53
  self.view.backgroundColor = [UIColor whiteColor];
30
54
  CGRect frame = self.view.bounds;
31
55
  frame.size.height = 44.f;
32
- frame.origin.y = 16.f;
33
56
  UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:frame];
34
- searchBar.text = [self defaultIP];
57
+ searchBar.barTintColor = primaryColor;
58
+ searchBar.text = [PBLLRemoteWatcher globalWatcher].defaultIP;
35
59
  searchBar.delegate = self;
36
60
  searchBar.returnKeyType = UIReturnKeyJoin;
61
+ searchBar.barStyle = UISearchBarStyleMinimal;
37
62
  [self.view addSubview:searchBar];
38
63
  _searchBar = searchBar;
64
+ [searchBar becomeFirstResponder];
65
+
66
+ // Help label
67
+ UILabel *helpLabel = [[UILabel alloc] init];
68
+ helpLabel.font = [UIFont systemFontOfSize:14.f];
69
+ helpLabel.numberOfLines = 0;
70
+ helpLabel.textColor = PBColorMake(@"666");
71
+ helpLabel.text = @(
72
+ "Input the IP of the pbind server started by:\n"
73
+ "\n"
74
+ " > gem install pbind" "\n"
75
+ " > cd [path-to-xcodeproj]" "\n"
76
+ " > pbind serv" "\n"
77
+ "\n"
78
+ "Then click [Join] to start online debugging.");
79
+ [self.view addSubview:helpLabel];
80
+
81
+ frame.origin.y += frame.size.height + 44.f;
82
+ frame.origin.x = 32.f;
83
+ frame.size.width = frame.size.width - 64.f;
84
+ frame.size.height = [helpLabel sizeThatFits:frame.size].height;
85
+ helpLabel.frame = frame;
39
86
 
40
87
  UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTap:)];
41
88
  [self.view addGestureRecognizer:tap];
42
89
  }
43
90
 
91
+ + (void)presentFromViewController:(UIViewController *)viewController {
92
+ PBLLInspectorController *inspectorVC = [[PBLLInspectorController alloc] init];
93
+ UINavigationController *nav = [[_PBLLWrapperNavigationController alloc] initWithRootViewController:inspectorVC];
94
+ [viewController presentViewController:nav animated:YES completion:nil];
95
+ }
96
+
44
97
  - (void)viewWillAppear:(BOOL)animated {
45
98
  [super viewWillAppear:animated];
46
99
  [PBLLInspector sharedInspector].hidden = YES;
47
100
  }
48
101
 
102
+ - (void)viewDidAppear:(BOOL)animated {
103
+ [super viewDidAppear:animated];
104
+ [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
105
+ }
106
+
107
+ - (void)viewWillDisappear:(BOOL)animated {
108
+ [super viewWillDisappear:animated];
109
+ [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
110
+ }
111
+
49
112
  - (void)viewDidDisappear:(BOOL)animated {
50
113
  [super viewDidDisappear:animated];
51
114
  [PBLLInspector sharedInspector].hidden = NO;
@@ -56,19 +119,6 @@
56
119
  // Dispose of any resources that can be recreated.
57
120
  }
58
121
 
59
- - (NSString *)defaultIP {
60
- NSString *ip = [[NSUserDefaults standardUserDefaults] objectForKey:@"pbind.server.ip"];
61
- if (ip == nil) {
62
- ip = @"192.168.1.10";
63
- }
64
- return ip;
65
- }
66
-
67
- - (void)setDefaultIP:(NSString *)ip {
68
- [[NSUserDefaults standardUserDefaults] setObject:ip forKey:@"pbind.server.ip"];
69
- [[NSUserDefaults standardUserDefaults] synchronize];
70
- }
71
-
72
122
  #pragma mark - UISearchBarDelegate
73
123
 
74
124
  - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
@@ -77,9 +127,8 @@
77
127
  return;
78
128
  }
79
129
 
80
- [self setDefaultIP:ip];
81
130
  [[PBLLRemoteWatcher globalWatcher] connect:ip];
82
- [self.navigationController popViewControllerAnimated:YES];
131
+ [self dismiss];
83
132
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
84
133
  [PBTopController().view pb_reloadClient];
85
134
  });
@@ -91,6 +140,11 @@
91
140
  [_searchBar resignFirstResponder];
92
141
  }
93
142
 
143
+ - (void)dismiss {
144
+ [_searchBar resignFirstResponder];
145
+ [self.navigationController dismissViewControllerAnimated:YES completion:nil];
146
+ }
147
+
94
148
  @end
95
149
 
96
150
  #endif
@@ -0,0 +1,23 @@
1
+ //
2
+ // PBLLInspectorTipsController.h
3
+ // Pbind
4
+ //
5
+ // Created by galen on 17/7/29.
6
+ //
7
+
8
+ #import "PBLLOptions.h"
9
+ #include <targetconditionals.h>
10
+
11
+ #if (PBLIVE_ENABLED)
12
+
13
+ #import <UIKit/UIKit.h>
14
+
15
+ @interface PBLLInspectorTipsController : UIViewController
16
+
17
+ @property (nonatomic, strong) NSString *tips;
18
+
19
+ @property (nonatomic, strong) NSString *code;
20
+
21
+ @end
22
+
23
+ #endif
@@ -0,0 +1,140 @@
1
+ //
2
+ // PBLLInspectorTipsController.m
3
+ // Pbind
4
+ //
5
+ // Created by galen on 17/7/29.
6
+ //
7
+
8
+ #import "PBLLInspectorTipsController.h"
9
+
10
+ #if (PBLIVE_ENABLED)
11
+
12
+ #import "PBLLRemoteWatcher.h"
13
+ #import "PBLLResource.h"
14
+ #import <Pbind/Pbind.h>
15
+
16
+ @interface PBLLInspectorTipsController ()
17
+
18
+ @property (nonatomic, strong) UILabel *tipsLabel;
19
+ @property (nonatomic, strong) UIToolbar *toolbar;
20
+ @property (nonatomic, assign) CGFloat preferredWidth;
21
+ @property (nonatomic, strong) UIBarButtonItem *codeOrTipsItem;
22
+
23
+ @end
24
+
25
+ @implementation PBLLInspectorTipsController
26
+
27
+ static BOOL kDisplaysCode = NO;
28
+
29
+ - (void)viewDidLoad {
30
+ [super viewDidLoad];
31
+ // Do any additional setup after loading the view.
32
+
33
+ CGRect rect = [UIScreen mainScreen].bounds;
34
+ _preferredWidth = rect.size.width * 2.f / 3.f;
35
+
36
+ rect.origin.x = 16.f;
37
+ rect.origin.y = 16.f;
38
+ UILabel *label = [[UILabel alloc] initWithFrame:rect];
39
+ label.textColor = [UIColor whiteColor];
40
+ label.text = self.tips;
41
+ label.font = [UIFont systemFontOfSize:12.f];
42
+ label.numberOfLines = 0;
43
+ rect.size.height = [label sizeThatFits:rect.size].height;
44
+ label.frame = rect;
45
+
46
+ [self.view addSubview:label];
47
+ _tipsLabel = label;
48
+
49
+ UIToolbar *toolbar = [[UIToolbar alloc] init];
50
+ [toolbar setBarTintColor:self.popoverPresentationController.backgroundColor];
51
+ [toolbar setTintColor:[UIColor whiteColor]];
52
+
53
+ NSMutableArray *items = [NSMutableArray arrayWithCapacity:4];
54
+ [items addObject:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self action:@selector(handleClose:)]];
55
+ [items addObject:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]];
56
+ if (self.code != nil) {
57
+ _codeOrTipsItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:self action:@selector(handleToggleCode:)];
58
+ [items addObject:_codeOrTipsItem];
59
+
60
+ [items addObject:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]];
61
+ }
62
+ // Copy
63
+ [items addObject:[[UIBarButtonItem alloc] initWithImage:[PBLLResource copyImage] style:UIBarButtonItemStylePlain target:self action:@selector(handleCopy:)]];
64
+ #if !(TARGET_IPHONE_SIMULATOR)
65
+ // Post
66
+ UIBarButtonItem *postItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemReply target:self action:@selector(handlePost:)];
67
+ [items addObject:postItem];
68
+ #endif
69
+
70
+ toolbar.items = items;
71
+ [self.view addSubview:toolbar];
72
+ _toolbar = toolbar;
73
+
74
+ [self render];
75
+ }
76
+
77
+ - (void)render {
78
+ [self renderWithAnimated:NO];
79
+ }
80
+
81
+ - (void)renderWithAnimated:(BOOL)animated {
82
+ dispatch_block_t renderBlock = ^{
83
+ if (_code != nil) {
84
+ if (kDisplaysCode) {
85
+ _codeOrTipsItem.title = @"Value";
86
+ _tipsLabel.text = _code;
87
+ } else {
88
+ _codeOrTipsItem.title = @"Code";
89
+ _tipsLabel.text = _tips;
90
+ }
91
+ } else {
92
+ _tipsLabel.text = _tips;
93
+ }
94
+
95
+ CGRect rect = CGRectMake(16.f, 16.f, _preferredWidth - 32.f, CGFLOAT_MAX);
96
+ rect.size.height = [_tipsLabel sizeThatFits:rect.size].height;
97
+ _tipsLabel.frame = rect;
98
+
99
+ rect.origin.x = 0.f;
100
+ rect.origin.y += rect.size.height + 16.f;
101
+ rect.size.width = _preferredWidth;
102
+ rect.size.height = 44.f;
103
+ _toolbar.frame = rect;
104
+
105
+ rect.size.height += rect.origin.y;
106
+ self.preferredContentSize = rect.size;
107
+ };
108
+ if (animated) {
109
+ [UIView animateWithDuration:.25f animations:renderBlock completion:^(BOOL finished) {
110
+ [self.popoverPresentationController.containerView setNeedsLayout];
111
+ }];
112
+ } else {
113
+ renderBlock();
114
+ }
115
+ }
116
+
117
+ #pragma mark - BarButtonItem
118
+
119
+ - (void)handleClose:(id)sender {
120
+ [self dismissViewControllerAnimated:YES completion:nil];
121
+ }
122
+
123
+ - (void)handleToggleCode:(id)sender {
124
+ kDisplaysCode = !kDisplaysCode;
125
+ [self renderWithAnimated:YES];
126
+ }
127
+
128
+ - (void)handleCopy:(id)sender {
129
+ [UIPasteboard generalPasteboard].string = _tipsLabel.text;
130
+ }
131
+
132
+ #if !(TARGET_IPHONE_SIMULATOR)
133
+ - (void)handlePost:(id)sender {
134
+ [[PBLLRemoteWatcher globalWatcher] sendLog:_tips];
135
+ }
136
+ #endif
137
+
138
+ @end
139
+
140
+ #endif
@@ -5,4 +5,4 @@
5
5
  // Created by Galen Lin on 25/03/2017.
6
6
  //
7
7
 
8
- #define PBLIVE_ENABLED DEBUG
8
+ #define PBLIVE_ENABLED (DEBUG || PROFILE)
@@ -24,6 +24,8 @@
24
24
  - (void)remoteWatcher:(PBLLRemoteWatcher *)watcher didCreateFile:(NSString *)fileName;
25
25
  - (void)remoteWatcher:(PBLLRemoteWatcher *)watcher didDeleteFile:(NSString *)fileName;
26
26
 
27
+ - (void)remoteWatcher:(PBLLRemoteWatcher *)watcher didChangeConnectState:(BOOL)connected;
28
+
27
29
  @end
28
30
 
29
31
  @interface PBLLRemoteWatcher : NSObject
@@ -35,8 +37,12 @@
35
37
 
36
38
  - (void)requestAPI:(NSString *)api success:(void (^)(NSData *))success failure:(void (^)(NSError *))failure;
37
39
 
40
+ - (void)sendLog:(NSString *)log;
41
+
38
42
  @property (nonatomic, assign) id<PBLLRemoteWatcherDelegate> delegate;
39
43
 
44
+ @property (nonatomic, strong, readonly) NSString *defaultIP;
45
+
40
46
  @end
41
47
 
42
48
  #endif
@@ -16,17 +16,25 @@
16
16
  {
17
17
  NSInputStream *inputStream;
18
18
  NSOutputStream *outputStream;
19
- void (^responseBlock)(NSData *);
19
+ void (^apiSuccessBlock)(NSData *);
20
+ void (^apiFailureBolck)(NSError *);
20
21
  BOOL streamOpened;
21
22
  NSData *apiReqData;
22
23
  NSString *tempResourcesPath;
23
24
  NSString *connectedIP;
25
+ NSInteger retryCount;
24
26
  }
25
27
 
26
28
  @end
27
29
 
28
30
  @implementation PBLLRemoteWatcher
29
31
 
32
+ static const NSTimeInterval kTimeoutSeconds = 3.f;
33
+ static NSString *const kServerIPUserDefaultsKey = @"pbind.server.ip";
34
+ static NSString *const kDefaultServerIP = @"192.168.1.10";
35
+ static const NSInteger kServerPort = 8082;
36
+ static const NSInteger kMaxRetryCount = 5;
37
+
30
38
  + (instancetype)globalWatcher {
31
39
  static PBLLRemoteWatcher *o;
32
40
  static dispatch_once_t onceToken;
@@ -39,10 +47,15 @@
39
47
  - (void)connect:(NSString *)ip {
40
48
  [self close];
41
49
 
50
+ if (ip == nil) {
51
+ return;
52
+ }
53
+
42
54
  connectedIP = ip;
55
+ [[NSUserDefaults standardUserDefaults] setObject:ip forKey:kServerIPUserDefaultsKey];
43
56
  CFReadStreamRef readStream;
44
57
  CFWriteStreamRef writeStream;
45
- CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)ip, 8082, &readStream, &writeStream);
58
+ CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)ip, kServerPort, &readStream, &writeStream);
46
59
  inputStream = (__bridge NSInputStream *)readStream;
47
60
  outputStream = (__bridge NSOutputStream *)writeStream;
48
61
  inputStream.delegate = self;
@@ -54,11 +67,15 @@
54
67
  }
55
68
 
56
69
  - (void)connectDefaultIP {
57
- NSString *ip = [[NSUserDefaults standardUserDefaults] objectForKey:@"pbind.server.ip"];
70
+ [self connect:self.defaultIP];
71
+ }
72
+
73
+ - (NSString *)defaultIP {
74
+ NSString *ip = [[NSUserDefaults standardUserDefaults] objectForKey:kServerIPUserDefaultsKey];
58
75
  if (ip == nil) {
59
- ip = @"192.168.1.2";
76
+ ip = kDefaultServerIP;
60
77
  }
61
- [self connect:ip];
78
+ return ip;
62
79
  }
63
80
 
64
81
  - (void)requestAPI:(NSString *)api success:(void (^)(NSData *))success failure:(void (^)(NSError *))failure {
@@ -69,13 +86,31 @@
69
86
  return;
70
87
  }
71
88
 
72
- responseBlock = success;
73
- NSData *data = [api dataUsingEncoding:NSUTF8StringEncoding];
89
+ apiSuccessBlock = success;
90
+ apiFailureBolck = failure;
91
+
92
+ NSData *reqData = [self dataWithMessage:api event:PBLLRemoteEventJsonRequest];
74
93
  if (streamOpened) {
75
- [outputStream write:[data bytes] maxLength:[data length]];
94
+ [self sendData:reqData];
76
95
  } else {
77
- apiReqData = data;
96
+ // apiReqData = reqData;
97
+ failure(nil);
98
+ return;
78
99
  }
100
+
101
+ NSLog(@"---- perform delay onTimeout");
102
+ [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onTimeout) object:nil];
103
+ [self performSelector:@selector(onTimeout) withObject:nil afterDelay:kTimeoutSeconds];
104
+ }
105
+
106
+ - (void)onTimeout {
107
+ if (apiFailureBolck) {
108
+ apiFailureBolck([NSError errorWithDomain:@"PBLLRemoteWatcher"
109
+ code:-1
110
+ userInfo:@{NSLocalizedDescriptionKey: @"Server no response"}]);
111
+ apiFailureBolck = nil;
112
+ }
113
+ apiSuccessBlock = nil;
79
114
  }
80
115
 
81
116
  - (void)close {
@@ -90,10 +125,67 @@
90
125
  streamOpened = NO;
91
126
  }
92
127
 
128
+ #pragma mark - Communication
129
+
130
+ typedef NS_ENUM(NSUInteger, PBLLRemoteEvent) {
131
+ // client events
132
+ PBLLRemoteEventConnected = 0xC0,
133
+ PBLLRemoteEventJsonRequest = 0xC1,
134
+ PBLLRemoteEventLog = 0xC2,
135
+
136
+ // server events - data
137
+ PBLLRemoteEventDataJson = 0xD0,
138
+
139
+ // server events - error
140
+ PBLLRemoteEventErrorIgnored = 0xE0,
141
+
142
+ // server events - file
143
+ PBLLRemoteEventFileCreated = 0xF0,
144
+ PBLLRemoteEventFileUpdated = 0xF1,
145
+ PBLLRemoteEventFileDeleted = 0xF2,
146
+ };
147
+
148
+ - (void)sendMessage:(NSString *)message {
149
+ NSData *msgData = [message dataUsingEncoding:NSUTF8StringEncoding];
150
+ [self sendData:msgData];
151
+ }
152
+
153
+ - (void)sendLog:(NSString *)log {
154
+ [self sendMessage:log event:PBLLRemoteEventLog];
155
+ }
156
+
157
+ - (void)sendConnectedMessage {
158
+ NSString *osModel = [[UIDevice currentDevice] name];
159
+ NSString *osVersion = [[UIDevice currentDevice] systemVersion];
160
+ NSString *deviceName = [NSString stringWithFormat:@"%@(%@)", osModel, osVersion];
161
+ [self sendMessage:deviceName event:PBLLRemoteEventConnected];
162
+ }
163
+
164
+ - (void)sendMessage:(NSString *)message event:(PBLLRemoteEvent)event {
165
+ NSData *data = [self dataWithMessage:message event:event];
166
+ [self sendData:data];
167
+ }
168
+
169
+ - (void)sendData:(NSData *)data {
170
+ if (!streamOpened) {
171
+ return;
172
+ }
173
+
174
+ [outputStream write:[data bytes] maxLength:[data length]];
175
+ }
176
+
177
+ - (NSData *)dataWithMessage:(NSString *)message event:(PBLLRemoteEvent)event {
178
+ NSData *msgData = [message dataUsingEncoding:NSUTF8StringEncoding];
179
+ NSUInteger len = msgData.length + 1;
180
+ NSMutableData *data = [[NSMutableData alloc] initWithCapacity:len];
181
+ [data appendBytes:&event length:1];
182
+ [data appendData:msgData];
183
+ return data;
184
+ }
185
+
93
186
  #pragma mark - NSStreamDelegate
94
187
 
95
188
  - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
96
- NSLog(@"socket: %i, %@", (int)eventCode, aStream);
97
189
  switch (eventCode) {
98
190
  case NSStreamEventOpenCompleted:
99
191
  break;
@@ -102,47 +194,71 @@
102
194
  if (!streamOpened) {
103
195
  streamOpened = YES;
104
196
 
105
- // Send connected message
106
- NSString *osModel = [[UIDevice currentDevice] name];
107
- NSString *osVersion = [[UIDevice currentDevice] systemVersion];
108
- NSString *msg = [NSString stringWithFormat:@"[C]%@(%@)", osModel, osVersion];
109
- NSData *msgData = [msg dataUsingEncoding:NSUTF8StringEncoding];
110
- [outputStream write:[msgData bytes] maxLength:[msgData length]];
197
+ [self sendConnectedMessage];
198
+
199
+ if ([self.delegate respondsToSelector:@selector(remoteWatcher:didChangeConnectState:)]) {
200
+ [self.delegate remoteWatcher:self didChangeConnectState:YES];
201
+ }
111
202
  }
112
203
 
113
- if (apiReqData != nil) {
114
- [outputStream write:[apiReqData bytes] maxLength:[apiReqData length]];
115
- apiReqData = nil;
116
- }
204
+ // if (apiReqData != nil) {
205
+ // [self sendData:apiReqData];
206
+ // apiReqData = nil;
207
+ // }
117
208
  }
118
209
  break;
119
210
  case NSStreamEventHasBytesAvailable:
120
211
  if (aStream == inputStream) {
121
- NSLog(@"inputStream is ready.");
122
-
123
212
  uint8_t type[1];
124
213
  [inputStream read:type maxLength:1];
125
- switch (*type) {
126
- case 0xE0: { // Got json
214
+ PBLLRemoteEvent event = *type;
215
+ switch (event) {
216
+ case PBLLRemoteEventDataJson: { // Got json
217
+ NSString *jsonName = [inputStream readString];
127
218
  NSData *jsonData = [inputStream readData];
128
- if (responseBlock != nil) {
129
- responseBlock(jsonData);
219
+ NSLog(@"---- cancel onTimeout");
220
+ [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onTimeout) object:nil];
221
+ if (apiSuccessBlock != nil) {
222
+ apiSuccessBlock(jsonData);
223
+ apiSuccessBlock = nil;
224
+ }
225
+ apiFailureBolck = nil;
226
+ [self sendMessage:jsonName event:PBLLRemoteEventDataJson];
227
+ break;
228
+ }
229
+ case PBLLRemoteEventErrorIgnored: { // Ingores API
230
+ [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onTimeout) object:nil];
231
+ if (apiFailureBolck != nil) {
232
+ apiFailureBolck([NSError errorWithDomain:@"PBLLRemoteWatcher" code:-2 userInfo:@{NSLocalizedDescriptionKey: @"User ignores the API"}]);
130
233
  }
234
+ apiSuccessBlock = nil;
131
235
  break;
132
236
  }
133
- case 0xF0: { // Create file
237
+ case PBLLRemoteEventFileCreated: { // Create file
134
238
  NSString *fileName = [inputStream readString];
239
+ if (fileName == nil) {
240
+ break;
241
+ }
242
+ [self sendMessage:fileName event:event];
135
243
  [self.delegate remoteWatcher:self didCreateFile:fileName];
136
244
  break;
137
245
  }
138
- case 0xF1: { // Update file
246
+ case PBLLRemoteEventFileUpdated: { // Update file
139
247
  NSString *fileName = [inputStream readString];
248
+ if (fileName == nil) {
249
+ break;
250
+ }
140
251
  NSData *fileData = [inputStream readData];
252
+ [self sendMessage:fileName event:event];
141
253
  [self.delegate remoteWatcher:self didUpdateFile:fileName withData:fileData];
142
254
  break;
143
255
  }
144
- case 0xF2: { // Delete file
256
+ case PBLLRemoteEventFileDeleted: { // Delete file
145
257
  NSString *fileName = [inputStream readString];
258
+ if (fileName == nil) {
259
+ break;
260
+ }
261
+ [self sendMessage:fileName event:event];
146
262
  [self.delegate remoteWatcher:self didDeleteFile:fileName];
147
263
  break;
148
264
  }
@@ -153,14 +269,24 @@
153
269
  break;
154
270
  case NSStreamEventErrorOccurred:
155
271
  if (aStream == outputStream) {
272
+ retryCount++;
273
+ if (retryCount >= kMaxRetryCount) {
274
+ retryCount = 0;
275
+ break;
276
+ }
277
+
156
278
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
157
279
  [self connect:connectedIP];
158
280
  });
159
281
  }
282
+ NSLog(@"[PBLLRemoteWatcher] %@", [aStream streamError]);
160
283
  break;
161
284
  case NSStreamEventEndEncountered:
162
285
  if (aStream == inputStream) {
163
286
  [self close];
287
+ if ([self.delegate respondsToSelector:@selector(remoteWatcher:didChangeConnectState:)]) {
288
+ [self.delegate remoteWatcher:self didChangeConnectState:NO];
289
+ }
164
290
  }
165
291
  break;
166
292
  default: