-
Notifications
You must be signed in to change notification settings - Fork 0
/
NetConnection.m
131 lines (109 loc) · 3.18 KB
/
NetConnection.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#import "NetConnection.h"
//---------------------------------------------------------------------------
@interface NetConnection (Private)
- (id)initWithURL:(NSURL*)url;
- (BOOL)isNetworkConnected;
- (void)changedKey:(NSString*)key userInfo:(NSDictionary*)userInfo;
@end
//---------------------------------------------------------------------------
void _NetConnectionNotificationCallback(
SCDynamicStoreRef store,
CFArrayRef changedKeys,
void* source) {
NSString* key;
NSDictionary* info;
NSEnumerator* keysE = [(NSArray *)changedKeys objectEnumerator];
while (key = [keysE nextObject]) {
info = (NSDictionary*)SCDynamicStoreCopyValue(store, (CFStringRef)key);
[(NetConnection*)source changedKey:key userInfo:info];
[info release];
}
}
//---------------------------------------------------------------------------
@implementation NetConnection
static NetConnection* instance = nil;
+ (NetConnection*)netConnection
{
if (instance == nil) {
NSURL* url = [NSURL URLWithString:@"http://www.google.com/"];
instance = [[NetConnection alloc] initWithURL:url];
}
return instance;
}
- (void)dealloc
{
// remove dynamic store
CFRunLoopRemoveSource(
[[NSRunLoop currentRunLoop] getCFRunLoop],
runLoopSource,
kCFRunLoopCommonModes
);
CFRelease(runLoopSource);
CFRelease(dynamicStore);
[super dealloc];
}
- (BOOL)isOnline
{
return isOnline;
}
@end
//---------------------------------------------------------------------------
@implementation NetConnection (Private)
- (id)initWithURL:(NSURL*)url
{
self = [super init];
if (self) {
// check present connectivity
connectivityURL = [url retain];
isOnline = [self isNetworkConnected];
// set up dynamic store
SCDynamicStoreContext context = {0, (void *)self, NULL, NULL, NULL};
dynamicStore = SCDynamicStoreCreate(
NULL,
(CFStringRef) [[NSBundle mainBundle] bundleIdentifier],
_NetConnectionNotificationCallback,
&context
);
// add dynamic store to run loop
runLoopSource = SCDynamicStoreCreateRunLoopSource(NULL, dynamicStore, 0);
CFRunLoopAddSource(
[[NSRunLoop currentRunLoop] getCFRunLoop],
runLoopSource,
kCFRunLoopCommonModes
);
// only observe ip changes
BOOL success = SCDynamicStoreSetNotificationKeys(
dynamicStore,
NULL,
(CFArrayRef)[NSArray arrayWithObject:@"State:/Network/Global/IP.*"]
);
if (!success) {
NSLog(@"Error: keys could not be observed.");
}
}
return self;
}
- (BOOL)isNetworkConnected
{
SCNetworkConnectionFlags status;
BOOL success = SCNetworkCheckReachabilityByName(
[[connectivityURL host] UTF8String],
&status
);
success = success
&& (status & kSCNetworkFlagsReachable)
&& !(status & kSCNetworkFlagsConnectionRequired);
return success;
}
- (void)changedKey:(NSString*)key userInfo:(NSDictionary*)userInfo
{
BOOL wasOnline = isOnline;
isOnline = userInfo != nil;
if (wasOnline != isOnline) {
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:kNetConnectionChangeNotification
object:self
userInfo:userInfo];
}
}
@end