MIduo.xcodeproj/project.pbxproj
@@ -491,10 +491,6 @@ 2D0DF78D20C642AE002BB619 /* SJUnbindPhoneViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2D0DF78B20C642AE002BB619 /* SJUnbindPhoneViewController.xib */; }; 2D0E729620C0DAE600822DC8 /* SJButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D0E729520C0DAE600822DC8 /* SJButton.m */; }; 2D0F7DB620D0F91600355B51 /* SJTransitionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D0F7DB520D0F91600355B51 /* SJTransitionView.m */; }; 2D100B63212159D000109DAF /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D100B5C212159CF00109DAF /* Reachability.m */; }; 2D100B64212159D000109DAF /* SGNetObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D100B5E212159CF00109DAF /* SGNetObserver.m */; }; 2D100B65212159D000109DAF /* SimplePing.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D100B60212159CF00109DAF /* SimplePing.m */; }; 2D100B66212159D000109DAF /* SimplePinger.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D100B62212159CF00109DAF /* SimplePinger.m */; }; 2D10FAC32108613500C4C3E0 /* WXBindTipsView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D10FAC22108613500C4C3E0 /* WXBindTipsView.m */; }; 2D1175B121199F4000D4CD0F /* ObtainProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D1175AB21199F3F00D4CD0F /* ObtainProperty.m */; }; 2D1175B221199F4000D4CD0F /* PlistFileOperator.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D1175AC21199F3F00D4CD0F /* PlistFileOperator.m */; }; @@ -543,6 +539,10 @@ 2DEAE78220EC6748003349B4 /* SJNetwork.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DEAE78120EC6748003349B4 /* SJNetwork.m */; }; 2DEF568120FF20990071C985 /* SJTipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DEF568020FF20990071C985 /* SJTipView.m */; }; 2DEF568420FF36620071C985 /* SJBaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DEF568320FF36620071C985 /* SJBaseViewController.m */; }; 2DFBA9CD21217D6F00AB845B /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DFBA9C621217D6F00AB845B /* Reachability.m */; }; 2DFBA9CE21217D6F00AB845B /* SGNetObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DFBA9C821217D6F00AB845B /* SGNetObserver.m */; }; 2DFBA9CF21217D6F00AB845B /* SimplePing.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DFBA9CA21217D6F00AB845B /* SimplePing.m */; }; 2DFBA9D021217D6F00AB845B /* SimplePinger.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DFBA9CC21217D6F00AB845B /* SimplePinger.m */; }; 2DFC813A20E09D4500CCDAB7 /* yw_1222.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2DFC813920E09D4500CCDAB7 /* yw_1222.jpg */; }; AD52310E1F1B6A24007FCFA1 /* OrderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AD52310D1F1B6A24007FCFA1 /* OrderViewController.m */; }; /* End PBXBuildFile section */ @@ -1456,14 +1456,6 @@ 2D0E729520C0DAE600822DC8 /* SJButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SJButton.m; sourceTree = "<group>"; }; 2D0F7DB420D0F91600355B51 /* SJTransitionView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SJTransitionView.h; sourceTree = "<group>"; }; 2D0F7DB520D0F91600355B51 /* SJTransitionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SJTransitionView.m; sourceTree = "<group>"; }; 2D100B5B212159CF00109DAF /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = "<group>"; }; 2D100B5C212159CF00109DAF /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = "<group>"; }; 2D100B5D212159CF00109DAF /* SGNetObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGNetObserver.h; sourceTree = "<group>"; }; 2D100B5E212159CF00109DAF /* SGNetObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGNetObserver.m; sourceTree = "<group>"; }; 2D100B5F212159CF00109DAF /* SimplePing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimplePing.h; sourceTree = "<group>"; }; 2D100B60212159CF00109DAF /* SimplePing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimplePing.m; sourceTree = "<group>"; }; 2D100B61212159CF00109DAF /* SimplePinger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimplePinger.h; sourceTree = "<group>"; }; 2D100B62212159CF00109DAF /* SimplePinger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimplePinger.m; sourceTree = "<group>"; }; 2D10FAC12108613500C4C3E0 /* WXBindTipsView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXBindTipsView.h; sourceTree = "<group>"; }; 2D10FAC22108613500C4C3E0 /* WXBindTipsView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXBindTipsView.m; sourceTree = "<group>"; }; 2D1175AB21199F3F00D4CD0F /* ObtainProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObtainProperty.m; sourceTree = "<group>"; }; @@ -1544,6 +1536,14 @@ 2DEF568020FF20990071C985 /* SJTipView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SJTipView.m; sourceTree = "<group>"; }; 2DEF568220FF36620071C985 /* SJBaseViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SJBaseViewController.h; sourceTree = "<group>"; }; 2DEF568320FF36620071C985 /* SJBaseViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SJBaseViewController.m; sourceTree = "<group>"; }; 2DFBA9C521217D6F00AB845B /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = "<group>"; }; 2DFBA9C621217D6F00AB845B /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = "<group>"; }; 2DFBA9C721217D6F00AB845B /* SGNetObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGNetObserver.h; sourceTree = "<group>"; }; 2DFBA9C821217D6F00AB845B /* SGNetObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGNetObserver.m; sourceTree = "<group>"; }; 2DFBA9C921217D6F00AB845B /* SimplePing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimplePing.h; sourceTree = "<group>"; }; 2DFBA9CA21217D6F00AB845B /* SimplePing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimplePing.m; sourceTree = "<group>"; }; 2DFBA9CB21217D6F00AB845B /* SimplePinger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimplePinger.h; sourceTree = "<group>"; }; 2DFBA9CC21217D6F00AB845B /* SimplePinger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimplePinger.m; sourceTree = "<group>"; }; 2DFC813920E09D4500CCDAB7 /* yw_1222.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = yw_1222.jpg; sourceTree = "<group>"; }; A10E40577F379E83D85926C6 /* Pods_MIduo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MIduo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; AB238CE26A4E87752975FA82 /* Pods-MIduo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MIduo.release.xcconfig"; path = "Pods/Target Support Files/Pods-MIduo/Pods-MIduo.release.xcconfig"; sourceTree = "<group>"; }; @@ -3238,7 +3238,7 @@ 18AC538B1E5A9876006D1FDF /* lib */ = { isa = PBXGroup; children = ( 2D100B5A212159CF00109DAF /* SGNetObserver */, 2DFBA9C421217D6F00AB845B /* SGNetObserver */, 2D1175AA21199F2700D4CD0F /* FileManger */, 2D9F157B2117E8E800EFFAFB /* EasyJSWebView-master */, 1845C239209C562C009C639B /* LBXScan */, @@ -3454,22 +3454,6 @@ path = balance; sourceTree = "<group>"; }; 2D100B5A212159CF00109DAF /* SGNetObserver */ = { isa = PBXGroup; children = ( 2D100B5B212159CF00109DAF /* Reachability.h */, 2D100B5C212159CF00109DAF /* Reachability.m */, 2D100B5D212159CF00109DAF /* SGNetObserver.h */, 2D100B5E212159CF00109DAF /* SGNetObserver.m */, 2D100B5F212159CF00109DAF /* SimplePing.h */, 2D100B60212159CF00109DAF /* SimplePing.m */, 2D100B61212159CF00109DAF /* SimplePinger.h */, 2D100B62212159CF00109DAF /* SimplePinger.m */, ); name = SGNetObserver; path = "../../../../SGNetObserver-master/SGNetObserver"; sourceTree = "<group>"; }; 2D1175AA21199F2700D4CD0F /* FileManger */ = { isa = PBXGroup; children = ( @@ -3514,6 +3498,21 @@ 2D9F15862117E8E800EFFAFB /* test.html */, ); path = "EasyJSWebView-master"; sourceTree = "<group>"; }; 2DFBA9C421217D6F00AB845B /* SGNetObserver */ = { isa = PBXGroup; children = ( 2DFBA9C521217D6F00AB845B /* Reachability.h */, 2DFBA9C621217D6F00AB845B /* Reachability.m */, 2DFBA9C721217D6F00AB845B /* SGNetObserver.h */, 2DFBA9C821217D6F00AB845B /* SGNetObserver.m */, 2DFBA9C921217D6F00AB845B /* SimplePing.h */, 2DFBA9CA21217D6F00AB845B /* SimplePing.m */, 2DFBA9CB21217D6F00AB845B /* SimplePinger.h */, 2DFBA9CC21217D6F00AB845B /* SimplePinger.m */, ); path = SGNetObserver; sourceTree = "<group>"; }; 3EB2FCBC06FCFF59022C5ECD /* Frameworks */ = { @@ -3933,7 +3932,7 @@ 1845C450209C562D009C639B /* ZXAddressBookDoCoMoResultParser.m in Sources */, 1865E43C1EF1112A00333767 /* SectionTopicCollectionViewCell.m in Sources */, 1845C4C1209C562E009C639B /* ZXRSSExpandedDecodedNumeric.m in Sources */, 2D100B64212159D000109DAF /* SGNetObserver.m in Sources */, 2DFBA9CE21217D6F00AB845B /* SGNetObserver.m in Sources */, 181ECE271EF369BF00472224 /* ZJSegmentStyle.m in Sources */, 1892034720BE51C6008C1045 /* LBXZXCapture.m in Sources */, 1845C45A209C562D009C639B /* ZXGeoParsedResult.m in Sources */, @@ -3949,7 +3948,7 @@ 1897D9C01E600E94003DF6FE /* ClearCollectionReusableView.m in Sources */, 2D9F158A2117E8E800EFFAFB /* EasyJSWebViewProxyDelegate.m in Sources */, 1845C4BE209C562E009C639B /* ZXRSSExpandedCurrentParsingState.m in Sources */, 2D100B65212159D000109DAF /* SimplePing.m in Sources */, 2DFBA9CF21217D6F00AB845B /* SimplePing.m in Sources */, 187522901E654D6900B6AE15 /* SureWebViewController.m in Sources */, 18D399AD1EA765AD00A01CD3 /* thirdClassificationViewController.m in Sources */, 1845C514209C562E009C639B /* ZXQRCodeEncoder.m in Sources */, @@ -4002,7 +4001,7 @@ 182BEB601EAA081400B11FC5 /* LXAlertView.m in Sources */, 1810FBF91E7FBDBB005B42B3 /* NSString+Utils.m in Sources */, 1892034320BE51C6008C1045 /* LBXScanView.m in Sources */, 2D100B63212159D000109DAF /* Reachability.m in Sources */, 2DFBA9CD21217D6F00AB845B /* Reachability.m in Sources */, 2D43E74E211D92790008BA48 /* ALAnomalyNetWorkView.m in Sources */, 2D6858F420DB5D8B00E4376A /* SJCouponCollectionViewCell.m in Sources */, 1845C47D209C562D009C639B /* ZXBitMatrix.m in Sources */, @@ -4057,7 +4056,7 @@ 1896F26D1FD0ED96009D6EEF /* RecommendCouponViewController.m in Sources */, 18D9541A20AE705C005D5D02 /* FeignGoodsDetaiViewController.m in Sources */, 1845C4A1209C562E009C639B /* ZXDataMatrixDefaultPlacement.m in Sources */, 2D100B66212159D000109DAF /* SimplePinger.m in Sources */, 2DFBA9D021217D6F00AB845B /* SimplePinger.m in Sources */, 1845C4B2209C562E009C639B /* ZXAbstractExpandedDecoder.m in Sources */, 1845C4D6209C562E009C639B /* ZXEAN13Reader.m in Sources */, 1845C4B4209C562E009C639B /* ZXAI01320xDecoder.m in Sources */, MIduo.xcworkspace/xcuserdata/mj.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
@@ -103,7 +103,7 @@ endingColumnNumber = "9223372036854775807" startingLineNumber = "261" endingLineNumber = "261" landmarkName = "-dealloc" landmarkName = "-networkError:" landmarkType = "7"> </BreakpointContent> </BreakpointProxy> MIduo/Êý¾Ý/lib/SGNetObserver/Reachability.h
New file @@ -0,0 +1,68 @@ /* Copyright (C) 2016 Apple Inc. All Rights Reserved. See LICENSE.txt for this sampleâs licensing information Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. */ #import <Foundation/Foundation.h> #import <SystemConfiguration/SystemConfiguration.h> #import <netinet/in.h> typedef enum : NSInteger { NotReachable = 0, ReachableViaWiFi, ReachableViaWWAN } NetworkStatus; #pragma mark IPv6 Support //Reachability fully support IPv6. For full details, see ReadMe.md. @interface Reachability : NSObject /** * åè° */ @property (nonatomic,copy) void(^networkStatusDidChanged)(); /** * hostname */ @property (nonatomic,copy,readonly)NSString *hostName; /*! * Use to check the reachability of a given host name. */ + (instancetype)reachabilityWithHostName:(NSString *)hostName; /*! * Use to check the reachability of a given IP address. */ + (instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress; /*! * Checks whether the default route is available. Should be used by applications that do not connect to a particular host. */ + (instancetype)reachabilityForInternetConnection; #pragma mark reachabilityForLocalWiFi //reachabilityForLocalWiFi has been removed from the sample. See ReadMe.md for more information. //+ (instancetype)reachabilityForLocalWiFi; /*! * Start listening for reachability notifications on the current run loop. */ - (BOOL)startNotifier; - (void)stopNotifier; - (NetworkStatus)currentReachabilityStatus; /*! * WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand. */ - (BOOL)connectionRequired; @end MIduo/Êý¾Ý/lib/SGNetObserver/Reachability.m
New file @@ -0,0 +1,247 @@ /* Copyright (C) 2016 Apple Inc. All Rights Reserved. See LICENSE.txt for this sampleâs licensing information Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. */ #import <arpa/inet.h> #import <ifaddrs.h> #import <netdb.h> #import <sys/socket.h> #import <netinet/in.h> #import <CoreFoundation/CoreFoundation.h> #import "Reachability.h" #pragma mark IPv6 Support //Reachability fully support IPv6. For full details, see ReadMe.md. #pragma mark - Supporting functions #define kShouldPrintReachabilityFlags 1 static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment) { #if kShouldPrintReachabilityFlags NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n", (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', comment ); #endif } static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) { #pragma unused (target, flags) NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback"); Reachability *hostReachability = (__bridge Reachability *)info; if (hostReachability.networkStatusDidChanged) { hostReachability.networkStatusDidChanged(); } } #pragma mark - Reachability implementation @interface Reachability() @end @implementation Reachability { SCNetworkReachabilityRef _reachabilityRef; } + (instancetype)reachabilityWithHostName:(NSString *)hostName { Reachability* returnValue = NULL; SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); if (reachability != NULL) { returnValue= [[self alloc] init]; if (returnValue != NULL) { returnValue->_reachabilityRef = reachability; } else { CFRelease(reachability); } } returnValue->_hostName = hostName; return returnValue; } + (instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, hostAddress); Reachability* returnValue = NULL; if (reachability != NULL) { returnValue = [[self alloc] init]; if (returnValue != NULL) { returnValue->_reachabilityRef = reachability; } else { CFRelease(reachability); } } return returnValue; } + (instancetype)reachabilityForInternetConnection { struct sockaddr_in zeroAddress; bzero(&zeroAddress, sizeof(zeroAddress)); zeroAddress.sin_len = sizeof(zeroAddress); zeroAddress.sin_family = AF_INET; return [self reachabilityWithAddress: (const struct sockaddr *) &zeroAddress]; } #pragma mark reachabilityForLocalWiFi //reachabilityForLocalWiFi has been removed from the sample. See ReadMe.md for more information. //+ (instancetype)reachabilityForLocalWiFi #pragma mark - Start and stop notifier - (BOOL)startNotifier { BOOL returnValue = NO; SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL}; if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context)) { if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) { returnValue = YES; } } return returnValue; } - (void)stopNotifier { if (_reachabilityRef != NULL) { SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); } } - (void)dealloc { [self stopNotifier]; if (_reachabilityRef != NULL) { CFRelease(_reachabilityRef); } } #pragma mark - Network Flag Handling - (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags { PrintReachabilityFlags(flags, "networkStatusForFlags"); if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) { // The target host is not reachable. return NotReachable; } NetworkStatus returnValue = NotReachable; if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) { /* If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi... */ returnValue = ReachableViaWiFi; } if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) { /* ... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs... */ if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) { /* ... and no [user] intervention is needed... */ returnValue = ReachableViaWiFi; } } if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) { /* ... but WWAN connections are OK if the calling application is using the CFNetwork APIs. */ returnValue = ReachableViaWWAN; } return returnValue; } - (BOOL)connectionRequired { NSAssert(_reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef"); SCNetworkReachabilityFlags flags; if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags)) { return (flags & kSCNetworkReachabilityFlagsConnectionRequired); } return NO; } - (NetworkStatus)currentReachabilityStatus { NSAssert(_reachabilityRef != NULL, @"currentNetworkStatus called with NULL SCNetworkReachabilityRef"); NetworkStatus returnValue = NotReachable; SCNetworkReachabilityFlags flags; if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags)) { returnValue = [self networkStatusForFlags:flags]; } return returnValue; } @end MIduo/Êý¾Ý/lib/SGNetObserver/SGNetObserver.h
New file @@ -0,0 +1,84 @@ // // SGNetObserver.h // SGNetObserverDemo // // Created by apple on 16/9/19. // Copyright © 2016å¹´ iOSSinger. All rights reserved. // #import <UIKit/UIKit.h> /** * ç½ç»ç¶æååçå ¨å±éç¥ * info-keys: * @"status" ç½ç»ç¶æ,SGNetworkStatusç±»å * @"host" host å°å */ extern NSString *SGReachabilityChangedNotification; typedef NS_ENUM(NSUInteger, SGNetworkStatus) { SGNetworkStatusNone, SGNetworkStatus3G, SGNetworkStatus4G, SGNetworkStatusWifi, SGNetworkStatusUkonow }; @protocol SGNetworkStatusDelegate <NSObject> - (void)observer:(id)obsever host:(NSString *)host networkStatusDidChanged:(SGNetworkStatus)ststus; @end @interface SGNetObserver : NSObject /** * å½åç½ç»ç¶æ */ @property (nonatomic,assign) SGNetworkStatus networkStatus; /** * delegate,å¦æè®¾å®,åªèµ°ä»£ç,ä¸åå ¨å±éç¥.å¦ååªåå ¨å±éç¥ */ @property (nonatomic,weak) id <SGNetworkStatusDelegate> delegate; /** * æ¯å¦æ¯æIPv4,é»è®¤å ¨é¨æ¯æ */ @property (nonatomic,assign) BOOL supportIPv4; /** * æ¯å¦æ¯æIPv6 */ @property (nonatomic,assign) BOOL supportIPv6; /** * æå¾å°æ¦çping失败(å®é 没ææç½),设å®å¤å°æ¬¡pingå¤±è´¥è®¤ä¸ºæ¯æç½,é»è®¤2次 */ @property (nonatomic,assign) NSUInteger failureTimes; /** * ping çé¢ç,é»è®¤1s */ @property (nonatomic,assign) NSTimeInterval interval; /** * é»è®¤www.baidu.com */ + (instancetype)defultObsever; /** * èªå®ä¹å°å */ + (instancetype)observerWithHost:(NSString *)host; /** * å¼å§çæ§ */ - (void)startNotifier; /** * åæ¢çæ§ */ - (void)stopNotifier; @end MIduo/Êý¾Ý/lib/SGNetObserver/SGNetObserver.m
New file @@ -0,0 +1,183 @@ // // SGNetObserver.m // SGNetObserverDemo // // Created by apple on 16/9/19. // Copyright © 2016å¹´ iOSSinger. All rights reserved. // #import "SGNetObserver.h" #import "Reachability.h" #import "SimplePinger.h" NSString *SGReachabilityChangedNotification = @"SGNetworkReachabilityChangedNotification"; @interface SGNetObserver() @property (nonatomic,copy) NSString *host; @property (nonatomic,strong) Reachability *hostReachability; @property (nonatomic,strong) SimplePinger *pinger; @end @implementation SGNetObserver #pragma mark - åå§å + (instancetype)defultObsever{ SGNetObserver *obsever = [[self alloc] init]; obsever.host = @"www.baidu.com"; return obsever; } + (instancetype)observerWithHost:(NSString *)host{ SGNetObserver *obsever = [[self alloc] init]; obsever.host = host; return obsever; } - (instancetype)init{ if (self = [super init]) { _networkStatus = -1; _failureTimes = 2; _interval = 1.0; } return self; } - (void)dealloc{ [self.hostReachability stopNotifier]; [self.pinger stopNotifier]; } #pragma mark - function - (void)startNotifier{ [self.hostReachability startNotifier]; [self.pinger startNotifier]; } - (void)stopNotifier{ [self.hostReachability stopNotifier]; [self.pinger stopNotifier]; } #pragma mark - delegate - (void)networkStatusDidChanged{ //è·åä¸¤ç§æ¹æ³å¾å°çèç½ç¶æ,并转为BOOLå¼ BOOL status1 = [self.hostReachability currentReachabilityStatus]; BOOL status2 = self.pinger.reachable; //综å夿ç½ç»,夿åå:Reachability -> pinger if (status1 && status2) {//æç½ self.networkStatus = self.netWorkDetailStatus; }else{//æ ç½ self.networkStatus = SGNetworkStatusNone; } if (!status2 && status1) { [[NSNotificationCenter defaultCenter] postNotificationName:@"networkError" object:nil]; } } #pragma mark - setter - (void)setNetworkStatus:(SGNetworkStatus)networkStatus{ if (_networkStatus != networkStatus) { _networkStatus = networkStatus; NSLog(@"ç½ç»ç¶æ-----%@",self.networkDict[@(networkStatus)]); //æä»£ç if(self.delegate){//è°ç¨ä»£ç if ([self.delegate respondsToSelector:@selector(observer:host:networkStatusDidChanged:)]) { [self.delegate observer:self host:self.host networkStatusDidChanged:networkStatus]; } }else{//åéå ¨å±éç¥ NSDictionary *info = @{@"status" : @(networkStatus), @"host" : self.host }; [[NSNotificationCenter defaultCenter] postNotificationName:SGReachabilityChangedNotification object:nil userInfo:info]; } } } #pragma mark - getter - (Reachability *)hostReachability{ if (_hostReachability == nil) { _hostReachability = [Reachability reachabilityWithHostName:self.host]; __weak typeof(self) weakSelf = self; [_hostReachability setNetworkStatusDidChanged:^{ [weakSelf networkStatusDidChanged]; }]; } return _hostReachability; } - (SimplePinger *)pinger{ if (_pinger == nil) { _pinger = [SimplePinger simplePingerWithHostName:self.host]; _pinger.supportIPv4 = self.supportIPv4; _pinger.supportIPv6 = self.supportIPv6; _pinger.interval = self.interval; _pinger.failureTimes = self.failureTimes; __weak typeof(self) weakSelf = self; [_pinger setNetworkStatusDidChanged:^{ [weakSelf networkStatusDidChanged]; }]; } return _pinger; } #pragma mark - tools - (SGNetworkStatus)netWorkDetailStatus{ UIApplication *app = [UIApplication sharedApplication]; UIView *statusBar = [app valueForKeyPath:@"statusBar"]; UIView *foregroundView = [statusBar valueForKeyPath:@"foregroundView"]; UIView *networkView = nil; for (UIView *childView in foregroundView.subviews) { if ([childView isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) { networkView = childView; } } SGNetworkStatus status = SGNetworkStatusNone; if (networkView) { int netType = [[networkView valueForKeyPath:@"dataNetworkType"]intValue]; switch (netType) { case 0: status = SGNetworkStatusNone; break; case 1://å®é 䏿¯2G status = SGNetworkStatusUkonow; break; case 2: status = SGNetworkStatus3G; break; case 3: status = SGNetworkStatus4G; break; case 5: status = SGNetworkStatusWifi; break; default: status = SGNetworkStatusUkonow; break; } } return status; } - (NSDictionary *)networkDict{ return @{ @(SGNetworkStatusNone) : @"æ ç½ç»", @(SGNetworkStatusUkonow) : @"æªç¥ç½ç»", @(SGNetworkStatus3G) : @"3Gç½ç»", @(SGNetworkStatus4G) : @"4Gç½ç»", @(SGNetworkStatusWifi) : @"WIFIç½ç»", }; } @end MIduo/Êý¾Ý/lib/SGNetObserver/SimplePing.h
New file @@ -0,0 +1,272 @@ /* Copyright (C) 2016 Apple Inc. All Rights Reserved. See LICENSE.txt for this sampleâs licensing information Abstract: An object wrapper around the low-level BSD Sockets ping function. */ @import Foundation; #include <AssertMacros.h> // for __Check_Compile_Time NS_ASSUME_NONNULL_BEGIN @protocol SimplePingDelegate; /*! Controls the IP address version used by SimplePing instances. */ typedef NS_ENUM(NSInteger, SimplePingAddressStyle) { SimplePingAddressStyleAny, ///< Use the first IPv4 or IPv6 address found; the default. SimplePingAddressStyleICMPv4, ///< Use the first IPv4 address found. SimplePingAddressStyleICMPv6 ///< Use the first IPv6 address found. }; /*! An object wrapper around the low-level BSD Sockets ping function. * \details To use the class create an instance, set the delegate and call `-start` * to start the instance on the current run loop. If things go well you'll soon get the * `-simplePing:didStartWithAddress:` delegate callback. From there you can can call * `-sendPingWithData:` to send a ping and you'll receive the * `-simplePing:didReceivePingResponsePacket:sequenceNumber:` and * `-simplePing:didReceiveUnexpectedPacket:` delegate callbacks as ICMP packets arrive. * * The class can be used from any thread but the use of any single instance must be * confined to a specific thread and that thread must run its run loop. */ @interface SimplePing : NSObject - (instancetype)init NS_UNAVAILABLE; /*! Initialise the object to ping the specified host. * \param hostName The DNS name of the host to ping; an IPv4 or IPv6 address in string form will * work here. * \returns The initialised object. */ - (instancetype)initWithHostName:(NSString *)hostName NS_DESIGNATED_INITIALIZER; /*! A copy of the value passed to `-initWithHostName:`. */ @property (nonatomic, copy, readonly) NSString * hostName; /*! The delegate for this object. * \details Delegate callbacks are schedule in the default run loop mode of the run loop of the * thread that calls `-start`. */ @property (nonatomic, weak, readwrite, nullable) id<SimplePingDelegate> delegate; /*! Controls the IP address version used by the object. * \details You should set this value before starting the object. */ @property (nonatomic, assign, readwrite) SimplePingAddressStyle addressStyle; /*! The address being pinged. * \details The contents of the NSData is a (struct sockaddr) of some form. The * value is nil while the object is stopped and remains nil on start until * `-simplePing:didStartWithAddress:` is called. */ @property (nonatomic, copy, readonly, nullable) NSData * hostAddress; /*! The address family for `hostAddress`, or `AF_UNSPEC` if that's nil. */ @property (nonatomic, assign, readonly) sa_family_t hostAddressFamily; /*! The identifier used by pings by this object. * \details When you create an instance of this object it generates a random identifier * that it uses to identify its own pings. */ @property (nonatomic, assign, readonly) uint16_t identifier; /*! The next sequence number to be used by this object. * \details This value starts at zero and increments each time you send a ping (safely * wrapping back to zero if necessary). The sequence number is included in the ping, * allowing you to match up requests and responses, and thus calculate ping times and * so on. */ @property (nonatomic, assign, readonly) uint16_t nextSequenceNumber; /*! Starts the object. * \details You should set up the delegate and any ping parameters before calling this. * * If things go well you'll soon get the `-simplePing:didStartWithAddress:` delegate * callback, at which point you can start sending pings (via `-sendPingWithData:`) and * will start receiving ICMP packets (either ping responses, via the * `-simplePing:didReceivePingResponsePacket:sequenceNumber:` delegate callback, or * unsolicited ICMP packets, via the `-simplePing:didReceiveUnexpectedPacket:` delegate * callback). * * If the object fails to start, typically because `hostName` doesn't resolve, you'll get * the `-simplePing:didFailWithError:` delegate callback. * * It is not correct to start an already started object. */ - (void)start; /*! Sends a ping packet containing the specified data. * \details Sends an actual ping. * * The object must be started when you call this method and, on starting the object, you must * wait for the `-simplePing:didStartWithAddress:` delegate callback before calling it. * \param data Some data to include in the ping packet, after the ICMP header, or nil if you * want the packet to include a standard 56 byte payload (resulting in a standard 64 byte * ping). */ - (void)sendPingWithData:(nullable NSData *)data; /*! Stops the object. * \details You should call this when you're done pinging. * * It's safe to call this on an object that's stopped. */ - (void)stop; @end /*! A delegate protocol for the SimplePing class. */ @protocol SimplePingDelegate <NSObject> @optional /*! A SimplePing delegate callback, called once the object has started up. * \details This is called shortly after you start the object to tell you that the * object has successfully started. On receiving this callback, you can call * `-sendPingWithData:` to send pings. * * If the object didn't start, `-simplePing:didFailWithError:` is called instead. * \param pinger The object issuing the callback. * \param address The address that's being pinged; at the time this delegate callback * is made, this will have the same value as the `hostAddress` property. */ - (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address; /*! A SimplePing delegate callback, called if the object fails to start up. * \details This is called shortly after you start the object to tell you that the * object has failed to start. The most likely cause of failure is a problem * resolving `hostName`. * * By the time this callback is called, the object has stopped (that is, you don't * need to call `-stop` yourself). * \param pinger The object issuing the callback. * \param error Describes the failure. */ - (void)simplePing:(SimplePing *)pinger didFailWithError:(NSError *)error; /*! A SimplePing delegate callback, called when the object has successfully sent a ping packet. * \details Each call to `-sendPingWithData:` will result in either a * `-simplePing:didSendPacket:sequenceNumber:` delegate callback or a * `-simplePing:didFailToSendPacket:sequenceNumber:error:` delegate callback (unless you * stop the object before you get the callback). These callbacks are currently delivered * synchronously from within `-sendPingWithData:`, but this synchronous behaviour is not * considered API. * \param pinger The object issuing the callback. * \param packet The packet that was sent; this includes the ICMP header (`ICMPHeader`) and the * data you passed to `-sendPingWithData:` but does not include any IP-level headers. * \param sequenceNumber The ICMP sequence number of that packet. */ - (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber; /*! A SimplePing delegate callback, called when the object fails to send a ping packet. * \details Each call to `-sendPingWithData:` will result in either a * `-simplePing:didSendPacket:sequenceNumber:` delegate callback or a * `-simplePing:didFailToSendPacket:sequenceNumber:error:` delegate callback (unless you * stop the object before you get the callback). These callbacks are currently delivered * synchronously from within `-sendPingWithData:`, but this synchronous behaviour is not * considered API. * \param pinger The object issuing the callback. * \param packet The packet that was not sent; see `-simplePing:didSendPacket:sequenceNumber:` * for details. * \param sequenceNumber The ICMP sequence number of that packet. * \param error Describes the failure. */ - (void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber error:(NSError *)error; /*! A SimplePing delegate callback, called when the object receives a ping response. * \details If the object receives an ping response that matches a ping request that it * sent, it informs the delegate via this callback. Matching is primarily done based on * the ICMP identifier, although other criteria are used as well. * \param pinger The object issuing the callback. * \param packet The packet received; this includes the ICMP header (`ICMPHeader`) and any data that * follows that in the ICMP message but does not include any IP-level headers. * \param sequenceNumber The ICMP sequence number of that packet. */ - (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber; /*! A SimplePing delegate callback, called when the object receives an unmatched ICMP message. * \details If the object receives an ICMP message that does not match a ping request that it * sent, it informs the delegate via this callback. The nature of ICMP handling in a * BSD kernel makes this a common event because, when an ICMP message arrives, it is * delivered to all ICMP sockets. * * IMPORTANT: This callback is especially common when using IPv6 because IPv6 uses ICMP * for important network management functions. For example, IPv6 routers periodically * send out Router Advertisement (RA) packets via Neighbor Discovery Protocol (NDP), which * is implemented on top of ICMP. * * For more on matching, see the discussion associated with * `-simplePing:didReceivePingResponsePacket:sequenceNumber:`. * \param pinger The object issuing the callback. * \param packet The packet received; this includes the ICMP header (`ICMPHeader`) and any data that * follows that in the ICMP message but does not include any IP-level headers. */ - (void)simplePing:(SimplePing *)pinger didReceiveUnexpectedPacket:(NSData *)packet; @end #pragma mark * ICMP On-The-Wire Format /*! Describes the on-the-wire header format for an ICMP ping. * \details This defines the header structure of ping packets on the wire. Both IPv4 and * IPv6 use the same basic structure. * * This is declared in the header because clients of SimplePing might want to use * it parse received ping packets. */ struct ICMPHeader { uint8_t type; uint8_t code; uint16_t checksum; uint16_t identifier; uint16_t sequenceNumber; // data... }; typedef struct ICMPHeader ICMPHeader; __Check_Compile_Time(sizeof(ICMPHeader) == 8); __Check_Compile_Time(offsetof(ICMPHeader, type) == 0); __Check_Compile_Time(offsetof(ICMPHeader, code) == 1); __Check_Compile_Time(offsetof(ICMPHeader, checksum) == 2); __Check_Compile_Time(offsetof(ICMPHeader, identifier) == 4); __Check_Compile_Time(offsetof(ICMPHeader, sequenceNumber) == 6); enum { ICMPv4TypeEchoRequest = 8, ///< The ICMP `type` for a ping request; in this case `code` is always 0. ICMPv4TypeEchoReply = 0 ///< The ICMP `type` for a ping response; in this case `code` is always 0. }; enum { ICMPv6TypeEchoRequest = 128, ///< The ICMP `type` for a ping request; in this case `code` is always 0. ICMPv6TypeEchoReply = 129 ///< The ICMP `type` for a ping response; in this case `code` is always 0. }; NS_ASSUME_NONNULL_END MIduo/Êý¾Ý/lib/SGNetObserver/SimplePing.m
New file @@ -0,0 +1,785 @@ /* Copyright (C) 2016 Apple Inc. All Rights Reserved. See LICENSE.txt for this sampleâs licensing information Abstract: An object wrapper around the low-level BSD Sockets ping function. */ #import "SimplePing.h" #include <sys/socket.h> #include <netinet/in.h> #include <errno.h> #pragma mark * IPv4 and ICMPv4 On-The-Wire Format /*! Describes the on-the-wire header format for an IPv4 packet. * \details This defines the header structure of IPv4 packets on the wire. We need * this in order to skip this header in the IPv4 case, where the kernel passes * it to us for no obvious reason. */ struct IPv4Header { uint8_t versionAndHeaderLength; uint8_t differentiatedServices; uint16_t totalLength; uint16_t identification; uint16_t flagsAndFragmentOffset; uint8_t timeToLive; uint8_t protocol; uint16_t headerChecksum; uint8_t sourceAddress[4]; uint8_t destinationAddress[4]; // options... // data... }; typedef struct IPv4Header IPv4Header; __Check_Compile_Time(sizeof(IPv4Header) == 20); __Check_Compile_Time(offsetof(IPv4Header, versionAndHeaderLength) == 0); __Check_Compile_Time(offsetof(IPv4Header, differentiatedServices) == 1); __Check_Compile_Time(offsetof(IPv4Header, totalLength) == 2); __Check_Compile_Time(offsetof(IPv4Header, identification) == 4); __Check_Compile_Time(offsetof(IPv4Header, flagsAndFragmentOffset) == 6); __Check_Compile_Time(offsetof(IPv4Header, timeToLive) == 8); __Check_Compile_Time(offsetof(IPv4Header, protocol) == 9); __Check_Compile_Time(offsetof(IPv4Header, headerChecksum) == 10); __Check_Compile_Time(offsetof(IPv4Header, sourceAddress) == 12); __Check_Compile_Time(offsetof(IPv4Header, destinationAddress) == 16); /*! Calculates an IP checksum. * \details This is the standard BSD checksum code, modified to use modern types. * \param buffer A pointer to the data to checksum. * \param bufferLen The length of that data. * \returns The checksum value, in network byte order. */ static uint16_t in_cksum(const void *buffer, size_t bufferLen) { // size_t bytesLeft; int32_t sum; const uint16_t * cursor; union { uint16_t us; uint8_t uc[2]; } last; uint16_t answer; bytesLeft = bufferLen; sum = 0; cursor = buffer; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (bytesLeft > 1) { sum += *cursor; cursor += 1; bytesLeft -= 2; } /* mop up an odd byte, if necessary */ if (bytesLeft == 1) { last.uc[0] = * (const uint8_t *) cursor; last.uc[1] = 0; sum += last.us; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = (uint16_t) ~sum; /* truncate to 16 bits */ return answer; } #pragma mark * SimplePing @interface SimplePing () // read/write versions of public properties @property (nonatomic, copy, readwrite, nullable) NSData * hostAddress; @property (nonatomic, assign, readwrite ) uint16_t nextSequenceNumber; // private properties /*! True if nextSequenceNumber has wrapped from 65535 to 0. */ @property (nonatomic, assign, readwrite) BOOL nextSequenceNumberHasWrapped; /*! A host object for name-to-address resolution. */ @property (nonatomic, strong, readwrite, nullable) CFHostRef host __attribute__ ((NSObject)); /*! A socket object for ICMP send and receive. */ @property (nonatomic, strong, readwrite, nullable) CFSocketRef socket __attribute__ ((NSObject)); @end @implementation SimplePing - (instancetype)initWithHostName:(NSString *)hostName { NSParameterAssert(hostName != nil); self = [super init]; if (self != nil) { self->_hostName = [hostName copy]; self->_identifier = (uint16_t) arc4random(); } return self; } - (void)dealloc { [self stop]; // Double check that -stop took care of _host and _socket. assert(self->_host == NULL); assert(self->_socket == NULL); } - (sa_family_t)hostAddressFamily { sa_family_t result; result = AF_UNSPEC; if ( (self.hostAddress != nil) && (self.hostAddress.length >= sizeof(struct sockaddr)) ) { result = ((const struct sockaddr *) self.hostAddress.bytes)->sa_family; } return result; } /*! Shuts down the pinger object and tell the delegate about the error. * \param error Describes the failure. */ - (void)didFailWithError:(NSError *)error { id<SimplePingDelegate> strongDelegate; assert(error != nil); // We retain ourselves temporarily because it's common for the delegate method // to release its last reference to us, which causes -dealloc to be called here. // If we then reference self on the return path, things go badly. I don't think // that happens currently, but I've got into the habit of doing this as a // defensive measure. CFAutorelease( CFBridgingRetain( self )); [self stop]; strongDelegate = self.delegate; if ( (strongDelegate != nil) && [strongDelegate respondsToSelector:@selector(simplePing:didFailWithError:)] ) { [strongDelegate simplePing:self didFailWithError:error]; } } /*! Shuts down the pinger object and tell the delegate about the error. * \details This converts the CFStreamError to an NSError and then call through to * -didFailWithError: to do the real work. * \param streamError Describes the failure. */ - (void)didFailWithHostStreamError:(CFStreamError)streamError { NSDictionary * userInfo; NSError * error; if (streamError.domain == kCFStreamErrorDomainNetDB) { userInfo = @{(id) kCFGetAddrInfoFailureKey: @(streamError.error)}; } else { userInfo = nil; } error = [NSError errorWithDomain:(NSString *) kCFErrorDomainCFNetwork code:kCFHostErrorUnknown userInfo:userInfo]; [self didFailWithError:error]; } /*! Builds a ping packet from the supplied parameters. * \param type The packet type, which is different for IPv4 and IPv6. * \param payload Data to place after the ICMP header. * \param requiresChecksum Determines whether a checksum is calculated (IPv4) or not (IPv6). * \returns A ping packet suitable to be passed to the kernel. */ - (NSData *)pingPacketWithType:(uint8_t)type payload:(NSData *)payload requiresChecksum:(BOOL)requiresChecksum { NSMutableData * packet; ICMPHeader * icmpPtr; packet = [NSMutableData dataWithLength:sizeof(*icmpPtr) + payload.length]; assert(packet != nil); icmpPtr = packet.mutableBytes; icmpPtr->type = type; icmpPtr->code = 0; icmpPtr->checksum = 0; icmpPtr->identifier = OSSwapHostToBigInt16(self.identifier); icmpPtr->sequenceNumber = OSSwapHostToBigInt16(self.nextSequenceNumber); memcpy(&icmpPtr[1], [payload bytes], [payload length]); if (requiresChecksum) { // The IP checksum routine returns a 16-bit number that's already in correct byte order // (due to wacky 1's complement maths), so we just put it into the packet as a 16-bit unit. icmpPtr->checksum = in_cksum(packet.bytes, packet.length); } return packet; } - (void)sendPingWithData:(NSData *)data { int err; NSData * payload; NSData * packet; ssize_t bytesSent; id<SimplePingDelegate> strongDelegate; // data may be nil NSParameterAssert(self.hostAddress != nil); // gotta wait for -simplePing:didStartWithAddress: // Construct the ping packet. payload = data; if (payload == nil) { payload = [[NSString stringWithFormat:@"%28zd bottles of beer on the wall", (ssize_t) 99 - (size_t) (self.nextSequenceNumber % 100) ] dataUsingEncoding:NSASCIIStringEncoding]; assert(payload != nil); // Our dummy payload is sized so that the resulting ICMP packet, including the ICMPHeader, is // 64-bytes, which makes it easier to recognise our packets on the wire. assert([payload length] == 56); } switch (self.hostAddressFamily) { case AF_INET: { packet = [self pingPacketWithType:ICMPv4TypeEchoRequest payload:payload requiresChecksum:YES]; } break; case AF_INET6: { packet = [self pingPacketWithType:ICMPv6TypeEchoRequest payload:payload requiresChecksum:NO]; } break; default: { assert(NO); } break; } assert(packet != nil); // Send the packet. if (self.socket == NULL) { bytesSent = -1; err = EBADF; } else { bytesSent = sendto( CFSocketGetNative(self.socket), packet.bytes, packet.length, 0, self.hostAddress.bytes, (socklen_t) self.hostAddress.length ); err = 0; if (bytesSent < 0) { err = errno; } } // Handle the results of the send. strongDelegate = self.delegate; if ( (bytesSent > 0) && (((NSUInteger) bytesSent) == packet.length) ) { // Complete success. Tell the client. if ( (strongDelegate != nil) && [strongDelegate respondsToSelector:@selector(simplePing:didSendPacket:sequenceNumber:)] ) { [strongDelegate simplePing:self didSendPacket:packet sequenceNumber:self.nextSequenceNumber]; } } else { NSError * error; // Some sort of failure. Tell the client. if (err == 0) { err = ENOBUFS; // This is not a hugely descriptor error, alas. } static NSInteger number = 0; error = [NSError errorWithDomain:NSPOSIXErrorDomain code:err userInfo:nil]; if ( (strongDelegate != nil) && [strongDelegate respondsToSelector:@selector(simplePing:didFailToSendPacket:sequenceNumber:error:)] ) { number ++; [strongDelegate simplePing:self didFailToSendPacket:packet sequenceNumber:self.nextSequenceNumber error:error]; } } self.nextSequenceNumber += 1; if (self.nextSequenceNumber == 0) { self.nextSequenceNumberHasWrapped = YES; } } /*! Calculates the offset of the ICMP header within an IPv4 packet. * \details In the IPv4 case the kernel returns us a buffer that includes the * IPv4 header. We're not interested in that, so we have to skip over it. * This code does a rough check of the IPv4 header and, if it looks OK, * returns the offset of the ICMP header. * \param packet The IPv4 packet, as returned to us by the kernel. * \returns The offset of the ICMP header, or NSNotFound. */ + (NSUInteger)icmpHeaderOffsetInIPv4Packet:(NSData *)packet { // Returns the offset of the ICMPv4Header within an IP packet. NSUInteger result; const struct IPv4Header * ipPtr; size_t ipHeaderLength; result = NSNotFound; if (packet.length >= (sizeof(IPv4Header) + sizeof(ICMPHeader))) { ipPtr = (const IPv4Header *) packet.bytes; if ( ((ipPtr->versionAndHeaderLength & 0xF0) == 0x40) && // IPv4 ( ipPtr->protocol == IPPROTO_ICMP ) ) { ipHeaderLength = (ipPtr->versionAndHeaderLength & 0x0F) * sizeof(uint32_t); if (packet.length >= (ipHeaderLength + sizeof(ICMPHeader))) { result = ipHeaderLength; } } } return result; } /*! Checks whether the specified sequence number is one we sent. * \param sequenceNumber The incoming sequence number. * \returns YES if the sequence number looks like one we sent. */ - (BOOL)validateSequenceNumber:(uint16_t)sequenceNumber { if (self.nextSequenceNumberHasWrapped) { // If the sequence numbers have wrapped that we can't reliably check // whether this is a sequence number we sent. Rather, we check to see // whether the sequence number is within the last 120 sequence numbers // we sent. Note that the uint16_t subtraction here does the right // thing regardless of the wrapping. // // Why 120? Well, if we send one ping per second, 120 is 2 minutes, which // is the standard "max time a packet can bounce around the Internet" value. return ((uint16_t) (self.nextSequenceNumber - sequenceNumber)) < (uint16_t) 120; } else { return sequenceNumber < self.nextSequenceNumber; } } /*! Checks whether an incoming IPv4 packet looks like a ping response. * \details This routine modifies this `packet` data! It does this for two reasons: * * * It needs to zero out the `checksum` field of the ICMPHeader in order to do * its checksum calculation. * * * It removes the IPv4 header from the front of the packet. * \param packet The IPv4 packet, as returned to us by the kernel. * \param sequenceNumberPtr A pointer to a place to start the ICMP sequence number. * \returns YES if the packet looks like a reasonable IPv4 ping response. */ - (BOOL)validatePing4ResponsePacket:(NSMutableData *)packet sequenceNumber:(uint16_t *)sequenceNumberPtr { BOOL result; NSUInteger icmpHeaderOffset; ICMPHeader * icmpPtr; uint16_t receivedChecksum; uint16_t calculatedChecksum; result = NO; icmpHeaderOffset = [[self class] icmpHeaderOffsetInIPv4Packet:packet]; if (icmpHeaderOffset != NSNotFound) { icmpPtr = (struct ICMPHeader *) (((uint8_t *) packet.mutableBytes) + icmpHeaderOffset); receivedChecksum = icmpPtr->checksum; icmpPtr->checksum = 0; calculatedChecksum = in_cksum(icmpPtr, packet.length - icmpHeaderOffset); icmpPtr->checksum = receivedChecksum; if (receivedChecksum == calculatedChecksum) { if ( (icmpPtr->type == ICMPv4TypeEchoReply) && (icmpPtr->code == 0) ) { if ( OSSwapBigToHostInt16(icmpPtr->identifier) == self.identifier ) { uint16_t sequenceNumber; sequenceNumber = OSSwapBigToHostInt16(icmpPtr->sequenceNumber); if ([self validateSequenceNumber:sequenceNumber]) { // Remove the IPv4 header off the front of the data we received, leaving us with // just the ICMP header and the ping payload. [packet replaceBytesInRange:NSMakeRange(0, icmpHeaderOffset) withBytes:NULL length:0]; *sequenceNumberPtr = sequenceNumber; result = YES; } } } } } return result; } /*! Checks whether an incoming IPv6 packet looks like a ping response. * \param packet The IPv6 packet, as returned to us by the kernel; note that this routine * could modify this data but does not need to in the IPv6 case. * \param sequenceNumberPtr A pointer to a place to start the ICMP sequence number. * \returns YES if the packet looks like a reasonable IPv4 ping response. */ - (BOOL)validatePing6ResponsePacket:(NSMutableData *)packet sequenceNumber:(uint16_t *)sequenceNumberPtr { BOOL result; const ICMPHeader * icmpPtr; result = NO; if (packet.length >= sizeof(*icmpPtr)) { icmpPtr = packet.bytes; // In the IPv6 case we don't check the checksum because that's hard (we need to // cook up an IPv6 pseudo header and we don't have the ingredients) and unnecessary // (the kernel has already done this check). if ( (icmpPtr->type == ICMPv6TypeEchoReply) && (icmpPtr->code == 0) ) { if ( OSSwapBigToHostInt16(icmpPtr->identifier) == self.identifier ) { uint16_t sequenceNumber; sequenceNumber = OSSwapBigToHostInt16(icmpPtr->sequenceNumber); if ([self validateSequenceNumber:sequenceNumber]) { *sequenceNumberPtr = sequenceNumber; result = YES; } } } } return result; } /*! Checks whether an incoming packet looks like a ping response. * \param packet The packet, as returned to us by the kernel; note that may end up modifying * this data. * \param sequenceNumberPtr A pointer to a place to start the ICMP sequence number. * \returns YES if the packet looks like a reasonable IPv4 ping response. */ - (BOOL)validatePingResponsePacket:(NSMutableData *)packet sequenceNumber:(uint16_t *)sequenceNumberPtr { BOOL result; switch (self.hostAddressFamily) { case AF_INET: { result = [self validatePing4ResponsePacket:packet sequenceNumber:sequenceNumberPtr]; } break; case AF_INET6: { result = [self validatePing6ResponsePacket:packet sequenceNumber:sequenceNumberPtr]; } break; default: { assert(NO); result = NO; } break; } return result; } /*! Reads data from the ICMP socket. * \details Called by the socket handling code (SocketReadCallback) to process an ICMP * message waiting on the socket. */ - (void)readData { int err; struct sockaddr_storage addr; socklen_t addrLen; ssize_t bytesRead; void * buffer; enum { kBufferSize = 65535 }; // 65535 is the maximum IP packet size, which seems like a reasonable bound // here (plus it's what <x-man-page://8/ping> uses). buffer = malloc(kBufferSize); assert(buffer != NULL); // Actually read the data. We use recvfrom(), and thus get back the source address, // but we don't actually do anything with it. It would be trivial to pass it to // the delegate but we don't need it in this example. addrLen = sizeof(addr); bytesRead = recvfrom(CFSocketGetNative(self.socket), buffer, kBufferSize, 0, (struct sockaddr *) &addr, &addrLen); err = 0; if (bytesRead < 0) { err = errno; } // Process the data we read. if (bytesRead > 0) { NSMutableData * packet; id<SimplePingDelegate> strongDelegate; uint16_t sequenceNumber; packet = [NSMutableData dataWithBytes:buffer length:(NSUInteger) bytesRead]; assert(packet != nil); // We got some data, pass it up to our client. strongDelegate = self.delegate; if ( [self validatePingResponsePacket:packet sequenceNumber:&sequenceNumber] ) { if ( (strongDelegate != nil) && [strongDelegate respondsToSelector:@selector(simplePing:didReceivePingResponsePacket:sequenceNumber:)] ) { [strongDelegate simplePing:self didReceivePingResponsePacket:packet sequenceNumber:sequenceNumber]; } } else { if ( (strongDelegate != nil) && [strongDelegate respondsToSelector:@selector(simplePing:didReceiveUnexpectedPacket:)] ) { [strongDelegate simplePing:self didReceiveUnexpectedPacket:packet]; } } } else { // We failed to read the data, so shut everything down. if (err == 0) { err = EPIPE; } [self didFailWithError:[NSError errorWithDomain:NSPOSIXErrorDomain code:err userInfo:nil]]; } free(buffer); // Note that we don't loop back trying to read more data. Rather, we just // let CFSocket call us again. } /*! The callback for our CFSocket object. * \details This simply routes the call to our `-readData` method. * \param s See the documentation for CFSocketCallBack. * \param type See the documentation for CFSocketCallBack. * \param address See the documentation for CFSocketCallBack. * \param data See the documentation for CFSocketCallBack. * \param info See the documentation for CFSocketCallBack; this is actually a pointer to the * 'owning' object. */ static void SocketReadCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) { // This C routine is called by CFSocket when there's data waiting on our // ICMP socket. It just redirects the call to Objective-C code. SimplePing * obj; obj = (__bridge SimplePing *) info; assert([obj isKindOfClass:[SimplePing class]]); #pragma unused(s) assert(s == obj.socket); #pragma unused(type) assert(type == kCFSocketReadCallBack); #pragma unused(address) assert(address == nil); #pragma unused(data) assert(data == nil); [obj readData]; } /*! Starts the send and receive infrastructure. * \details This is called once we've successfully resolved `hostName` in to * `hostAddress`. It's responsible for setting up the socket for sending and * receiving pings. */ - (void)startWithHostAddress { int err; int fd; assert(self.hostAddress != nil); // Open the socket. fd = -1; err = 0; switch (self.hostAddressFamily) { case AF_INET: { fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); if (fd < 0) { err = errno; } } break; case AF_INET6: { fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); if (fd < 0) { err = errno; } } break; default: { err = EPROTONOSUPPORT; } break; } if (err != 0) { [self didFailWithError:[NSError errorWithDomain:NSPOSIXErrorDomain code:err userInfo:nil]]; } else { CFSocketContext context = {0, (__bridge void *)(self), NULL, NULL, NULL}; CFRunLoopSourceRef rls; id<SimplePingDelegate> strongDelegate; // Wrap it in a CFSocket and schedule it on the runloop. self.socket = (CFSocketRef) CFAutorelease( CFSocketCreateWithNative(NULL, fd, kCFSocketReadCallBack, SocketReadCallback, &context) ); assert(self.socket != NULL); // The socket will now take care of cleaning up our file descriptor. assert( CFSocketGetSocketFlags(self.socket) & kCFSocketCloseOnInvalidate ); fd = -1; rls = CFSocketCreateRunLoopSource(NULL, self.socket, 0); assert(rls != NULL); CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); CFRelease(rls); strongDelegate = self.delegate; if ( (strongDelegate != nil) && [strongDelegate respondsToSelector:@selector(simplePing:didStartWithAddress:)] ) { [strongDelegate simplePing:self didStartWithAddress:self.hostAddress]; } } assert(fd == -1); } /*! Processes the results of our name-to-address resolution. * \details Called by our CFHost resolution callback (HostResolveCallback) when host * resolution is complete. We just latch the first appropriate address and kick * off the send and receive infrastructure. */ - (void)hostResolutionDone { Boolean resolved; NSArray * addresses; // Find the first appropriate address. addresses = (__bridge NSArray *) CFHostGetAddressing(self.host, &resolved); if ( resolved && (addresses != nil) ) { resolved = false; for (NSData * address in addresses) { const struct sockaddr * addrPtr; addrPtr = (const struct sockaddr *) address.bytes; if ( address.length >= sizeof(struct sockaddr) ) { switch (addrPtr->sa_family) { case AF_INET: { if (self.addressStyle != SimplePingAddressStyleICMPv6) { self.hostAddress = address; resolved = true; } } break; case AF_INET6: { if (self.addressStyle != SimplePingAddressStyleICMPv4) { self.hostAddress = address; resolved = true; } } break; } } if (resolved) { break; } } } // We're done resolving, so shut that down. [self stopHostResolution]; // If all is OK, start the send and receive infrastructure, otherwise stop. if (resolved) { [self startWithHostAddress]; } else { [self didFailWithError:[NSError errorWithDomain:(NSString *)kCFErrorDomainCFNetwork code:kCFHostErrorHostNotFound userInfo:nil]]; } } /*! The callback for our CFHost object. * \details This simply routes the call to our `-hostResolutionDone` or * `-didFailWithHostStreamError:` methods. * \param theHost See the documentation for CFHostClientCallBack. * \param typeInfo See the documentation for CFHostClientCallBack. * \param error See the documentation for CFHostClientCallBack. * \param info See the documentation for CFHostClientCallBack; this is actually a pointer to * the 'owning' object. */ static void HostResolveCallback(CFHostRef theHost, CFHostInfoType typeInfo, const CFStreamError *error, void *info) { // This C routine is called by CFHost when the host resolution is complete. // It just redirects the call to the appropriate Objective-C method. SimplePing * obj; obj = (__bridge SimplePing *) info; assert([obj isKindOfClass:[SimplePing class]]); #pragma unused(theHost) assert(theHost == obj.host); #pragma unused(typeInfo) assert(typeInfo == kCFHostAddresses); if ( (error != NULL) && (error->domain != 0) ) { [obj didFailWithHostStreamError:*error]; } else { [obj hostResolutionDone]; } } - (void)start { Boolean success; CFHostClientContext context = {0, (__bridge void *)(self), NULL, NULL, NULL}; CFStreamError streamError; assert(self.host == NULL); assert(self.hostAddress == nil); self.host = (CFHostRef) CFAutorelease( CFHostCreateWithName(NULL, (__bridge CFStringRef) self.hostName) ); assert(self.host != NULL); CFHostSetClient(self.host, HostResolveCallback, &context); CFHostScheduleWithRunLoop(self.host, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); success = CFHostStartInfoResolution(self.host, kCFHostAddresses, &streamError); if ( ! success ) { [self didFailWithHostStreamError:streamError]; } } /*! Stops the name-to-address resolution infrastructure. */ - (void)stopHostResolution { // Shut down the CFHost. if (self.host != NULL) { CFHostSetClient(self.host, NULL, NULL); CFHostUnscheduleFromRunLoop(self.host, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); self.host = NULL; } } /*! Stops the send and receive infrastructure. */ - (void)stopSocket { if (self.socket != NULL) { CFSocketInvalidate(self.socket); self.socket = NULL; } } - (void)stop { [self stopHostResolution]; [self stopSocket]; // Junk the host address on stop. If the client calls -start again, we'll // re-resolve the host name. self.hostAddress = NULL; } @end MIduo/Êý¾Ý/lib/SGNetObserver/SimplePinger.h
New file @@ -0,0 +1,50 @@ // // SimpleHeartbeat.h // SGNetObserverDemo // // Created by apple on 16/9/20. // Copyright © 2016å¹´ iOSSinger. All rights reserved. // #import <Foundation/Foundation.h> #import "SimplePing.h" @interface SimplePinger : NSObject /** * æ¯å¦pingçé */ @property (nonatomic,assign) BOOL reachable; /** * æå¾å°æ¦çping失败,设å®å¤å°æ¬¡pingå¤±è´¥è®¤ä¸ºæ¯æç½,é»è®¤2次, å¿ é¡» >= 2 */ @property (nonatomic,assign) NSUInteger failureTimes; /** * ping çé¢ç,é»è®¤1s */ @property (nonatomic,assign) NSTimeInterval interval; /** * æ¯å¦æ¯æIPv4,é»è®¤å ¨é¨æ¯æ */ @property (nonatomic,assign) BOOL supportIPv4; /** * æ¯å¦æ¯æIPv6 */ @property (nonatomic,assign) BOOL supportIPv6; /** * åè° */ @property (nonatomic,copy) void(^networkStatusDidChanged)(); + (instancetype)simplePingerWithHostName:(NSString *)hostName; - (void)startNotifier; - (void)stopNotifier; @end MIduo/Êý¾Ý/lib/SGNetObserver/SimplePinger.m
New file @@ -0,0 +1,188 @@ // // SimpleHeartbeat.m // SGNetObserverDemo // // Created by apple on 16/9/20. // Copyright © 2016å¹´ iOSSinger. All rights reserved. // #import "SimplePinger.h" #import "SimplePing.h" #include <netdb.h> @interface SimplePinger()<SimplePingDelegate> @property (nonatomic,strong) SimplePing *pinger; @property (nonatomic,copy) NSString *hostName; @property (nonatomic,strong) NSTimer *sendTimer; /** * åé失败记å½,失败次æ°ä¸ºfailuretimesæ¶,认为æç½. */ @property (nonatomic,strong) NSMutableArray *array; @end @implementation SimplePinger #pragma mark - åå§å + (instancetype)simplePingerWithHostName:(NSString *)hostName{ SimplePinger *pinger = [[SimplePinger alloc] init]; pinger.hostName = hostName; return pinger; } - (instancetype)init{ if(self = [super init]){ self.interval = 1.0; self.failureTimes = 2; self.reachable = YES; } return self; } - (void)dealloc{ [self stopPing]; [self.array removeAllObjects]; [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(sendPing) object:nil]; } #pragma mark - function - (void)startNotifier{ [self startForceIPv4:self.supportIPv4 forceIPv6:self.supportIPv6]; } - (void)stopNotifier{ [self stopPing]; } - (void)startForceIPv4:(BOOL)forceIPv4 forceIPv6:(BOOL)forceIPv6{ self.pinger = [[SimplePing alloc] initWithHostName:self.hostName]; if (forceIPv4 && !forceIPv6) { self.pinger.addressStyle = SimplePingAddressStyleICMPv4; }else if (forceIPv6 && !forceIPv4){ self.pinger.addressStyle = SimplePingAddressStyleICMPv6; }else{ self.pinger.addressStyle = SimplePingAddressStyleAny; } self.pinger.delegate = self; [self.pinger start]; } - (void)sendPing{ static NSInteger number = 0; if (number < 3) { number ++; [self.pinger sendPingWithData:nil]; }else{ [_sendTimer invalidate]; _sendTimer = nil; } } - (void)stopPing{ [self.pinger stop]; self.pinger.delegate = nil; self.pinger = nil; [self.sendTimer invalidate]; self.sendTimer = nil; } #pragma mark - delegaet - (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address{ NSLog(@"didStartPingWithAddress: %@",[self addressWithData:address]); [self sendPing]; if (!_sendTimer) { _sendTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(sendPing) userInfo:nil repeats:YES]; } } //åéæå,sequenceNumberèå´:0~65535,è¶ èå´åä» 0 å¼å§ - (void)simplsentePing:(SimplePing *)pinger didSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber{ NSLog(@"#%u sent", sequenceNumber); if(sequenceNumber == 0){//éç½® [self.array removeAllObjects]; } //æ ¹æ®failuretimes夿æ¯å¦æç½ if (self.array.count >= self.failureTimes) { self.reachable = NO; [self.array removeAllObjects]; } //å°æ¬æ¬¡è®°å½å å ¥ [self.array addObject:@(sequenceNumber)]; } //åé失败 - (void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber error:(NSError *)error{ NSLog(@"#%u fail sent",sequenceNumber); //åé失败,ç´æ¥è®¤ä¸ºæç½ self.reachable = NO; [self.array removeAllObjects]; } //æ¥æ¶æå - (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber{ //æç½ self.reachable = YES; [self.array removeAllObjects]; } //æªç¥å¤±è´¥,éå¯ping - (void)simplePing:(SimplePing *)pinger didFailWithError:(NSError *)error{ self.reachable = NO; [self stopPing]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self startNotifier]; }); } //æ ¹æ®data,计ç®host - (NSString *)addressWithData:(NSData *)address{ char *hostStr = malloc(NI_MAXHOST); memset(hostStr, 0, NI_MAXHOST); BOOL success = getnameinfo((const struct sockaddr *)address.bytes, (socklen_t)address.length, hostStr, (socklen_t)NI_MAXHOST, nil, 0, NI_NUMERICHOST) == 0; NSString *result; if (success) { result = [NSString stringWithUTF8String:hostStr]; }else{ result = @"?"; } free(hostStr); return result; } #pragma mark - setter - (void)setReachable:(BOOL)reachable{ if (_reachable != reachable) { _reachable = reachable; if (self.networkStatusDidChanged) { self.networkStatusDidChanged(); } } } - (void)setFailureTimes:(NSUInteger)failureTimes{ if (failureTimes < 2) { failureTimes = 2; } _failureTimes = failureTimes; } - (NSMutableArray *)array{ if (_array == nil) { _array = [NSMutableArray array]; } return _array; } @end MIduo/½çÃæ/ÓÅ»Ýȯ/ÍÆ¼ö/RecommendCouponViewController.m
@@ -169,7 +169,7 @@ [[YTHNetInterface startInterface] getCouponListWithPage:[NSString stringWithFormat:@"%ld",(long)self.page] Withblock:^(BOOL isSuccessful, id result, NSString *error) { if (isSuccessful) { //self.adviceTableview.hidden = NO; self.adviceTableview.hidden = NO; NSDictionary *tempDic=(NSDictionary *)result; @@ -207,17 +207,26 @@ if (self.GoodsData.count != 0) { //self.adviceTableview.hidden = NO; self.adviceTableview.hidden = YES; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; } else { self.adviceTableview.hidden = NO; } } else { if (self.GoodsData.count != 0) { // self.adviceTableview.hidden = NO; self.adviceTableview.hidden = YES; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; } else { self.adviceTableview.hidden = NO; } } } @@ -455,7 +464,7 @@ // Fallback on earlier versions } // _adviceTableview.hidden = YES; _adviceTableview.hidden = YES; _adviceTableview.separatorStyle = UITableViewCellSeparatorStyleNone; return _adviceTableview; } MIduo/½çÃæ/ÎÒµÄ/LoginViewController.m
@@ -343,11 +343,13 @@ return ; } if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return ; } [YTHsharedManger startManger].isBound = NO; @@ -425,11 +427,13 @@ */ - (IBAction)clickAgreement:(id)sender { if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return ; } XYRWebViewController *aboutWebVC=[[XYRWebViewController alloc] init]; MIduo/½çÃæ/ÎÒµÄ/SJUnbindPhoneViewController.m
@@ -75,11 +75,13 @@ return; } if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return ; } NSMutableDictionary *dic = @{}.mutableCopy; MIduo/½çÃæ/ÎÒµÄ/balance/ÌåÏÖ/AddIncarnateViewController.m
@@ -12,6 +12,7 @@ @interface AddIncarnateViewController () @property (weak, nonatomic) IBOutlet UITextField *nameText; @property (weak, nonatomic) IBOutlet UITextField *zhifubaoText; @property (weak, nonatomic) IBOutlet UILabel *labelTips; @end MIduo/½çÃæ/ÎÒµÄ/balance/ÌåÏÖ/AddIncarnateViewController.xib
@@ -12,6 +12,7 @@ <objects> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="AddIncarnateViewController"> <connections> <outlet property="labelTips" destination="Mjp-Hv-7Kn" id="8Ag-SG-y6C"/> <outlet property="nameText" destination="2AH-UX-SdD" id="85m-8D-xRU"/> <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> <outlet property="zhifubaoText" destination="sXz-cR-dZt" id="MCT-y7-0eQ"/> @@ -22,8 +23,27 @@ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="2Pu-tB-RuN"> <rect key="frame" x="0.0" y="0.0" width="375" height="40"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="为确ä¿ä½ çèµéå®å ¨ï¼è¯·å确填åè´¦å·å¯¹åºä¿¡æ¯ï¼" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Mjp-Hv-7Kn"> <rect key="frame" x="15" y="0.0" width="360" height="40"/> <fontDescription key="fontDescription" type="system" pointSize="13"/> <color key="textColor" red="0.88235294117647056" green="0.47450980392156861" blue="0.47450980392156861" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> <color key="backgroundColor" red="1" green="0.99215686274509807" blue="0.88235294117647056" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstAttribute="height" constant="40" id="Jba-th-BfX"/> <constraint firstItem="Mjp-Hv-7Kn" firstAttribute="top" secondItem="2Pu-tB-RuN" secondAttribute="top" id="cdJ-j6-ufJ"/> <constraint firstAttribute="trailing" secondItem="Mjp-Hv-7Kn" secondAttribute="trailing" id="csy-sx-Wio"/> <constraint firstAttribute="bottom" secondItem="Mjp-Hv-7Kn" secondAttribute="bottom" id="j5F-ZI-JCk"/> <constraint firstItem="Mjp-Hv-7Kn" firstAttribute="leading" secondItem="2Pu-tB-RuN" secondAttribute="leading" constant="15" id="mIE-Vb-Pbe"/> </constraints> </view> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="W5U-xK-P7j"> <rect key="frame" x="0.0" y="10" width="375" height="160"/> <rect key="frame" x="0.0" y="50" width="375" height="160"/> <subviews> <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="æ¯ä»å®" translatesAutoresizingMaskIntoConstraints="NO" id="ARx-dm-zbb"> <rect key="frame" x="20" y="20" width="35" height="35"/> @@ -112,7 +132,7 @@ </constraints> </view> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JuN-HO-zP5"> <rect key="frame" x="94" y="200" width="187.5" height="34"/> <rect key="frame" x="94" y="240" width="187.5" height="34"/> <color key="backgroundColor" red="0.93333333333333335" green="0.26666666666666666" blue="0.27843137254901962" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstAttribute="height" constant="34" id="oyG-23-J3x"/> @@ -133,9 +153,12 @@ <constraints> <constraint firstItem="W5U-xK-P7j" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="7Ra-gr-YCo"/> <constraint firstItem="JuN-HO-zP5" firstAttribute="top" secondItem="W5U-xK-P7j" secondAttribute="bottom" constant="30" id="7lv-7o-qnT"/> <constraint firstItem="W5U-xK-P7j" firstAttribute="top" secondItem="2Pu-tB-RuN" secondAttribute="bottom" constant="10" id="ByE-2u-7dv"/> <constraint firstAttribute="trailing" secondItem="W5U-xK-P7j" secondAttribute="trailing" id="Ua1-GY-v7b"/> <constraint firstItem="2Pu-tB-RuN" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="Uu2-Tc-kZs"/> <constraint firstItem="JuN-HO-zP5" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="Wt6-GG-4LO"/> <constraint firstItem="W5U-xK-P7j" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="10" id="xsV-dF-e1N"/> <constraint firstItem="2Pu-tB-RuN" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="ehl-Dv-eZ9"/> <constraint firstAttribute="trailing" secondItem="2Pu-tB-RuN" secondAttribute="trailing" id="fNv-dq-C80"/> <constraint firstItem="JuN-HO-zP5" firstAttribute="width" secondItem="i5M-Pr-FkT" secondAttribute="width" multiplier="1:2" id="zNI-dX-jTv"/> </constraints> <point key="canvasLocation" x="33.5" y="53.5"/> MIduo/½çÃæ/ÎÒµÄ/balance/Ã÷ϸ/BalaDetailViewController.m
@@ -84,7 +84,8 @@ } }else{ [self autoDisappearAlertTime:0.5 msg:object[@"msg"]]; [CustomProgressHUD showNormal:object[@"msg"]]; } MIduo/½çÃæ/ÎÒµÄ/collection/MinCollectViewController.m
@@ -246,8 +246,8 @@ } [self.collectview.mj_header endRefreshing]; }else{ [self autoDisappearAlertTime:0.5 msg:object[@"msg"]]; [CustomProgressHUD showNormal:object[@"msg"]]; } } fail:^(id object) { MIduo/½çÃæ/ÎÒµÄ/message/MineMessageViewController.m
@@ -99,7 +99,7 @@ } NSLog(@"%@",self.datasource); }else{ [self autoDisappearAlertTime:0.5 msg:object[@"msg"]]; [CustomProgressHUD showNormal:object[@"msg"]]; } } fail:^(id object) { MIduo/½çÃæ/ÎÒµÄ/messageLogin/MessageLoginViewController.m
@@ -175,11 +175,13 @@ return; } if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return ; } if (self.passwordText.text.length != 6) { @@ -412,11 +414,13 @@ return; } if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return ; } [self.passwordText becomeFirstResponder ]; MIduo/½çÃæ/ÎÒµÄ/userInfoViewController.m
@@ -260,11 +260,13 @@ if (indexPath.section==1) { //ç¨æ·ç¹å»äºï¼å¯è½æ¯ç»å®ï¼å¯è½æ¯è§£ç»ï¼éè¦å¤æ if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return ; } if (indexPath.row==0) {//æ·å® @@ -315,11 +317,14 @@ } }else if(indexPath.row == 1){//微信 if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return ; } NSString *wxOpenId = [_userInfo objectForKey:@"wxOpenId"]; MIduo/½çÃæ/ÍøÒ³ÊÓͼ/OrderViewController.m
@@ -361,7 +361,8 @@ [self.orderTableView.mj_footer endRefreshingWithNoMoreData]; } }else{ [self autoDisappearAlertTime:0.5 msg:object[@"msg"]]; [CustomProgressHUD showNormal:object[@"msg"]]; } } fail:^(id object) { MIduo/½çÃæ/ÍøÒ³ÊÓͼ/ÉÌÆ·ÏêÇé/GoodDeTrViewController.m
@@ -183,11 +183,13 @@ */ - (void)fecthAndPostCollection { if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return ; } self.buttomView.collectButton.enabled = NO; @@ -543,10 +545,12 @@ if (self.recommendArray.count != 0) { if (error.code == -1009) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; }else{ [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; } } }]; @@ -556,11 +560,13 @@ - (void)useQuanClicked:(GoodsHeaderTableViewCell *)cell { if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return ; } if (![[NSUserDefaults standardUserDefaults] objectForKey:@"userId"]) { @@ -615,11 +621,13 @@ #pragma mark - ButtomCarViewDelegate - (void)shareClicked:(ButtomCarView *)view { if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return ; } if (![[NSUserDefaults standardUserDefaults] objectForKey:@"userId"]) { @@ -664,11 +672,13 @@ */ - (void)buyClicked:(ButtomCarView *)view { if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return ; } if (![[NSUserDefaults standardUserDefaults] objectForKey:@"userId"]) { MIduo/½çÃæ/ÑûÇë/ÉÌÆ··ÖÏí/ShonpingShareViewController.m
@@ -275,12 +275,16 @@ } if ( [urlString containsString:@"yeshitv://fanli_invite"]) { if ([YTHsharedManger startManger].networkStatus == 0) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»æªè¿æ¥ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return NO; } if ([YTHsharedManger startManger].isCheckNetCanUse == -2) { [self autoDisappearAlertTime:0.5 msg:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; [CustomProgressHUD showNormal:@"ç½ç»è¿æ¥å¼å¸¸ï¼è¯·æ£æµç½ç»è®¾ç½®"]; return NO; } InvitationFriendsViewController *invitaVC = [[InvitationFriendsViewController alloc]init]; MIduo/½çÃæ/Ê×Ò³/ListViewController.m
@@ -39,6 +39,9 @@ - (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter] removeObserver:self name:@"networkError" object:nil]; self.view.backgroundColor= YTHColor(239, 239, 239); _huojianW.constant=33*KScreenW/320; self.title = @"é¦é¡µ";