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.
- checksums.yaml +4 -4
- data/lib/pbind/command.rb +2 -0
- data/lib/pbind/command/mock.rb +1 -1
- data/lib/pbind/command/serv.rb +78 -16
- data/lib/pbind/command/view.rb +86 -0
- data/lib/pbind/gem_version.rb +1 -1
- data/lib/pbind/minify.rb +52 -0
- data/source/PBLiveLoader/NSInputStream+Reader.m +10 -0
- data/source/PBLiveLoader/PBLLInspector.h +2 -2
- data/source/PBLiveLoader/PBLLInspector.m +385 -22
- data/source/PBLiveLoader/PBLLInspectorController.h +2 -0
- data/source/PBLiveLoader/PBLLInspectorController.m +71 -17
- data/source/PBLiveLoader/PBLLInspectorTipsController.h +23 -0
- data/source/PBLiveLoader/PBLLInspectorTipsController.m +140 -0
- data/source/PBLiveLoader/PBLLOptions.h +1 -1
- data/source/PBLiveLoader/PBLLRemoteWatcher.h +6 -0
- data/source/PBLiveLoader/PBLLRemoteWatcher.m +155 -29
- data/source/PBLiveLoader/PBLLResource.h +25 -0
- data/source/PBLiveLoader/PBLLResource.m +208 -0
- data/source/PBLiveLoader/PBLiveLoader.m +44 -8
- metadata +8 -3
@@ -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.
|
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
|
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
|
@@ -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 (^
|
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,
|
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
|
-
|
70
|
+
[self connect:self.defaultIP];
|
71
|
+
}
|
72
|
+
|
73
|
+
- (NSString *)defaultIP {
|
74
|
+
NSString *ip = [[NSUserDefaults standardUserDefaults] objectForKey:kServerIPUserDefaultsKey];
|
58
75
|
if (ip == nil) {
|
59
|
-
ip =
|
76
|
+
ip = kDefaultServerIP;
|
60
77
|
}
|
61
|
-
|
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
|
-
|
73
|
-
|
89
|
+
apiSuccessBlock = success;
|
90
|
+
apiFailureBolck = failure;
|
91
|
+
|
92
|
+
NSData *reqData = [self dataWithMessage:api event:PBLLRemoteEventJsonRequest];
|
74
93
|
if (streamOpened) {
|
75
|
-
[
|
94
|
+
[self sendData:reqData];
|
76
95
|
} else {
|
77
|
-
apiReqData =
|
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
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
-
[
|
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
|
-
|
126
|
-
|
214
|
+
PBLLRemoteEvent event = *type;
|
215
|
+
switch (event) {
|
216
|
+
case PBLLRemoteEventDataJson: { // Got json
|
217
|
+
NSString *jsonName = [inputStream readString];
|
127
218
|
NSData *jsonData = [inputStream readData];
|
128
|
-
|
129
|
-
|
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
|
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
|
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
|
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:
|