├── res └── readme.txt ├── .DS_Store ├── en.lproj ├── InfoPlist.strings ├── ConnectTestViewController.xib └── MainWindow.xib ├── Default-568h@2x.png ├── ConnectTest ├── ConnectTestViewController.m ├── ConnectTestViewController.h ├── main.m ├── ConnectTest-Prefix.pch ├── ITcpClient.h ├── ConnectTestAppDelegate.h ├── TcpClient.h ├── TestUI.h ├── ConnectTest-Info.plist ├── Reachability.h ├── TestUI.m ├── ConnectTestAppDelegate.m ├── TcpClient.m └── Reachability.m ├── ConnectTest.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── smalltask.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings ├── xcuserdata │ └── smalltask.xcuserdatad │ │ ├── xcschemes │ │ ├── xcschememanagement.plist │ │ └── ConnectTest.xcscheme │ │ └── xcdebugger │ │ └── Breakpoints.xcbkptlist └── project.pbxproj ├── Extensions ├── README.txt ├── ContextFilterLogFormatter.h ├── ContextFilterLogFormatter.m ├── DispatchQueueLogFormatter.h └── DispatchQueueLogFormatter.m ├── ConnectTest-Prefix.pch ├── README.md ├── ConnectTest-Info.plist ├── vendor ├── DDASLLogger.h ├── DDASLLogger.m ├── DDAbstractDatabaseLogger.h ├── DDTTYLogger.h ├── DDFileLogger.h ├── DDAbstractDatabaseLogger.m └── DDLog.h └── Documentation.html /res/readme.txt: -------------------------------------------------------------------------------- 1 | test. -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalltask/TestTcpConnection/HEAD/.DS_Store -------------------------------------------------------------------------------- /en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalltask/TestTcpConnection/HEAD/Default-568h@2x.png -------------------------------------------------------------------------------- /ConnectTest/ConnectTestViewController.m: -------------------------------------------------------------------------------- 1 | #import "ConnectTestViewController.h" 2 | 3 | 4 | @implementation ConnectTestViewController 5 | 6 | @synthesize label = _label; 7 | 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /ConnectTest/ConnectTestViewController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface ConnectTestViewController : UIViewController { 5 | 6 | } 7 | 8 | @property (nonatomic, strong) IBOutlet UILabel *label; 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /ConnectTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ConnectTest.xcodeproj/project.xcworkspace/xcuserdata/smalltask.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalltask/TestTcpConnection/HEAD/ConnectTest.xcodeproj/project.xcworkspace/xcuserdata/smalltask.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Extensions/README.txt: -------------------------------------------------------------------------------- 1 | This folder contains some sample formatters that may be helpful. 2 | 3 | Feel free to change them, extend them, or use them as the basis for your own custom formatter(s). 4 | 5 | More information about creating your own custom formatters can be found on the wiki: 6 | https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomFormatters 7 | 8 | -------------------------------------------------------------------------------- /ConnectTest/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ConnectTest 4 | // 5 | // Created by Robbie Hanson on 7/25/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | @autoreleasepool { 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | return retVal; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ConnectTest-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ConnectTest' target in the 'ConnectTest' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iPhone SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /ConnectTest/ConnectTest-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ConnectTest' target in the 'ConnectTest' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iPhone SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TestTcpConnection 2 | ================= 3 | 4 | Tcp connection test. 5 | 6 | Use GCDAsyncSocket framework. 7 | 8 | 基于GCDAsyncSocket项目进行实现; 9 | 10 | 增加了一个用户测试界面, 11 | 12 | 实现了手工收发消息的功能, 13 | 14 | 便于测试时使用; 15 | 16 | GCDAsyncSocket原先的Demo里,测试界面比较简单,用起来不方便。另外,如果测试过程中,忽然拔掉网线,socketConnection不能及时响应断网的状态,所以增加了Reachability类来判断网络状态的变更; 17 | 18 | 测试情况: 19 | Wifi,2g/3g网络,手机在不同类型网络之间切换,客户端忽然拔掉网线,服务器端忽然中断,均可以正确响应; 20 | 21 | -------------------------------------------------------------------------------- /ConnectTest/ITcpClient.h: -------------------------------------------------------------------------------- 1 | // 2 | // ITcpClient.h 3 | // ConnectTest 4 | // 5 | // Created by SmallTask on 13-8-22. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @protocol ITcpClient 12 | 13 | #pragma mark ITcpClient 14 | 15 | /**发送到服务器端的数据*/ 16 | -(void)OnSendDataSuccess:(NSString*)sendedTxt; 17 | 18 | /**收到服务器端发送的数据*/ 19 | -(void)OnReciveData:(NSString*)recivedTxt; 20 | 21 | /**socket连接出现错误*/ 22 | -(void)OnConnectionError:(NSError *)err; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ConnectTest/ConnectTestAppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "TestUI.h" 3 | #import "TcpClient.h" 4 | 5 | @class ConnectTestViewController; 6 | @class GCDAsyncSocket; 7 | 8 | 9 | @interface ConnectTestAppDelegate : NSObject 10 | { 11 | GCDAsyncSocket *asyncSocket; 12 | } 13 | 14 | @property(nonatomic,retain) TcpClient *tcpClient; 15 | 16 | @property (nonatomic, strong) IBOutlet UIWindow *window; 17 | @property (nonatomic, strong) IBOutlet ConnectTestViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ConnectTest.xcodeproj/xcuserdata/smalltask.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ConnectTest.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | DCDE285713DDEC74006BFCC0 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ConnectTest.xcodeproj/project.xcworkspace/xcuserdata/smalltask.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | IssueFilterStyle 12 | ShowActiveSchemeOnly 13 | LiveSourceIssuesEnabled 14 | 15 | SnapshotAutomaticallyBeforeSignificantChanges 16 | 17 | SnapshotLocationStyle 18 | Default 19 | 20 | 21 | -------------------------------------------------------------------------------- /ConnectTest/TcpClient.h: -------------------------------------------------------------------------------- 1 | // 2 | // TcpClient.h 3 | // ConnectTest 4 | // 5 | // Created by SmallTask on 13-8-15. 6 | // 7 | // 8 | 9 | #import 10 | #import "GCDAsyncSocket.h" 11 | #import "ITcpClient.h" 12 | 13 | @interface TcpClient : NSObject 14 | { 15 | long TAG_SEND; 16 | long TAG_RECIVED; 17 | 18 | id itcpClient; 19 | 20 | NSMutableArray *recivedArray; 21 | } 22 | 23 | @property (nonatomic,retain) GCDAsyncSocket *asyncSocket; 24 | 25 | 26 | + (TcpClient *)sharedInstance; 27 | 28 | -(void)setDelegate_ITcpClient:(id)_itcpClient; 29 | 30 | -(void)openTcpConnection:(NSString*)host port:(NSInteger)port; 31 | 32 | -(void)read:(NSInteger)tag; 33 | 34 | -(void)writeString:(NSString*)datastr; 35 | 36 | -(void)writeData:(NSData*)data; 37 | 38 | -(long)GetSendTag; 39 | 40 | -(long)GetRecivedTag; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /ConnectTest/TestUI.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestUI.h 3 | // ConnectTest 4 | // 5 | // Created by SmallTask on 13-8-15. 6 | // 7 | // 8 | 9 | #import 10 | #import "TcpClient.h" 11 | #import "ITcpClient.h" 12 | #import "Reachability.h" 13 | 14 | 15 | @interface TestUI : UIViewController 16 | 17 | 18 | 19 | @property (weak, nonatomic) IBOutlet UIScrollView *scrollview; 20 | @property (weak, nonatomic) IBOutlet UITextField *tfAddress; 21 | @property (weak, nonatomic) IBOutlet UITextField *tfPort; 22 | @property (weak, nonatomic) IBOutlet UIButton *btConnect; 23 | @property (weak, nonatomic) IBOutlet UILabel *lbConnectionResult; 24 | 25 | @property (weak, nonatomic) IBOutlet UITextField *tftxt; 26 | @property (weak, nonatomic) IBOutlet UIButton *btSend; 27 | 28 | @property (weak, nonatomic) IBOutlet UITextView *tfRecived; 29 | 30 | 31 | - (IBAction)onBtConnection:(id)sender; 32 | 33 | - (IBAction)onbtClicked:(id)sender; 34 | 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ConnectTest-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.zhytest.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | LSRequiresIPhoneOS 28 | 29 | NSMainNibFile 30 | MainWindow 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /vendor/DDASLLogger.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import "DDLog.h" 5 | 6 | /** 7 | * Welcome to Cocoa Lumberjack! 8 | * 9 | * The project page has a wealth of documentation if you have any questions. 10 | * https://github.com/robbiehanson/CocoaLumberjack 11 | * 12 | * If you're new to the project you may wish to read the "Getting Started" wiki. 13 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 14 | * 15 | * 16 | * This class provides a logger for the Apple System Log facility. 17 | * 18 | * As described in the "Getting Started" page, 19 | * the traditional NSLog() function directs it's output to two places: 20 | * 21 | * - Apple System Log 22 | * - StdErr (if stderr is a TTY) so log statements show up in Xcode console 23 | * 24 | * To duplicate NSLog() functionality you can simply add this logger and a tty logger. 25 | * However, if you instead choose to use file logging (for faster performance), 26 | * you may choose to use a file logger and a tty logger. 27 | **/ 28 | 29 | @interface DDASLLogger : DDAbstractLogger 30 | { 31 | aslclient client; 32 | } 33 | 34 | + (DDASLLogger *)sharedInstance; 35 | 36 | // Inherited from DDAbstractLogger 37 | 38 | // - (id )logFormatter; 39 | // - (void)setLogFormatter:(id )formatter; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /ConnectTest/ConnectTest-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.zhytest.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | LSRequiresIPhoneOS 28 | 29 | NSMainNibFile 30 | MainWindow 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Documentation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Welcome to the CocoaAsyncSocket project!

5 | 6 |

7 | A wealth of documentation can be found on the Google Code homepage:
8 | https://github.com/robbiehanson/CocoaAsyncSocket 9 |

10 | 11 |

12 | If you are new to networking, it is recommended you start by reading the Intro page:
13 | https://github.com/robbiehanson/CocoaAsyncSocket/wiki/Intro 14 |

15 | 16 |

17 | If you are a seasoned networking professional, with 10+ years of experience writing low-level socket code, 18 | and detailed knowledge of the underlying BSD networking stack, then you can skip the CommonPitfalls page.
19 | Otherwise, it should be considered mandatory reading:
20 | https://github.com/robbiehanson/CocoaAsyncSocket/wiki/CommonPitfalls 21 |

22 | 23 |

24 | A little bit of investment in your knowledge and understanding of networking fundamentals can go a long way.
25 | And it can save you a LOT of time and frustration in the long run. 26 |

27 | 28 |

29 | Your first goto for reference should ALWAYS be the header files. They are extremely well documented. Please read them. 30 |

31 | 32 |

33 | Did I mention you should read the headers? They're docemented very nicely, in plain english. 34 |

35 | 36 |

37 | If you have any questions you are welcome to post to the CocoaAsyncSocket mailing list:
38 | http://groups.google.com/group/cocoaasyncsocket
39 |
40 | The list is archived, and available for browsing online.
41 | You may be able to instantly find the answer you're looking for with a quick search.
42 |

43 | 44 |

We hope the CocoaAsyncSocket project can provide you with powerful and easy to use networking libraries.

45 | 46 | 47 | -------------------------------------------------------------------------------- /Extensions/ContextFilterLogFormatter.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "DDLog.h" 3 | 4 | @class ContextFilterLogFormatter; 5 | 6 | /** 7 | * Welcome to Cocoa Lumberjack! 8 | * 9 | * The project page has a wealth of documentation if you have any questions. 10 | * https://github.com/robbiehanson/CocoaLumberjack 11 | * 12 | * If you're new to the project you may wish to read the "Getting Started" page. 13 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 14 | * 15 | * 16 | * This class provides a log formatter that filters log statements from a logging context not on the whitelist. 17 | * 18 | * A log formatter can be added to any logger to format and/or filter its output. 19 | * You can learn more about log formatters here: 20 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomFormatters 21 | * 22 | * You can learn more about logging context's here: 23 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomContext 24 | * 25 | * But here's a quick overview / refresher: 26 | * 27 | * Every log statement has a logging context. 28 | * These come from the underlying logging macros defined in DDLog.h. 29 | * The default logging context is zero. 30 | * You can define multiple logging context's for use in your application. 31 | * For example, logically separate parts of your app each have a different logging context. 32 | * Also 3rd party frameworks that make use of Lumberjack generally use their own dedicated logging context. 33 | **/ 34 | @interface ContextWhitelistFilterLogFormatter : NSObject 35 | 36 | - (id)init; 37 | 38 | - (void)addToWhitelist:(int)loggingContext; 39 | - (void)removeFromWhitelist:(int)loggingContext; 40 | 41 | - (NSArray *)whitelist; 42 | 43 | - (BOOL)isOnWhitelist:(int)loggingContext; 44 | 45 | @end 46 | 47 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | #pragma mark - 49 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 50 | 51 | /** 52 | * This class provides a log formatter that filters log statements from a logging context on the blacklist. 53 | **/ 54 | @interface ContextBlacklistFilterLogFormatter : NSObject 55 | 56 | - (id)init; 57 | 58 | - (void)addToBlacklist:(int)loggingContext; 59 | - (void)removeFromBlacklist:(int)loggingContext; 60 | 61 | - (NSArray *)blacklist; 62 | 63 | - (BOOL)isOnBlacklist:(int)loggingContext; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /vendor/DDASLLogger.m: -------------------------------------------------------------------------------- 1 | #import "DDASLLogger.h" 2 | 3 | #import 4 | 5 | /** 6 | * Welcome to Cocoa Lumberjack! 7 | * 8 | * The project page has a wealth of documentation if you have any questions. 9 | * https://github.com/robbiehanson/CocoaLumberjack 10 | * 11 | * If you're new to the project you may wish to read the "Getting Started" wiki. 12 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 13 | **/ 14 | 15 | #if ! __has_feature(objc_arc) 16 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 17 | #endif 18 | 19 | 20 | @implementation DDASLLogger 21 | 22 | static DDASLLogger *sharedInstance; 23 | 24 | /** 25 | * The runtime sends initialize to each class in a program exactly one time just before the class, 26 | * or any class that inherits from it, is sent its first message from within the program. (Thus the 27 | * method may never be invoked if the class is not used.) The runtime sends the initialize message to 28 | * classes in a thread-safe manner. Superclasses receive this message before their subclasses. 29 | * 30 | * This method may also be called directly (assumably by accident), hence the safety mechanism. 31 | **/ 32 | + (void)initialize 33 | { 34 | static BOOL initialized = NO; 35 | if (!initialized) 36 | { 37 | initialized = YES; 38 | 39 | sharedInstance = [[DDASLLogger alloc] init]; 40 | } 41 | } 42 | 43 | + (DDASLLogger *)sharedInstance 44 | { 45 | return sharedInstance; 46 | } 47 | 48 | - (id)init 49 | { 50 | if (sharedInstance != nil) 51 | { 52 | return nil; 53 | } 54 | 55 | if ((self = [super init])) 56 | { 57 | // A default asl client is provided for the main thread, 58 | // but background threads need to create their own client. 59 | 60 | client = asl_open(NULL, "com.apple.console", 0); 61 | } 62 | return self; 63 | } 64 | 65 | - (void)logMessage:(DDLogMessage *)logMessage 66 | { 67 | NSString *logMsg = logMessage->logMsg; 68 | 69 | if (formatter) 70 | { 71 | logMsg = [formatter formatLogMessage:logMessage]; 72 | } 73 | 74 | if (logMsg) 75 | { 76 | const char *msg = [logMsg UTF8String]; 77 | 78 | int aslLogLevel; 79 | switch (logMessage->logLevel) 80 | { 81 | // Note: By default ASL will filter anything above level 5 (Notice). 82 | // So our mappings shouldn't go above that level. 83 | 84 | case 1 : aslLogLevel = ASL_LEVEL_CRIT; break; 85 | case 2 : aslLogLevel = ASL_LEVEL_ERR; break; 86 | case 3 : aslLogLevel = ASL_LEVEL_WARNING; break; 87 | default : aslLogLevel = ASL_LEVEL_NOTICE; break; 88 | } 89 | 90 | asl_log(client, NULL, aslLogLevel, "%s", msg); 91 | } 92 | } 93 | 94 | - (NSString *)loggerName 95 | { 96 | return @"cocoa.lumberjack.aslLogger"; 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /ConnectTest.xcodeproj/xcuserdata/smalltask.xcuserdatad/xcschemes/ConnectTest.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /ConnectTest/Reachability.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011, Tony Million. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import 29 | #import 30 | 31 | #import 32 | #import 33 | #import 34 | #import 35 | #import 36 | #import 37 | 38 | /** 39 | * Does ARC support GCD objects? 40 | * It does if the minimum deployment target is iOS 6+ or Mac OS X 8+ 41 | * 42 | * @see http://opensource.apple.com/source/libdispatch/libdispatch-228.18/os/object.h 43 | **/ 44 | #if OS_OBJECT_USE_OBJC 45 | #define NEEDS_DISPATCH_RETAIN_RELEASE 0 46 | #else 47 | #define NEEDS_DISPATCH_RETAIN_RELEASE 1 48 | #endif 49 | 50 | /** 51 | * Create NS_ENUM macro if it does not exist on the targeted version of iOS or OS X. 52 | * 53 | * @see http://nshipster.com/ns_enum-ns_options/ 54 | **/ 55 | #ifndef NS_ENUM 56 | #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type 57 | #endif 58 | 59 | extern NSString *const kReachabilityChangedNotification; 60 | 61 | typedef NS_ENUM(NSInteger, NetworkStatus) { 62 | // Apple NetworkStatus Compatible Names. 63 | NotReachable = 0, 64 | ReachableViaWiFi = 2, 65 | ReachableViaWWAN = 1 66 | }; 67 | 68 | @class Reachability; 69 | 70 | typedef void (^NetworkReachable)(Reachability * reachability); 71 | typedef void (^NetworkUnreachable)(Reachability * reachability); 72 | 73 | @interface Reachability : NSObject 74 | 75 | @property (nonatomic, copy) NetworkReachable reachableBlock; 76 | @property (nonatomic, copy) NetworkUnreachable unreachableBlock; 77 | 78 | 79 | @property (nonatomic, assign) BOOL reachableOnWWAN; 80 | 81 | +(Reachability*)reachabilityWithHostname:(NSString*)hostname; 82 | +(Reachability*)reachabilityForInternetConnection; 83 | +(Reachability*)reachabilityWithAddress:(const struct sockaddr_in*)hostAddress; 84 | +(Reachability*)reachabilityForLocalWiFi; 85 | 86 | -(Reachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref; 87 | 88 | -(BOOL)startNotifier; 89 | -(void)stopNotifier; 90 | 91 | -(BOOL)isReachable; 92 | -(BOOL)isReachableViaWWAN; 93 | -(BOOL)isReachableViaWiFi; 94 | 95 | // WWAN may be available, but not active until a connection has been established. 96 | // WiFi may require a connection for VPN on Demand. 97 | -(BOOL)isConnectionRequired; // Identical DDG variant. 98 | -(BOOL)connectionRequired; // Apple's routine. 99 | // Dynamic, on demand connection? 100 | -(BOOL)isConnectionOnDemand; 101 | // Is user intervention required? 102 | -(BOOL)isInterventionRequired; 103 | 104 | -(NetworkStatus)currentReachabilityStatus; 105 | -(SCNetworkReachabilityFlags)reachabilityFlags; 106 | -(NSString*)currentReachabilityString; 107 | -(NSString*)currentReachabilityFlags; 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /vendor/DDAbstractDatabaseLogger.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "DDLog.h" 4 | 5 | /** 6 | * Welcome to Cocoa Lumberjack! 7 | * 8 | * The project page has a wealth of documentation if you have any questions. 9 | * https://github.com/robbiehanson/CocoaLumberjack 10 | * 11 | * If you're new to the project you may wish to read the "Getting Started" wiki. 12 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 13 | * 14 | * 15 | * This class provides an abstract implementation of a database logger. 16 | * 17 | * That is, it provides the base implementation for a database logger to build atop of. 18 | * All that is needed for a concrete database logger is to extend this class 19 | * and override the methods in the implementation file that are prefixed with "db_". 20 | **/ 21 | 22 | @interface DDAbstractDatabaseLogger : DDAbstractLogger { 23 | @protected 24 | NSUInteger saveThreshold; 25 | NSTimeInterval saveInterval; 26 | NSTimeInterval maxAge; 27 | NSTimeInterval deleteInterval; 28 | BOOL deleteOnEverySave; 29 | 30 | BOOL saveTimerSuspended; 31 | NSUInteger unsavedCount; 32 | dispatch_time_t unsavedTime; 33 | dispatch_source_t saveTimer; 34 | dispatch_time_t lastDeleteTime; 35 | dispatch_source_t deleteTimer; 36 | } 37 | 38 | /** 39 | * Specifies how often to save the data to disk. 40 | * Since saving is an expensive operation (disk io) it is not done after every log statement. 41 | * These properties allow you to configure how/when the logger saves to disk. 42 | * 43 | * A save is done when either (whichever happens first): 44 | * 45 | * - The number of unsaved log entries reaches saveThreshold 46 | * - The amount of time since the oldest unsaved log entry was created reaches saveInterval 47 | * 48 | * You can optionally disable the saveThreshold by setting it to zero. 49 | * If you disable the saveThreshold you are entirely dependent on the saveInterval. 50 | * 51 | * You can optionally disable the saveInterval by setting it to zero (or a negative value). 52 | * If you disable the saveInterval you are entirely dependent on the saveThreshold. 53 | * 54 | * It's not wise to disable both saveThreshold and saveInterval. 55 | * 56 | * The default saveThreshold is 500. 57 | * The default saveInterval is 60 seconds. 58 | **/ 59 | @property (assign, readwrite) NSUInteger saveThreshold; 60 | @property (assign, readwrite) NSTimeInterval saveInterval; 61 | 62 | /** 63 | * It is likely you don't want the log entries to persist forever. 64 | * Doing so would allow the database to grow infinitely large over time. 65 | * 66 | * The maxAge property provides a way to specify how old a log statement can get 67 | * before it should get deleted from the database. 68 | * 69 | * The deleteInterval specifies how often to sweep for old log entries. 70 | * Since deleting is an expensive operation (disk io) is is done on a fixed interval. 71 | * 72 | * An alternative to the deleteInterval is the deleteOnEverySave option. 73 | * This specifies that old log entries should be deleted during every save operation. 74 | * 75 | * You can optionally disable the maxAge by setting it to zero (or a negative value). 76 | * If you disable the maxAge then old log statements are not deleted. 77 | * 78 | * You can optionally disable the deleteInterval by setting it to zero (or a negative value). 79 | * 80 | * If you disable both deleteInterval and deleteOnEverySave then old log statements are not deleted. 81 | * 82 | * It's not wise to enable both deleteInterval and deleteOnEverySave. 83 | * 84 | * The default maxAge is 7 days. 85 | * The default deleteInterval is 5 minutes. 86 | * The default deleteOnEverySave is NO. 87 | **/ 88 | @property (assign, readwrite) NSTimeInterval maxAge; 89 | @property (assign, readwrite) NSTimeInterval deleteInterval; 90 | @property (assign, readwrite) BOOL deleteOnEverySave; 91 | 92 | /** 93 | * Forces a save of any pending log entries (flushes log entries to disk). 94 | **/ 95 | - (void)savePendingLogEntries; 96 | 97 | /** 98 | * Removes any log entries that are older than maxAge. 99 | **/ 100 | - (void)deleteOldLogEntries; 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /Extensions/ContextFilterLogFormatter.m: -------------------------------------------------------------------------------- 1 | #import "ContextFilterLogFormatter.h" 2 | #import 3 | 4 | /** 5 | * Welcome to Cocoa Lumberjack! 6 | * 7 | * The project page has a wealth of documentation if you have any questions. 8 | * https://github.com/robbiehanson/CocoaLumberjack 9 | * 10 | * If you're new to the project you may wish to read the "Getting Started" wiki. 11 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 12 | **/ 13 | 14 | #if ! __has_feature(objc_arc) 15 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 16 | #endif 17 | 18 | @interface LoggingContextSet : NSObject 19 | 20 | - (void)addToSet:(int)loggingContext; 21 | - (void)removeFromSet:(int)loggingContext; 22 | 23 | - (NSArray *)currentSet; 24 | 25 | - (BOOL)isInSet:(int)loggingContext; 26 | 27 | @end 28 | 29 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | #pragma mark - 31 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | @implementation ContextWhitelistFilterLogFormatter 34 | { 35 | LoggingContextSet *contextSet; 36 | } 37 | 38 | - (id)init 39 | { 40 | if ((self = [super init])) 41 | { 42 | contextSet = [[LoggingContextSet alloc] init]; 43 | } 44 | return self; 45 | } 46 | 47 | 48 | - (void)addToWhitelist:(int)loggingContext 49 | { 50 | [contextSet addToSet:loggingContext]; 51 | } 52 | 53 | - (void)removeFromWhitelist:(int)loggingContext 54 | { 55 | [contextSet removeFromSet:loggingContext]; 56 | } 57 | 58 | - (NSArray *)whitelist 59 | { 60 | return [contextSet currentSet]; 61 | } 62 | 63 | - (BOOL)isOnWhitelist:(int)loggingContext 64 | { 65 | return [contextSet isInSet:loggingContext]; 66 | } 67 | 68 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage 69 | { 70 | if ([self isOnWhitelist:logMessage->logContext]) 71 | return logMessage->logMsg; 72 | else 73 | return nil; 74 | } 75 | 76 | @end 77 | 78 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 79 | #pragma mark - 80 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | 82 | @implementation ContextBlacklistFilterLogFormatter 83 | { 84 | LoggingContextSet *contextSet; 85 | } 86 | 87 | - (id)init 88 | { 89 | if ((self = [super init])) 90 | { 91 | contextSet = [[LoggingContextSet alloc] init]; 92 | } 93 | return self; 94 | } 95 | 96 | 97 | - (void)addToBlacklist:(int)loggingContext 98 | { 99 | [contextSet addToSet:loggingContext]; 100 | } 101 | 102 | - (void)removeFromBlacklist:(int)loggingContext 103 | { 104 | [contextSet removeFromSet:loggingContext]; 105 | } 106 | 107 | - (NSArray *)blacklist 108 | { 109 | return [contextSet currentSet]; 110 | } 111 | 112 | - (BOOL)isOnBlacklist:(int)loggingContext 113 | { 114 | return [contextSet isInSet:loggingContext]; 115 | } 116 | 117 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage 118 | { 119 | if ([self isOnBlacklist:logMessage->logContext]) 120 | return nil; 121 | else 122 | return logMessage->logMsg; 123 | } 124 | 125 | @end 126 | 127 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 128 | #pragma mark - 129 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 130 | 131 | @implementation LoggingContextSet 132 | { 133 | OSSpinLock lock; 134 | NSMutableSet *set; 135 | } 136 | 137 | - (id)init 138 | { 139 | if ((self = [super init])) 140 | { 141 | set = [[NSMutableSet alloc] init]; 142 | } 143 | return self; 144 | } 145 | 146 | 147 | - (void)addToSet:(int)loggingContext 148 | { 149 | OSSpinLockLock(&lock); 150 | { 151 | [set addObject:[NSNumber numberWithInt:loggingContext]]; 152 | } 153 | OSSpinLockUnlock(&lock); 154 | } 155 | 156 | - (void)removeFromSet:(int)loggingContext 157 | { 158 | OSSpinLockLock(&lock); 159 | { 160 | [set removeObject:[NSNumber numberWithInt:loggingContext]]; 161 | } 162 | OSSpinLockUnlock(&lock); 163 | } 164 | 165 | - (NSArray *)currentSet 166 | { 167 | NSArray *result = nil; 168 | 169 | OSSpinLockLock(&lock); 170 | { 171 | result = [set allObjects]; 172 | } 173 | OSSpinLockUnlock(&lock); 174 | 175 | return result; 176 | } 177 | 178 | - (BOOL)isInSet:(int)loggingContext 179 | { 180 | BOOL result = NO; 181 | 182 | OSSpinLockLock(&lock); 183 | { 184 | result = [set containsObject:[NSNumber numberWithInt:loggingContext]]; 185 | } 186 | OSSpinLockUnlock(&lock); 187 | 188 | return result; 189 | } 190 | 191 | @end 192 | -------------------------------------------------------------------------------- /Extensions/DispatchQueueLogFormatter.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "DDLog.h" 4 | 5 | 6 | /** 7 | * Welcome to Cocoa Lumberjack! 8 | * 9 | * The project page has a wealth of documentation if you have any questions. 10 | * https://github.com/robbiehanson/CocoaLumberjack 11 | * 12 | * If you're new to the project you may wish to read the "Getting Started" page. 13 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 14 | * 15 | * 16 | * This class provides a log formatter that prints the dispatch_queue label instead of the mach_thread_id. 17 | * 18 | * A log formatter can be added to any logger to format and/or filter its output. 19 | * You can learn more about log formatters here: 20 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomFormatters 21 | * 22 | * A typical NSLog (or DDTTYLogger) prints detailed info as [:]. 23 | * For example: 24 | * 25 | * 2011-10-17 20:21:45.435 AppName[19928:5207] Your log message here 26 | * 27 | * Where: 28 | * - 19928 = process id 29 | * - 5207 = thread id (mach_thread_id printed in hex) 30 | * 31 | * When using grand central dispatch (GCD), this information is less useful. 32 | * This is because a single serial dispatch queue may be run on any thread from an internally managed thread pool. 33 | * For example: 34 | * 35 | * 2011-10-17 20:32:31.111 AppName[19954:4d07] Message from my_serial_dispatch_queue 36 | * 2011-10-17 20:32:31.112 AppName[19954:5207] Message from my_serial_dispatch_queue 37 | * 2011-10-17 20:32:31.113 AppName[19954:2c55] Message from my_serial_dispatch_queue 38 | * 39 | * This formatter allows you to replace the standard [box:info] with the dispatch_queue name. 40 | * For example: 41 | * 42 | * 2011-10-17 20:32:31.111 AppName[img-scaling] Message from my_serial_dispatch_queue 43 | * 2011-10-17 20:32:31.112 AppName[img-scaling] Message from my_serial_dispatch_queue 44 | * 2011-10-17 20:32:31.113 AppName[img-scaling] Message from my_serial_dispatch_queue 45 | * 46 | * If the dispatch_queue doesn't have a set name, then it falls back to the thread name. 47 | * If the current thread doesn't have a set name, then it falls back to the mach_thread_id in hex (like normal). 48 | * 49 | * Note: If manually creating your own background threads (via NSThread/alloc/init or NSThread/detachNeThread), 50 | * you can use [[NSThread currentThread] setName:(NSString *)]. 51 | **/ 52 | @interface DispatchQueueLogFormatter : NSObject 53 | { 54 | @protected 55 | 56 | NSDateFormatter *dateFormatter; 57 | 58 | @private 59 | 60 | OSSpinLock lock; 61 | 62 | NSUInteger _minQueueLength; // _prefix == Only access via atomic property 63 | NSUInteger _maxQueueLength; // _prefix == Only access via atomic property 64 | NSMutableDictionary *_replacements; // _prefix == Only access from within spinlock 65 | } 66 | 67 | /** 68 | * Standard init method. 69 | * Configure using properties as desired. 70 | **/ 71 | - (id)init; 72 | 73 | /** 74 | * The minQueueLength restricts the minimum size of the [detail box]. 75 | * If the minQueueLength is set to 0, there is no restriction. 76 | * 77 | * For example, say a dispatch_queue has a label of "diskIO": 78 | * 79 | * If the minQueueLength is 0: [diskIO] 80 | * If the minQueueLength is 4: [diskIO] 81 | * If the minQueueLength is 5: [diskIO] 82 | * If the minQueueLength is 6: [diskIO] 83 | * If the minQueueLength is 7: [diskIO ] 84 | * If the minQueueLength is 8: [diskIO ] 85 | * 86 | * The default minQueueLength is 0 (no minimum, so [detail box] won't be padded). 87 | **/ 88 | @property (assign) NSUInteger minQueueLength; 89 | 90 | /** 91 | * The maxQueueLength restricts the number of characters that will be inside the [detail box]. 92 | * If the maxQueueLength is 0, there is no restriction. 93 | * For example: 94 | * 95 | * Say a dispatch_queue has a label of "diskIO". (standardizedQueueLength==NO) 96 | * If the maxQueueLength is 0: [diskIO] 97 | * If the maxQueueLength is 4: [disk] 98 | * If the maxQueueLength is 5: [diskI] 99 | * If the maxQueueLength is 6: [diskIO] 100 | * If the maxQueueLength is 7: [diskIO] 101 | * If the maxQueueLength is 8: [diskIO] 102 | * 103 | * The default maxQueueLength is 0 (no maximum, so [thread box] queue names won't be truncated). 104 | **/ 105 | @property (assign) NSUInteger maxQueueLength; 106 | 107 | /** 108 | * Sometimes queue labels have long names like "com.apple.main-queue", 109 | * but you'd prefer something shorter like simply "main". 110 | * 111 | * This method allows you to set such preferred replacements. 112 | * The above example is set by default. 113 | * 114 | * To remove/undo a previous replacement, invoke this method with nil for the 'shortLabel' parameter. 115 | **/ 116 | - (NSString *)replacementStringForQueueLabel:(NSString *)longLabel; 117 | - (void)setReplacementString:(NSString *)shortLabel forQueueLabel:(NSString *)longLabel; 118 | 119 | @end 120 | -------------------------------------------------------------------------------- /Extensions/DispatchQueueLogFormatter.m: -------------------------------------------------------------------------------- 1 | #import "DispatchQueueLogFormatter.h" 2 | 3 | /** 4 | * Welcome to Cocoa Lumberjack! 5 | * 6 | * The project page has a wealth of documentation if you have any questions. 7 | * https://github.com/robbiehanson/CocoaLumberjack 8 | * 9 | * If you're new to the project you may wish to read the "Getting Started" wiki. 10 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 11 | **/ 12 | 13 | #if ! __has_feature(objc_arc) 14 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 15 | #endif 16 | 17 | 18 | @implementation DispatchQueueLogFormatter 19 | 20 | - (id)init 21 | { 22 | if ((self = [super init])) 23 | { 24 | dateFormatter = [[NSDateFormatter alloc] init]; 25 | [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4]; 26 | [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss:SSS"]; 27 | 28 | _minQueueLength = 0; 29 | _maxQueueLength = 0; 30 | _replacements = [[NSMutableDictionary alloc] init]; 31 | 32 | // Set default replacements: 33 | 34 | [_replacements setObject:@"main" forKey:@"com.apple.main-thread"]; 35 | } 36 | return self; 37 | } 38 | 39 | 40 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 41 | #pragma mark Configuration 42 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 43 | 44 | @synthesize minQueueLength = _minQueueLength; 45 | @synthesize maxQueueLength = _maxQueueLength; 46 | 47 | - (NSString *)replacementStringForQueueLabel:(NSString *)longLabel 48 | { 49 | NSString *result = nil; 50 | 51 | OSSpinLockLock(&lock); 52 | { 53 | result = [_replacements objectForKey:longLabel]; 54 | } 55 | OSSpinLockUnlock(&lock); 56 | 57 | return result; 58 | } 59 | 60 | - (void)setReplacementString:(NSString *)shortLabel forQueueLabel:(NSString *)longLabel 61 | { 62 | OSSpinLockLock(&lock); 63 | { 64 | if (shortLabel) 65 | [_replacements setObject:shortLabel forKey:longLabel]; 66 | else 67 | [_replacements removeObjectForKey:longLabel]; 68 | } 69 | OSSpinLockUnlock(&lock); 70 | } 71 | 72 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 73 | #pragma mark DDLogFormatter 74 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 75 | 76 | - (NSString *)queueThreadLabelForLogMessage:(DDLogMessage *)logMessage 77 | { 78 | // As per the DDLogFormatter contract, this method is always invoked on the same thread/dispatch_queue 79 | 80 | NSUInteger minQueueLength = self.minQueueLength; 81 | NSUInteger maxQueueLength = self.maxQueueLength; 82 | 83 | // Get the name of the queue, thread, or machID (whichever we are to use). 84 | 85 | NSString *queueThreadLabel = nil; 86 | 87 | BOOL useQueueLabel = YES; 88 | BOOL useThreadName = NO; 89 | 90 | if (logMessage->queueLabel) 91 | { 92 | // If you manually create a thread, it's dispatch_queue will have one of the thread names below. 93 | // Since all such threads have the same name, we'd prefer to use the threadName or the machThreadID. 94 | 95 | char *names[] = { "com.apple.root.low-priority", 96 | "com.apple.root.default-priority", 97 | "com.apple.root.high-priority", 98 | "com.apple.root.low-overcommit-priority", 99 | "com.apple.root.default-overcommit-priority", 100 | "com.apple.root.high-overcommit-priority" }; 101 | 102 | int length = sizeof(names) / sizeof(char *); 103 | 104 | int i; 105 | for (i = 0; i < length; i++) 106 | { 107 | if (strcmp(logMessage->queueLabel, names[i]) == 0) 108 | { 109 | useQueueLabel = NO; 110 | useThreadName = [logMessage->threadName length] > 0; 111 | break; 112 | } 113 | } 114 | } 115 | else 116 | { 117 | useQueueLabel = NO; 118 | useThreadName = [logMessage->threadName length] > 0; 119 | } 120 | 121 | if (useQueueLabel || useThreadName) 122 | { 123 | NSString *fullLabel; 124 | NSString *abrvLabel; 125 | 126 | if (useQueueLabel) 127 | fullLabel = [NSString stringWithUTF8String:logMessage->queueLabel]; 128 | else 129 | fullLabel = logMessage->threadName; 130 | 131 | OSSpinLockLock(&lock); 132 | { 133 | abrvLabel = [_replacements objectForKey:fullLabel]; 134 | } 135 | OSSpinLockUnlock(&lock); 136 | 137 | if (abrvLabel) 138 | queueThreadLabel = abrvLabel; 139 | else 140 | queueThreadLabel = fullLabel; 141 | } 142 | else 143 | { 144 | queueThreadLabel = [NSString stringWithFormat:@"%x", logMessage->machThreadID]; 145 | } 146 | 147 | // Now use the thread label in the output 148 | 149 | NSUInteger labelLength = [queueThreadLabel length]; 150 | 151 | // labelLength > maxQueueLength : truncate 152 | // labelLength < minQueueLength : padding 153 | // : exact 154 | 155 | if ((maxQueueLength > 0) && (labelLength > maxQueueLength)) 156 | { 157 | // Truncate 158 | 159 | return [queueThreadLabel substringToIndex:maxQueueLength]; 160 | } 161 | else if (labelLength < minQueueLength) 162 | { 163 | // Padding 164 | 165 | NSUInteger numSpaces = minQueueLength - labelLength; 166 | 167 | char spaces[numSpaces + 1]; 168 | memset(spaces, ' ', numSpaces); 169 | spaces[numSpaces] = '\0'; 170 | 171 | return [NSString stringWithFormat:@"%@%s", queueThreadLabel, spaces]; 172 | } 173 | else 174 | { 175 | // Exact 176 | 177 | return queueThreadLabel; 178 | } 179 | } 180 | 181 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage 182 | { 183 | NSString *timestamp = [dateFormatter stringFromDate:(logMessage->timestamp)]; 184 | NSString *queueThreadLabel = [self queueThreadLabelForLogMessage:logMessage]; 185 | 186 | return [NSString stringWithFormat:@"%@ [%@] %@", timestamp, queueThreadLabel, logMessage->logMsg]; 187 | } 188 | 189 | @end 190 | -------------------------------------------------------------------------------- /ConnectTest/TestUI.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestUI.m 3 | // ConnectTest 4 | // 5 | // Created by SmallTask on 13-8-15. 6 | // 7 | // 8 | 9 | #import "TestUI.h" 10 | 11 | @interface TestUI () 12 | 13 | @end 14 | 15 | @implementation TestUI 16 | 17 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 18 | { 19 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 20 | if (self) { 21 | // Custom initialization 22 | } 23 | return self; 24 | } 25 | 26 | - (void)viewDidLoad 27 | { 28 | [super viewDidLoad]; 29 | // Do any additional setup after loading the view from its nib. 30 | self.tfRecived.text = @""; 31 | 32 | [self netstate]; 33 | } 34 | 35 | - (void)didReceiveMemoryWarning 36 | { 37 | [super didReceiveMemoryWarning]; 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | -(void)netstate; 42 | { 43 | NSLog(@"开启 www.apple.com 的网络检测"); 44 | Reachability* reach = [Reachability reachabilityWithHostname:@"www.apple.com"]; 45 | NSLog(@"-- current status: %@", reach.currentReachabilityString); 46 | 47 | // start the notifier which will cause the reachability object to retain itself! 48 | 49 | [[NSNotificationCenter defaultCenter] addObserver:self 50 | selector:@selector(reachabilityChanged:) 51 | name:kReachabilityChangedNotification 52 | object:nil]; 53 | /* 54 | reach.reachableBlock = ^(Reachability * reachability) 55 | { 56 | dispatch_async(dispatch_get_main_queue(), ^{ 57 | // self.blockLabel.text = @"网络可用"; 58 | // self.blockLabel.backgroundColor = [UIColor greenColor]; 59 | }); 60 | }; 61 | 62 | reach.unreachableBlock = ^(Reachability * reachability) 63 | { 64 | dispatch_async(dispatch_get_main_queue(), ^{ 65 | self.tfRecived.text = @"网络不可用"; 66 | self.tfRecived.backgroundColor = [UIColor redColor]; 67 | }); 68 | }; 69 | 70 | */ 71 | [reach startNotifier]; 72 | 73 | } 74 | 75 | - (void) reachabilityChanged: (NSNotification*)note { 76 | Reachability * reach = [note object]; 77 | 78 | if(![reach isReachable]) 79 | { 80 | self.tfRecived.text = @"网络不可用"; 81 | self.tfRecived.backgroundColor = [UIColor redColor]; 82 | 83 | // self.wifiOnlyLabel.backgroundColor = [UIColor redColor]; 84 | // self.wwanOnlyLabel.backgroundColor = [UIColor redColor]; 85 | 86 | TcpClient *tcp = [TcpClient sharedInstance]; 87 | [tcp setDelegate_ITcpClient:self]; 88 | 89 | [tcp.asyncSocket disconnect]; 90 | 91 | return; 92 | } 93 | 94 | self.tfRecived.text = @"网络可用"; 95 | self.tfRecived.backgroundColor = [UIColor greenColor]; 96 | 97 | if (reach.isReachableViaWiFi) { 98 | self.tfRecived.backgroundColor = [UIColor greenColor]; 99 | self.tfRecived.text = @"当前通过wifi连接"; 100 | } else { 101 | self.tfRecived.backgroundColor = [UIColor redColor]; 102 | self.tfRecived.text = @"wifi未开启,不能用"; 103 | } 104 | 105 | if (reach.isReachableViaWWAN) { 106 | self.tfRecived.backgroundColor = [UIColor greenColor]; 107 | self.tfRecived.text = @"当前通过2g or 3g连接"; 108 | } else { 109 | self.tfRecived.backgroundColor = [UIColor redColor]; 110 | self.tfRecived.text = @"2g or 3g网络未使用"; 111 | } 112 | } 113 | 114 | 115 | - (IBAction)onBtConnection:(id)sender { 116 | TcpClient *tcp = [TcpClient sharedInstance]; 117 | [tcp setDelegate_ITcpClient:self]; 118 | if(tcp.asyncSocket.isConnected) 119 | { 120 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"网络已经连接好啦!" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil]; 121 | [alert show]; 122 | }else 123 | { 124 | NSString *HOST = self.tfAddress.text; 125 | NSString *port = self.tfPort.text; 126 | [tcp openTcpConnection:HOST port:[port intValue]]; 127 | } 128 | 129 | [self resignKeyboard]; 130 | 131 | } 132 | 133 | //发送消息 134 | - (IBAction)onbtClicked:(id)sender { 135 | 136 | // NSString *txt = self.tftxt.text; 137 | // NSData *data = [txt dataUsingEncoding:NSUTF8StringEncoding]; 138 | TcpClient *tcp = [TcpClient sharedInstance]; 139 | if(tcp.asyncSocket.isDisconnected) 140 | { 141 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"网络不通" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil]; 142 | [alert show]; 143 | return; 144 | }else if(tcp.asyncSocket.isConnected) 145 | { 146 | 147 | NSString *requestStr = [NSString stringWithFormat:@"%@\r\n",self.tftxt.text]; 148 | [tcp writeString:requestStr]; 149 | 150 | }else{ 151 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"TCP链接没有建立" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil]; 152 | [alert show]; 153 | } 154 | 155 | [self resignKeyboard]; 156 | } 157 | 158 | -(void)resignKeyboard; 159 | { 160 | [self.tfAddress resignFirstResponder]; 161 | [self.tfPort resignFirstResponder]; 162 | [self.tftxt resignFirstResponder]; 163 | } 164 | 165 | #pragma mark - 166 | #pragma mark ITcpClient 167 | 168 | /**发送到服务器端的数据*/ 169 | -(void)OnSendDataSuccess:(NSString*)sendedTxt; 170 | { 171 | self.tfRecived.text = [NSString stringWithFormat:@"%@\r\nsended-->:%@\r\n",self.tfRecived.text,sendedTxt]; 172 | } 173 | 174 | /**收到服务器端发送的数据*/ 175 | -(void)OnReciveData:(NSString*)recivedTxt; 176 | { 177 | self.tfRecived.text = [NSString stringWithFormat:@"%@\r\n-->recived:%@\r\n",self.tfRecived.text,recivedTxt]; 178 | } 179 | 180 | /**socket连接出现错误*/ 181 | -(void)OnConnectionError:(NSError *)err; 182 | { 183 | self.tfRecived.text = [NSString stringWithFormat:@"%@\r\n\r\n**** network error! ****\r\n",self.tfRecived.text]; 184 | } 185 | 186 | #pragma mark - 187 | #pragma mark UIScrollerView 188 | -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 189 | { 190 | [self resignKeyboard]; 191 | } 192 | 193 | 194 | @end 195 | -------------------------------------------------------------------------------- /vendor/DDTTYLogger.h: -------------------------------------------------------------------------------- 1 | #import 2 | #if TARGET_OS_IPHONE 3 | #import 4 | #else 5 | #import 6 | #endif 7 | 8 | #import "DDLog.h" 9 | 10 | /** 11 | * Welcome to Cocoa Lumberjack! 12 | * 13 | * The project page has a wealth of documentation if you have any questions. 14 | * https://github.com/robbiehanson/CocoaLumberjack 15 | * 16 | * If you're new to the project you may wish to read the "Getting Started" wiki. 17 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 18 | * 19 | * 20 | * This class provides a logger for Terminal output or Xcode console output, 21 | * depending on where you are running your code. 22 | * 23 | * As described in the "Getting Started" page, 24 | * the traditional NSLog() function directs it's output to two places: 25 | * 26 | * - Apple System Log (so it shows up in Console.app) 27 | * - StdErr (if stderr is a TTY, so log statements show up in Xcode console) 28 | * 29 | * To duplicate NSLog() functionality you can simply add this logger and an asl logger. 30 | * However, if you instead choose to use file logging (for faster performance), 31 | * you may choose to use only a file logger and a tty logger. 32 | **/ 33 | 34 | @interface DDTTYLogger : DDAbstractLogger 35 | { 36 | NSCalendar *calendar; 37 | NSUInteger calendarUnitFlags; 38 | 39 | NSString *appName; 40 | char *app; 41 | size_t appLen; 42 | 43 | NSString *processID; 44 | char *pid; 45 | size_t pidLen; 46 | 47 | BOOL colorsEnabled; 48 | NSMutableArray *colorProfilesArray; 49 | NSMutableDictionary *colorProfilesDict; 50 | } 51 | 52 | + (DDTTYLogger *)sharedInstance; 53 | 54 | /* Inherited from the DDLogger protocol: 55 | * 56 | * Formatters may optionally be added to any logger. 57 | * 58 | * If no formatter is set, the logger simply logs the message as it is given in logMessage, 59 | * or it may use its own built in formatting style. 60 | * 61 | * More information about formatters can be found here: 62 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomFormatters 63 | * 64 | * The actual implementation of these methods is inherited from DDAbstractLogger. 65 | 66 | - (id )logFormatter; 67 | - (void)setLogFormatter:(id )formatter; 68 | 69 | */ 70 | 71 | /** 72 | * Want to use different colors for different log levels? 73 | * Enable this property. 74 | * 75 | * If you run the application via the Terminal (not Xcode), 76 | * the logger will map colors to xterm-256color or xterm-color (if available). 77 | * 78 | * Xcode does NOT natively support colors in the Xcode debugging console. 79 | * You'll need to install the XcodeColors plugin to see colors in the Xcode console. 80 | * https://github.com/robbiehanson/XcodeColors 81 | * 82 | * The default value if NO. 83 | **/ 84 | @property (readwrite, assign) BOOL colorsEnabled; 85 | 86 | /** 87 | * The default color set (foregroundColor, backgroundColor) is: 88 | * 89 | * - LOG_FLAG_ERROR = (red, nil) 90 | * - LOG_FLAG_WARN = (orange, nil) 91 | * 92 | * You can customize the colors however you see fit. 93 | * Please note that you are passing a flag, NOT a level. 94 | * 95 | * GOOD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:LOG_FLAG_INFO]; // <- Good :) 96 | * BAD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:LOG_LEVEL_INFO]; // <- BAD! :( 97 | * 98 | * LOG_FLAG_INFO = 0...00100 99 | * LOG_LEVEL_INFO = 0...00111 <- Would match LOG_FLAG_INFO and LOG_FLAG_WARN and LOG_FLAG_ERROR 100 | * 101 | * If you run the application within Xcode, then the XcodeColors plugin is required. 102 | * 103 | * If you run the application from a shell, then DDTTYLogger will automatically map the given color to 104 | * the closest available color. (xterm-256color or xterm-color which have 256 and 16 supported colors respectively.) 105 | * 106 | * This method invokes setForegroundColor:backgroundColor:forFlag:context: and passes the default context (0). 107 | **/ 108 | #if TARGET_OS_IPHONE 109 | - (void)setForegroundColor:(UIColor *)txtColor backgroundColor:(UIColor *)bgColor forFlag:(int)mask; 110 | #else 111 | - (void)setForegroundColor:(NSColor *)txtColor backgroundColor:(NSColor *)bgColor forFlag:(int)mask; 112 | #endif 113 | 114 | /** 115 | * Just like setForegroundColor:backgroundColor:flag, but allows you to specify a particular logging context. 116 | * 117 | * A logging context is often used to identify log messages coming from a 3rd party framework, 118 | * although logging context's can be used for many different functions. 119 | * 120 | * Logging context's are explained in further detail here: 121 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomContext 122 | **/ 123 | #if TARGET_OS_IPHONE 124 | - (void)setForegroundColor:(UIColor *)txtColor backgroundColor:(UIColor *)bgColor forFlag:(int)mask context:(int)ctxt; 125 | #else 126 | - (void)setForegroundColor:(NSColor *)txtColor backgroundColor:(NSColor *)bgColor forFlag:(int)mask context:(int)ctxt; 127 | #endif 128 | 129 | /** 130 | * Similar to the methods above, but allows you to map DDLogMessage->tag to a particular color profile. 131 | * For example, you could do something like this: 132 | * 133 | * static NSString *const PurpleTag = @"PurpleTag"; 134 | * 135 | * #define DDLogPurple(frmt, ...) LOG_OBJC_TAG_MACRO(NO, 0, 0, 0, PurpleTag, frmt, ##__VA_ARGS__) 136 | * 137 | * And then in your applicationDidFinishLaunching, or wherever you configure Lumberjack: 138 | * 139 | * #if TARGET_OS_IPHONE 140 | * UIColor *purple = [UIColor colorWithRed:(64/255.0) green:(0/255.0) blue:(128/255.0) alpha:1.0]; 141 | * #else 142 | * NSColor *purple = [NSColor colorWithCalibratedRed:(64/255.0) green:(0/255.0) blue:(128/255.0) alpha:1.0]; 143 | * 144 | * [[DDTTYLogger sharedInstance] setForegroundColor:purple backgroundColor:nil forTag:PurpleTag]; 145 | * [DDLog addLogger:[DDTTYLogger sharedInstance]]; 146 | * 147 | * This would essentially give you a straight NSLog replacement that prints in purple: 148 | * 149 | * DDLogPurple(@"I'm a purple log message!"); 150 | **/ 151 | #if TARGET_OS_IPHONE 152 | - (void)setForegroundColor:(UIColor *)txtColor backgroundColor:(UIColor *)bgColor forTag:(id )tag; 153 | #else 154 | - (void)setForegroundColor:(NSColor *)txtColor backgroundColor:(NSColor *)bgColor forTag:(id )tag; 155 | #endif 156 | 157 | /** 158 | * Clearing color profiles. 159 | **/ 160 | - (void)clearColorsForFlag:(int)mask; 161 | - (void)clearColorsForFlag:(int)mask context:(int)context; 162 | - (void)clearColorsForTag:(id )tag; 163 | - (void)clearColorsForAllFlags; 164 | - (void)clearColorsForAllTags; 165 | - (void)clearAllColors; 166 | 167 | @end 168 | -------------------------------------------------------------------------------- /ConnectTest/ConnectTestAppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "ConnectTestAppDelegate.h" 2 | #import "ConnectTestViewController.h" 3 | #import "GCDAsyncSocket.h" 4 | #import "DDLog.h" 5 | #import "DDTTYLogger.h" 6 | 7 | // Log levels: off, error, warn, info, verbose 8 | static const int ddLogLevel = LOG_LEVEL_INFO; 9 | 10 | #define USE_SECURE_CONNECTION 0 11 | #define ENABLE_BACKGROUNDING 0 12 | 13 | #if USE_SECURE_CONNECTION 14 | #define HOST @"www.paypal.com" 15 | #define PORT 443 16 | #else 17 | #define HOST @"192.168.254.110 " 18 | #define PORT 88 19 | #endif 20 | 21 | @implementation ConnectTestAppDelegate 22 | 23 | @synthesize window = _window; 24 | @synthesize viewController = _viewController; 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | #pragma mark Application Lifecycle 28 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | 30 | - (id)init 31 | { 32 | if ((self = [super init])) 33 | { 34 | // Setup logging framework 35 | [DDLog addLogger:[DDTTYLogger sharedInstance]]; 36 | } 37 | return self; 38 | } 39 | 40 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 41 | { 42 | /* 43 | DDLogInfo(@"%@", THIS_METHOD); 44 | 45 | // Setup our socket (GCDAsyncSocket). 46 | // The socket will invoke our delegate methods using the usual delegate paradigm. 47 | // However, it will invoke the delegate methods on a specified GCD delegate dispatch queue. 48 | // 49 | // Now we can configure the delegate dispatch queue however we want. 50 | // We could use a dedicated dispatch queue for easy parallelization. 51 | // Or we could simply use the dispatch queue for the main thread. 52 | // 53 | // The best approach for your application will depend upon convenience, requirements and performance. 54 | // 55 | // For this simple example, we're just going to use the main thread. 56 | 57 | dispatch_queue_t mainQueue = dispatch_get_main_queue(); 58 | 59 | asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue]; 60 | 61 | #if USE_SECURE_CONNECTION 62 | { 63 | NSString *host = HOST; 64 | uint16_t port = PORT; 65 | 66 | DDLogInfo(@"Connecting to \"%@\" on port %hu...", host, port); 67 | self.viewController.label.text = @"Connecting..."; 68 | 69 | NSError *error = nil; 70 | if (![asyncSocket connectToHost:@"www.paypal.com" onPort:port error:&error]) 71 | { 72 | DDLogError(@"Error connecting: %@", error); 73 | self.viewController.label.text = @"Oops"; 74 | } 75 | } 76 | #else 77 | { 78 | NSString *host = HOST; 79 | uint16_t port = PORT; 80 | 81 | DDLogInfo(@"Connecting to \"%@\" on port %hu...", host, port); 82 | self.viewController.label.text = @"Connecting..."; 83 | 84 | NSError *error = nil; 85 | if (![asyncSocket connectToHost:host onPort:port error:&error]) 86 | { 87 | DDLogError(@"Error connecting: %@", error); 88 | self.viewController.label.text = @"Oops"; 89 | } 90 | 91 | // You can also specify an optional connect timeout. 92 | 93 | // NSError *error = nil; 94 | // if (![asyncSocket connectToHost:host onPort:80 withTimeout:5.0 error:&error]) 95 | // { 96 | // DDLogError(@"Error connecting: %@", error); 97 | // } 98 | 99 | } 100 | #endif 101 | 102 | // Add the view controller's view to the window and display. 103 | [self.window addSubview:self.viewController.view]; 104 | 105 | */ 106 | 107 | 108 | TestUI *testUI = [[TestUI alloc] initWithNibName:@"TestUI" bundle:nil]; 109 | self.window.rootViewController = testUI; 110 | 111 | 112 | [self.window makeKeyAndVisible]; 113 | 114 | return YES; 115 | } 116 | 117 | - (void)applicationWillResignActive:(UIApplication *)application 118 | { 119 | DDLogInfo(@"%@", THIS_METHOD); 120 | } 121 | 122 | - (void)applicationDidEnterBackground:(UIApplication *)application 123 | { 124 | DDLogInfo(@"%@", THIS_METHOD); 125 | } 126 | 127 | - (void)applicationWillEnterForeground:(UIApplication *)application 128 | { 129 | DDLogInfo(@"%@", THIS_METHOD); 130 | } 131 | 132 | - (void)applicationDidBecomeActive:(UIApplication *)application 133 | { 134 | static BOOL isAppLaunch = YES; 135 | if (isAppLaunch) 136 | { 137 | isAppLaunch = NO; 138 | return; 139 | } 140 | 141 | DDLogInfo(@"%@", THIS_METHOD); 142 | } 143 | 144 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 145 | #pragma mark Socket Delegate 146 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 147 | 148 | - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port 149 | { 150 | 151 | DDLogInfo(@"socket:%p didConnectToHost:%@ port:%hu", sock, host, port); 152 | self.viewController.label.text = @"Connected"; 153 | 154 | // DDLogInfo(@"localHost :%@ port:%hu", [sock localHost], [sock localPort]); 155 | 156 | #if USE_SECURE_CONNECTION 157 | { 158 | // Connected to secure server (HTTPS) 159 | 160 | #if ENABLE_BACKGROUNDING && !TARGET_IPHONE_SIMULATOR 161 | { 162 | // Backgrounding doesn't seem to be supported on the simulator yet 163 | 164 | [sock performBlock:^{ 165 | if ([sock enableBackgroundingOnSocket]) 166 | DDLogInfo(@"Enabled backgrounding on socket"); 167 | else 168 | DDLogWarn(@"Enabling backgrounding failed!"); 169 | }]; 170 | } 171 | #endif 172 | 173 | // Configure SSL/TLS settings 174 | NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:3]; 175 | 176 | // If you simply want to ensure that the remote host's certificate is valid, 177 | // then you can use an empty dictionary. 178 | 179 | // If you know the name of the remote host, then you should specify the name here. 180 | // 181 | // NOTE: 182 | // You should understand the security implications if you do not specify the peer name. 183 | // Please see the documentation for the startTLS method in GCDAsyncSocket.h for a full discussion. 184 | 185 | [settings setObject:@"www.paypal.com" 186 | forKey:(NSString *)kCFStreamSSLPeerName]; 187 | 188 | // To connect to a test server, with a self-signed certificate, use settings similar to this: 189 | 190 | // // Allow expired certificates 191 | // [settings setObject:[NSNumber numberWithBool:YES] 192 | // forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates]; 193 | // 194 | // // Allow self-signed certificates 195 | // [settings setObject:[NSNumber numberWithBool:YES] 196 | // forKey:(NSString *)kCFStreamSSLAllowsAnyRoot]; 197 | // 198 | // // In fact, don't even validate the certificate chain 199 | // [settings setObject:[NSNumber numberWithBool:NO] 200 | // forKey:(NSString *)kCFStreamSSLValidatesCertificateChain]; 201 | 202 | DDLogInfo(@"Starting TLS with settings:\n%@", settings); 203 | 204 | [sock startTLS:settings]; 205 | 206 | // You can also pass nil to the startTLS method, which is the same as passing an empty dictionary. 207 | // Again, you should understand the security implications of doing so. 208 | // Please see the documentation for the startTLS method in GCDAsyncSocket.h for a full discussion. 209 | 210 | } 211 | #else 212 | { 213 | // Connected to normal server (HTTP) 214 | 215 | #if ENABLE_BACKGROUNDING && !TARGET_IPHONE_SIMULATOR 216 | { 217 | // Backgrounding doesn't seem to be supported on the simulator yet 218 | 219 | [sock performBlock:^{ 220 | if ([sock enableBackgroundingOnSocket]) 221 | DDLogInfo(@"Enabled backgrounding on socket"); 222 | else 223 | DDLogWarn(@"Enabling backgrounding failed!"); 224 | }]; 225 | } 226 | #endif 227 | } 228 | #endif 229 | 230 | //模拟发送一条数据 231 | NSString *requestStr = [NSString stringWithFormat:@"GET / HTTP/1.1\r\nHost: %@\r\n\r\n", HOST]; 232 | NSData *requestData = [requestStr dataUsingEncoding:NSUTF8StringEncoding]; 233 | 234 | [sock writeData:requestData withTimeout:20. tag:1]; 235 | } 236 | 237 | - (void)socketDidSecure:(GCDAsyncSocket *)sock 238 | { 239 | DDLogInfo(@"socketDidSecure:%p", sock); 240 | self.viewController.label.text = @"Connected + Secure"; 241 | 242 | NSString *requestStr = [NSString stringWithFormat:@"GET / HTTP/1.1\r\nHost: %@\r\n\r\n", HOST]; 243 | NSData *requestData = [requestStr dataUsingEncoding:NSUTF8StringEncoding]; 244 | 245 | [sock writeData:requestData withTimeout:-1 tag:0]; 246 | [sock readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0]; 247 | } 248 | 249 | - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag 250 | { 251 | DDLogInfo(@"socket:%p didWriteDataWithTag:%ld", sock, tag); 252 | } 253 | 254 | - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 255 | { 256 | DDLogInfo(@"socket:%p didReadData:withTag:%ld", sock, tag); 257 | 258 | NSString *httpResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 259 | 260 | DDLogInfo(@"HTTP Response:\n%@", httpResponse); 261 | 262 | } 263 | 264 | - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err 265 | { 266 | DDLogInfo(@"socketDidDisconnect:%p withError: %@", sock, err); 267 | self.viewController.label.text = @"Disconnected"; 268 | } 269 | 270 | @end 271 | -------------------------------------------------------------------------------- /ConnectTest/TcpClient.m: -------------------------------------------------------------------------------- 1 | // 2 | // TcpClient.m 3 | // ConnectTest 4 | // 5 | // Created by SmallTask on 13-8-15. 6 | // 7 | // 8 | 9 | #import "TcpClient.h" 10 | #import "GCDAsyncSocket.h" 11 | #import "DDLog.h" 12 | #import "DDTTYLogger.h" 13 | 14 | // Log levels: off, error, warn, info, verbose 15 | static const int ddLogLevel = LOG_LEVEL_INFO; 16 | 17 | #define USE_SECURE_CONNECTION 0 18 | #define ENABLE_BACKGROUNDING 0 19 | 20 | #if USE_SECURE_CONNECTION 21 | #define HOST @"www.paypal.com" 22 | #define PORT 443 23 | #else 24 | #define HOST @"192.168.254.2" 25 | #define PORT 55184 26 | #endif 27 | 28 | @implementation TcpClient 29 | @synthesize asyncSocket; 30 | 31 | + (TcpClient *)sharedInstance; 32 | { 33 | static TcpClient *_sharedInstance = nil; 34 | static dispatch_once_t onceToken; 35 | dispatch_once(&onceToken, ^{ 36 | _sharedInstance = [[TcpClient alloc] init]; 37 | }); 38 | 39 | return _sharedInstance; 40 | } 41 | 42 | 43 | -(id)init; 44 | { 45 | self = [super init]; 46 | recivedArray = [NSMutableArray arrayWithCapacity:10]; 47 | return self; 48 | } 49 | 50 | -(void)setDelegate_ITcpClient:(id)_itcpClient; 51 | { 52 | itcpClient = _itcpClient; 53 | } 54 | 55 | -(void)openTcpConnection:(NSString*)host port:(NSInteger)port; 56 | { 57 | DDLogInfo(@"%@", THIS_METHOD); 58 | 59 | // Setup our socket (GCDAsyncSocket). 60 | // The socket will invoke our delegate methods using the usual delegate paradigm. 61 | // However, it will invoke the delegate methods on a specified GCD delegate dispatch queue. 62 | // 63 | // Now we can configure the delegate dispatch queue however we want. 64 | // We could use a dedicated dispatch queue for easy parallelization. 65 | // Or we could simply use the dispatch queue for the main thread. 66 | // 67 | // The best approach for your application will depend upon convenience, requirements and performance. 68 | // 69 | // For this simple example, we're just going to use the main thread. 70 | 71 | // dispatch_queue_t mainQueue = dispatch_get_main_queue(); 72 | dispatch_queue_t mainQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); 73 | asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue]; 74 | 75 | [asyncSocket setAutoDisconnectOnClosedReadStream:NO]; 76 | 77 | #if USE_SECURE_CONNECTION 78 | { 79 | NSString *host = HOST; 80 | uint16_t port = PORT; 81 | 82 | DDLogInfo(@"Connecting to \"%@\" on port %hu...", host, port); 83 | self.viewController.label.text = @"Connecting..."; 84 | 85 | NSError *error = nil; 86 | if (![asyncSocket connectToHost:@"www.paypal.com" onPort:port error:&error]) 87 | { 88 | DDLogError(@"Error connecting: %@", error); 89 | self.viewController.label.text = @"Oops"; 90 | } 91 | } 92 | #else 93 | { 94 | // NSString *host = HOST; 95 | // uint16_t port = PORT; 96 | 97 | DDLogInfo(@"Connecting to \"%@\" on port %hu...", host, port); 98 | // self.viewController.label.text = @"Connecting..."; 99 | 100 | NSError *error = nil; 101 | if (![asyncSocket connectToHost:host onPort:port error:&error]) 102 | { 103 | DDLogError(@"Error connecting: %@", error); 104 | // self.viewController.label.text = @"Oops"; 105 | } 106 | 107 | // You can also specify an optional connect timeout. 108 | 109 | // NSError *error = nil; 110 | // if (![asyncSocket connectToHost:host onPort:80 withTimeout:5.0 error:&error]) 111 | // { 112 | // DDLogError(@"Error connecting: %@", error); 113 | // } 114 | 115 | } 116 | #endif 117 | 118 | 119 | 120 | } 121 | 122 | -(void)writeString:(NSString*)datastr; 123 | { 124 | NSString *requestStr = [NSString stringWithFormat:@"%@\r\n",datastr]; 125 | 126 | NSData *requestData = [requestStr dataUsingEncoding:NSUTF8StringEncoding]; 127 | [self writeData:requestData]; 128 | } 129 | 130 | -(void)writeData:(NSData*)data; 131 | { 132 | TAG_SEND++; 133 | [asyncSocket writeData:data withTimeout:-1. tag:TAG_SEND]; 134 | } 135 | 136 | -(void)read; 137 | { 138 | [asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0]; 139 | // [asyncSocket readDataToData:[GCDAsyncSocket ZeroData] withTimeout:-1 tag:0]; 140 | // [asyncSocket readDataToLength:1 withTimeout:-1 tag:0]; 141 | } 142 | 143 | -(long)GetSendTag; 144 | { 145 | return TAG_SEND; 146 | } 147 | 148 | -(long)GetRecivedTag; 149 | { 150 | return TAG_RECIVED; 151 | } 152 | 153 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 154 | #pragma mark Socket Delegate 155 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 156 | 157 | - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port 158 | { 159 | DDLogInfo(@"socket:%p didConnectToHost:%@ port:%hu", sock, host, port); 160 | // self.viewController.label.text = @"Connected"; 161 | 162 | // DDLogInfo(@"localHost :%@ port:%hu", [sock localHost], [sock localPort]); 163 | [self read]; 164 | 165 | #if USE_SECURE_CONNECTION 166 | { 167 | // Connected to secure server (HTTPS) 168 | 169 | #if ENABLE_BACKGROUNDING && !TARGET_IPHONE_SIMULATOR 170 | { 171 | // Backgrounding doesn't seem to be supported on the simulator yet 172 | 173 | [sock performBlock:^{ 174 | if ([sock enableBackgroundingOnSocket]) 175 | DDLogInfo(@"Enabled backgrounding on socket"); 176 | else 177 | DDLogWarn(@"Enabling backgrounding failed!"); 178 | }]; 179 | } 180 | #endif 181 | 182 | // Configure SSL/TLS settings 183 | NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:3]; 184 | 185 | // If you simply want to ensure that the remote host's certificate is valid, 186 | // then you can use an empty dictionary. 187 | 188 | // If you know the name of the remote host, then you should specify the name here. 189 | // 190 | // NOTE: 191 | // You should understand the security implications if you do not specify the peer name. 192 | // Please see the documentation for the startTLS method in GCDAsyncSocket.h for a full discussion. 193 | 194 | [settings setObject:@"www.paypal.com" 195 | forKey:(NSString *)kCFStreamSSLPeerName]; 196 | 197 | // To connect to a test server, with a self-signed certificate, use settings similar to this: 198 | 199 | // // Allow expired certificates 200 | // [settings setObject:[NSNumber numberWithBool:YES] 201 | // forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates]; 202 | // 203 | // // Allow self-signed certificates 204 | // [settings setObject:[NSNumber numberWithBool:YES] 205 | // forKey:(NSString *)kCFStreamSSLAllowsAnyRoot]; 206 | // 207 | // // In fact, don't even validate the certificate chain 208 | // [settings setObject:[NSNumber numberWithBool:NO] 209 | // forKey:(NSString *)kCFStreamSSLValidatesCertificateChain]; 210 | 211 | DDLogInfo(@"Starting TLS with settings:\n%@", settings); 212 | 213 | [sock startTLS:settings]; 214 | 215 | // You can also pass nil to the startTLS method, which is the same as passing an empty dictionary. 216 | // Again, you should understand the security implications of doing so. 217 | // Please see the documentation for the startTLS method in GCDAsyncSocket.h for a full discussion. 218 | 219 | } 220 | #else 221 | { 222 | // Connected to normal server (HTTP) 223 | 224 | #if ENABLE_BACKGROUNDING && !TARGET_IPHONE_SIMULATOR 225 | { 226 | // Backgrounding doesn't seem to be supported on the simulator yet 227 | 228 | [sock performBlock:^{ 229 | if ([sock enableBackgroundingOnSocket]) 230 | DDLogInfo(@"Enabled backgrounding on socket"); 231 | else 232 | DDLogWarn(@"Enabling backgrounding failed!"); 233 | }]; 234 | } 235 | #endif 236 | } 237 | #endif 238 | 239 | //模拟发送一条数据 240 | // NSString *requestStr = [NSString stringWithFormat:@"GET / HTTP/1.1\r\nHost: %@\r\n\r\n", HOST]; 241 | // NSData *requestData = [requestStr dataUsingEncoding:NSUTF8StringEncoding]; 242 | // 243 | // [sock writeData:requestData withTimeout:20. tag:1]; 244 | 245 | 246 | } 247 | 248 | - (void)socketDidSecure:(GCDAsyncSocket *)sock 249 | { 250 | DDLogInfo(@"socketDidSecure:%p", sock); 251 | // self.viewController.label.text = @"Connected + Secure"; 252 | 253 | NSString *requestStr = [NSString stringWithFormat:@"GET / HTTP/1.1\r\nHost: %@\r\n\r\n", HOST]; 254 | NSData *requestData = [requestStr dataUsingEncoding:NSUTF8StringEncoding]; 255 | 256 | [sock writeData:requestData withTimeout:-1 tag:0]; 257 | [sock readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0]; 258 | } 259 | 260 | - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag 261 | { 262 | DDLogInfo(@"socket:%p didWriteDataWithTag:%ld", sock, tag); 263 | dispatch_async(dispatch_get_main_queue(), ^{ 264 | [itcpClient OnSendDataSuccess:[NSString stringWithFormat:@"tag:%li",tag]]; 265 | }); 266 | } 267 | 268 | - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 269 | { 270 | DDLogInfo(@"socket:%p didReadData:withTag:%ld", sock, tag); 271 | 272 | NSString *httpResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 273 | 274 | DDLogInfo(@"HTTP Response:\n%@", httpResponse); 275 | 276 | TAG_RECIVED = tag; 277 | 278 | if(![httpResponse isEqualToString:@""]) 279 | [recivedArray addObject:httpResponse]; 280 | 281 | dispatch_async(dispatch_get_main_queue(), ^{ 282 | // 283 | [itcpClient OnReciveData:httpResponse]; 284 | }); 285 | 286 | 287 | [self read]; 288 | 289 | [self writeString:@""]; 290 | 291 | 292 | } 293 | 294 | - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err 295 | { 296 | DDLogInfo(@"socketDidDisconnect:%p withError: %@", sock, err); 297 | dispatch_async(dispatch_get_main_queue(), ^{ 298 | [itcpClient OnConnectionError:err]; 299 | }); 300 | } 301 | 302 | - (void)socketDidCloseReadStream:(GCDAsyncSocket *)sock 303 | { 304 | 305 | } 306 | 307 | 308 | 309 | @end 310 | -------------------------------------------------------------------------------- /en.lproj/ConnectTestViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1536 5 | 11E53 6 | 2541 7 | 1138.47 8 | 569.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 1875 12 | 13 | 14 | YES 15 | IBProxyObject 16 | IBUILabel 17 | IBUIView 18 | 19 | 20 | YES 21 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 22 | 23 | 24 | PluginDependencyRecalculationVersion 25 | 26 | 27 | 28 | YES 29 | 30 | IBFilesOwner 31 | IBCocoaTouchFramework 32 | 33 | 34 | IBFirstResponder 35 | IBCocoaTouchFramework 36 | 37 | 38 | 39 | 274 40 | 41 | YES 42 | 43 | 44 | 292 45 | {{20, 135}, {280, 21}} 46 | 47 | 48 | 49 | NO 50 | YES 51 | 7 52 | NO 53 | IBCocoaTouchFramework 54 | 55 | 1 56 | Label 57 | 58 | 1 59 | MCAwIDAAA 60 | 61 | 1 62 | 63 | 1 64 | 17 65 | 66 | 67 | Helvetica 68 | 17 69 | 16 70 | 71 | NO 72 | 0 73 | 74 | 75 | {{0, 20}, {320, 460}} 76 | 77 | 78 | 79 | 80 | 3 81 | MC43NQA 82 | 83 | 2 84 | 85 | 86 | NO 87 | 88 | IBCocoaTouchFramework 89 | 90 | 91 | 92 | 93 | YES 94 | 95 | 96 | view 97 | 98 | 99 | 100 | 7 101 | 102 | 103 | 104 | label 105 | 106 | 107 | 108 | 17 109 | 110 | 111 | 112 | 113 | YES 114 | 115 | 0 116 | 117 | YES 118 | 119 | 120 | 121 | 122 | 123 | -1 124 | 125 | 126 | File's Owner 127 | 128 | 129 | -2 130 | 131 | 132 | 133 | 134 | 6 135 | 136 | 137 | YES 138 | 139 | 140 | 141 | 142 | 143 | 16 144 | 145 | 146 | 147 | 148 | 149 | 150 | YES 151 | 152 | YES 153 | -1.CustomClassName 154 | -1.IBPluginDependency 155 | -2.CustomClassName 156 | -2.IBPluginDependency 157 | 16.IBPluginDependency 158 | 6.IBPluginDependency 159 | 160 | 161 | YES 162 | ConnectTestViewController 163 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 164 | UIResponder 165 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 166 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 167 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 168 | 169 | 170 | 171 | YES 172 | 173 | 174 | 175 | 176 | 177 | YES 178 | 179 | 180 | 181 | 182 | 17 183 | 184 | 185 | 186 | YES 187 | 188 | ConnectTestViewController 189 | UIViewController 190 | 191 | label 192 | UILabel 193 | 194 | 195 | label 196 | 197 | label 198 | UILabel 199 | 200 | 201 | 202 | IBProjectSource 203 | ./Classes/ConnectTestViewController.h 204 | 205 | 206 | 207 | 208 | 0 209 | IBCocoaTouchFramework 210 | 211 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 212 | 213 | 214 | YES 215 | 3 216 | 1875 217 | 218 | 219 | -------------------------------------------------------------------------------- /vendor/DDFileLogger.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "DDLog.h" 3 | 4 | @class DDLogFileInfo; 5 | 6 | /** 7 | * Welcome to Cocoa Lumberjack! 8 | * 9 | * The project page has a wealth of documentation if you have any questions. 10 | * https://github.com/robbiehanson/CocoaLumberjack 11 | * 12 | * If you're new to the project you may wish to read the "Getting Started" wiki. 13 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 14 | * 15 | * 16 | * This class provides a logger to write log statements to a file. 17 | **/ 18 | 19 | 20 | // Default configuration and safety/sanity values. 21 | // 22 | // maximumFileSize -> DEFAULT_LOG_MAX_FILE_SIZE 23 | // rollingFrequency -> DEFAULT_LOG_ROLLING_FREQUENCY 24 | // maximumNumberOfLogFiles -> DEFAULT_LOG_MAX_NUM_LOG_FILES 25 | // 26 | // You should carefully consider the proper configuration values for your application. 27 | 28 | #define DEFAULT_LOG_MAX_FILE_SIZE (1024 * 1024) // 1 MB 29 | #define DEFAULT_LOG_ROLLING_FREQUENCY (60 * 60 * 24) // 24 Hours 30 | #define DEFAULT_LOG_MAX_NUM_LOG_FILES (5) // 5 Files 31 | 32 | 33 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | #pragma mark - 35 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | 37 | // The LogFileManager protocol is designed to allow you to control all aspects of your log files. 38 | // 39 | // The primary purpose of this is to allow you to do something with the log files after they have been rolled. 40 | // Perhaps you want to compress them to save disk space. 41 | // Perhaps you want to upload them to an FTP server. 42 | // Perhaps you want to run some analytics on the file. 43 | // 44 | // A default LogFileManager is, of course, provided. 45 | // The default LogFileManager simply deletes old log files according to the maximumNumberOfLogFiles property. 46 | // 47 | // This protocol provides various methods to fetch the list of log files. 48 | // 49 | // There are two variants: sorted and unsorted. 50 | // If sorting is not necessary, the unsorted variant is obviously faster. 51 | // The sorted variant will return an array sorted by when the log files were created, 52 | // with the most recently created log file at index 0, and the oldest log file at the end of the array. 53 | // 54 | // You can fetch only the log file paths (full path including name), log file names (name only), 55 | // or an array of DDLogFileInfo objects. 56 | // The DDLogFileInfo class is documented below, and provides a handy wrapper that 57 | // gives you easy access to various file attributes such as the creation date or the file size. 58 | 59 | @protocol DDLogFileManager 60 | @required 61 | 62 | // Public properties 63 | 64 | /** 65 | * The maximum number of archived log files to keep on disk. 66 | * For example, if this property is set to 3, 67 | * then the LogFileManager will only keep 3 archived log files (plus the current active log file) on disk. 68 | * Once the active log file is rolled/archived, then the oldest of the existing 3 rolled/archived log files is deleted. 69 | * 70 | * You may optionally disable deleting old/rolled/archived log files by setting this property to zero. 71 | **/ 72 | @property (readwrite, assign) NSUInteger maximumNumberOfLogFiles; 73 | 74 | // Public methods 75 | 76 | - (NSString *)logsDirectory; 77 | 78 | - (NSArray *)unsortedLogFilePaths; 79 | - (NSArray *)unsortedLogFileNames; 80 | - (NSArray *)unsortedLogFileInfos; 81 | 82 | - (NSArray *)sortedLogFilePaths; 83 | - (NSArray *)sortedLogFileNames; 84 | - (NSArray *)sortedLogFileInfos; 85 | 86 | // Private methods (only to be used by DDFileLogger) 87 | 88 | - (NSString *)createNewLogFile; 89 | 90 | @optional 91 | 92 | // Notifications from DDFileLogger 93 | 94 | - (void)didArchiveLogFile:(NSString *)logFilePath; 95 | - (void)didRollAndArchiveLogFile:(NSString *)logFilePath; 96 | 97 | @end 98 | 99 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 100 | #pragma mark - 101 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 102 | 103 | /** 104 | * Default log file manager. 105 | * 106 | * All log files are placed inside the logsDirectory. 107 | * If a specific logsDirectory isn't specified, the default directory is used. 108 | * On Mac, this is in ~/Library/Logs/. 109 | * On iPhone, this is in ~/Library/Caches/Logs. 110 | * 111 | * Log files are named "log-.txt", 112 | * where uuid is a 6 character hexadecimal consisting of the set [0123456789ABCDEF]. 113 | * 114 | * Archived log files are automatically deleted according to the maximumNumberOfLogFiles property. 115 | **/ 116 | @interface DDLogFileManagerDefault : NSObject 117 | { 118 | NSUInteger maximumNumberOfLogFiles; 119 | NSString *_logsDirectory; 120 | } 121 | 122 | - (id)init; 123 | - (id)initWithLogsDirectory:(NSString *)logsDirectory; 124 | 125 | /* Inherited from DDLogFileManager protocol: 126 | 127 | @property (readwrite, assign) NSUInteger maximumNumberOfLogFiles; 128 | 129 | - (NSString *)logsDirectory; 130 | 131 | - (NSArray *)unsortedLogFilePaths; 132 | - (NSArray *)unsortedLogFileNames; 133 | - (NSArray *)unsortedLogFileInfos; 134 | 135 | - (NSArray *)sortedLogFilePaths; 136 | - (NSArray *)sortedLogFileNames; 137 | - (NSArray *)sortedLogFileInfos; 138 | 139 | */ 140 | 141 | @end 142 | 143 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 144 | #pragma mark - 145 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 146 | 147 | /** 148 | * Most users will want file log messages to be prepended with the date and time. 149 | * Rather than forcing the majority of users to write their own formatter, 150 | * we will supply a logical default formatter. 151 | * Users can easily replace this formatter with their own by invoking the setLogFormatter method. 152 | * It can also be removed by calling setLogFormatter, and passing a nil parameter. 153 | * 154 | * In addition to the convenience of having a logical default formatter, 155 | * it will also provide a template that makes it easy for developers to copy and change. 156 | **/ 157 | @interface DDLogFileFormatterDefault : NSObject 158 | { 159 | NSDateFormatter *dateFormatter; 160 | } 161 | 162 | - (id)init; 163 | - (id)initWithDateFormatter:(NSDateFormatter *)dateFormatter; 164 | 165 | @end 166 | 167 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 168 | #pragma mark - 169 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 170 | 171 | @interface DDFileLogger : DDAbstractLogger 172 | { 173 | __strong id logFileManager; 174 | 175 | DDLogFileInfo *currentLogFileInfo; 176 | NSFileHandle *currentLogFileHandle; 177 | 178 | dispatch_source_t rollingTimer; 179 | 180 | unsigned long long maximumFileSize; 181 | NSTimeInterval rollingFrequency; 182 | } 183 | 184 | - (id)init; 185 | - (id)initWithLogFileManager:(id )logFileManager; 186 | 187 | /** 188 | * Log File Rolling: 189 | * 190 | * maximumFileSize: 191 | * The approximate maximum size to allow log files to grow. 192 | * If a log file is larger than this value after a log statement is appended, 193 | * then the log file is rolled. 194 | * 195 | * rollingFrequency 196 | * How often to roll the log file. 197 | * The frequency is given as an NSTimeInterval, which is a double that specifies the interval in seconds. 198 | * Once the log file gets to be this old, it is rolled. 199 | * 200 | * Both the maximumFileSize and the rollingFrequency are used to manage rolling. 201 | * Whichever occurs first will cause the log file to be rolled. 202 | * 203 | * For example: 204 | * The rollingFrequency is 24 hours, 205 | * but the log file surpasses the maximumFileSize after only 20 hours. 206 | * The log file will be rolled at that 20 hour mark. 207 | * A new log file will be created, and the 24 hour timer will be restarted. 208 | * 209 | * You may optionally disable rolling due to filesize by setting maximumFileSize to zero. 210 | * If you do so, rolling is based solely on rollingFrequency. 211 | * 212 | * You may optionally disable rolling due to time by setting rollingFrequency to zero (or any non-positive number). 213 | * If you do so, rolling is based solely on maximumFileSize. 214 | * 215 | * If you disable both maximumFileSize and rollingFrequency, then the log file won't ever be rolled. 216 | * This is strongly discouraged. 217 | **/ 218 | @property (readwrite, assign) unsigned long long maximumFileSize; 219 | @property (readwrite, assign) NSTimeInterval rollingFrequency; 220 | 221 | /** 222 | * The DDLogFileManager instance can be used to retrieve the list of log files, 223 | * and configure the maximum number of archived log files to keep. 224 | * 225 | * @see DDLogFileManager.maximumNumberOfLogFiles 226 | **/ 227 | @property (strong, nonatomic, readonly) id logFileManager; 228 | 229 | 230 | // You can optionally force the current log file to be rolled with this method. 231 | 232 | - (void)rollLogFile; 233 | 234 | // Inherited from DDAbstractLogger 235 | 236 | // - (id )logFormatter; 237 | // - (void)setLogFormatter:(id )formatter; 238 | 239 | @end 240 | 241 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 242 | #pragma mark - 243 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 244 | 245 | /** 246 | * DDLogFileInfo is a simple class that provides access to various file attributes. 247 | * It provides good performance as it only fetches the information if requested, 248 | * and it caches the information to prevent duplicate fetches. 249 | * 250 | * It was designed to provide quick snapshots of the current state of log files, 251 | * and to help sort log files in an array. 252 | * 253 | * This class does not monitor the files, or update it's cached attribute values if the file changes on disk. 254 | * This is not what the class was designed for. 255 | * 256 | * If you absolutely must get updated values, 257 | * you can invoke the reset method which will clear the cache. 258 | **/ 259 | @interface DDLogFileInfo : NSObject 260 | { 261 | __strong NSString *filePath; 262 | __strong NSString *fileName; 263 | 264 | __strong NSDictionary *fileAttributes; 265 | 266 | __strong NSDate *creationDate; 267 | __strong NSDate *modificationDate; 268 | 269 | unsigned long long fileSize; 270 | } 271 | 272 | @property (strong, nonatomic, readonly) NSString *filePath; 273 | @property (strong, nonatomic, readonly) NSString *fileName; 274 | 275 | @property (strong, nonatomic, readonly) NSDictionary *fileAttributes; 276 | 277 | @property (strong, nonatomic, readonly) NSDate *creationDate; 278 | @property (strong, nonatomic, readonly) NSDate *modificationDate; 279 | 280 | @property (nonatomic, readonly) unsigned long long fileSize; 281 | 282 | @property (nonatomic, readonly) NSTimeInterval age; 283 | 284 | @property (nonatomic, readwrite) BOOL isArchived; 285 | 286 | + (id)logFileWithPath:(NSString *)filePath; 287 | 288 | - (id)initWithFilePath:(NSString *)filePath; 289 | 290 | - (void)reset; 291 | - (void)renameFile:(NSString *)newFileName; 292 | 293 | #if TARGET_IPHONE_SIMULATOR 294 | 295 | // So here's the situation. 296 | // Extended attributes are perfect for what we're trying to do here (marking files as archived). 297 | // This is exactly what extended attributes were designed for. 298 | // 299 | // But Apple screws us over on the simulator. 300 | // Everytime you build-and-go, they copy the application into a new folder on the hard drive, 301 | // and as part of the process they strip extended attributes from our log files. 302 | // Normally, a copy of a file preserves extended attributes. 303 | // So obviously Apple has gone to great lengths to piss us off. 304 | // 305 | // Thus we use a slightly different tactic for marking log files as archived in the simulator. 306 | // That way it "just works" and there's no confusion when testing. 307 | // 308 | // The difference in method names is indicative of the difference in functionality. 309 | // On the simulator we add an attribute by appending a filename extension. 310 | // 311 | // For example: 312 | // log-ABC123.txt -> log-ABC123.archived.txt 313 | 314 | - (BOOL)hasExtensionAttributeWithName:(NSString *)attrName; 315 | 316 | - (void)addExtensionAttributeWithName:(NSString *)attrName; 317 | - (void)removeExtensionAttributeWithName:(NSString *)attrName; 318 | 319 | #else 320 | 321 | // Normal use of extended attributes used everywhere else, 322 | // such as on Macs and on iPhone devices. 323 | 324 | - (BOOL)hasExtendedAttributeWithName:(NSString *)attrName; 325 | 326 | - (void)addExtendedAttributeWithName:(NSString *)attrName; 327 | - (void)removeExtendedAttributeWithName:(NSString *)attrName; 328 | 329 | #endif 330 | 331 | - (NSComparisonResult)reverseCompareByCreationDate:(DDLogFileInfo *)another; 332 | - (NSComparisonResult)reverseCompareByModificationDate:(DDLogFileInfo *)another; 333 | 334 | @end 335 | -------------------------------------------------------------------------------- /ConnectTest/Reachability.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011, Tony Million. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "Reachability.h" 29 | 30 | 31 | NSString *const kReachabilityChangedNotification = @"kReachabilityChangedNotification"; 32 | 33 | @interface Reachability () 34 | 35 | @property (nonatomic, assign) SCNetworkReachabilityRef reachabilityRef; 36 | 37 | 38 | #if NEEDS_DISPATCH_RETAIN_RELEASE 39 | @property (nonatomic, assign) dispatch_queue_t reachabilitySerialQueue; 40 | #else 41 | @property (nonatomic, strong) dispatch_queue_t reachabilitySerialQueue; 42 | #endif 43 | 44 | 45 | @property (nonatomic, strong) id reachabilityObject; 46 | 47 | -(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags; 48 | -(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags; 49 | 50 | @end 51 | 52 | static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags) 53 | { 54 | return [NSString stringWithFormat:@"%c%c %c%c%c%c%c%c%c", 55 | #if TARGET_OS_IPHONE 56 | (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', 57 | #else 58 | 'X', 59 | #endif 60 | (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', 61 | (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', 62 | (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', 63 | (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', 64 | (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', 65 | (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', 66 | (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', 67 | (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-']; 68 | } 69 | 70 | // Start listening for reachability notifications on the current run loop 71 | static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) 72 | { 73 | #pragma unused (target) 74 | #if __has_feature(objc_arc) 75 | Reachability *reachability = ((__bridge Reachability*)info); 76 | #else 77 | Reachability *reachability = ((Reachability*)info); 78 | #endif 79 | 80 | // We probably don't need an autoreleasepool here, as GCD docs state each queue has its own autorelease pool, 81 | // but what the heck eh? 82 | @autoreleasepool 83 | { 84 | [reachability reachabilityChanged:flags]; 85 | } 86 | } 87 | 88 | 89 | @implementation Reachability 90 | 91 | @synthesize reachabilityRef; 92 | @synthesize reachabilitySerialQueue; 93 | 94 | @synthesize reachableOnWWAN; 95 | 96 | @synthesize reachableBlock; 97 | @synthesize unreachableBlock; 98 | 99 | @synthesize reachabilityObject; 100 | 101 | #pragma mark - Class Constructor Methods 102 | 103 | +(Reachability*)reachabilityWithHostName:(NSString*)hostname 104 | { 105 | return [Reachability reachabilityWithHostname:hostname]; 106 | } 107 | 108 | +(Reachability*)reachabilityWithHostname:(NSString*)hostname 109 | { 110 | SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]); 111 | if (ref) 112 | { 113 | id reachability = [[self alloc] initWithReachabilityRef:ref]; 114 | 115 | #if __has_feature(objc_arc) 116 | return reachability; 117 | #else 118 | return [reachability autorelease]; 119 | #endif 120 | 121 | } 122 | 123 | return nil; 124 | } 125 | 126 | +(Reachability *)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress 127 | { 128 | SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); 129 | if (ref) 130 | { 131 | id reachability = [[self alloc] initWithReachabilityRef:ref]; 132 | 133 | #if __has_feature(objc_arc) 134 | return reachability; 135 | #else 136 | return [reachability autorelease]; 137 | #endif 138 | } 139 | 140 | return nil; 141 | } 142 | 143 | +(Reachability *)reachabilityForInternetConnection 144 | { 145 | struct sockaddr_in zeroAddress; 146 | bzero(&zeroAddress, sizeof(zeroAddress)); 147 | zeroAddress.sin_len = sizeof(zeroAddress); 148 | zeroAddress.sin_family = AF_INET; 149 | 150 | return [self reachabilityWithAddress:&zeroAddress]; 151 | } 152 | 153 | +(Reachability*)reachabilityForLocalWiFi 154 | { 155 | struct sockaddr_in localWifiAddress; 156 | bzero(&localWifiAddress, sizeof(localWifiAddress)); 157 | localWifiAddress.sin_len = sizeof(localWifiAddress); 158 | localWifiAddress.sin_family = AF_INET; 159 | // IN_LINKLOCALNETNUM is defined in as 169.254.0.0 160 | localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); 161 | 162 | return [self reachabilityWithAddress:&localWifiAddress]; 163 | } 164 | 165 | 166 | // Initialization methods 167 | 168 | -(Reachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref 169 | { 170 | self = [super init]; 171 | if (self != nil) 172 | { 173 | self.reachableOnWWAN = YES; 174 | self.reachabilityRef = ref; 175 | } 176 | 177 | return self; 178 | } 179 | 180 | -(void)dealloc 181 | { 182 | [self stopNotifier]; 183 | 184 | if(self.reachabilityRef) 185 | { 186 | CFRelease(self.reachabilityRef); 187 | self.reachabilityRef = nil; 188 | } 189 | 190 | self.reachableBlock = nil; 191 | self.unreachableBlock = nil; 192 | 193 | #if !(__has_feature(objc_arc)) 194 | [super dealloc]; 195 | #endif 196 | 197 | 198 | } 199 | 200 | #pragma mark - Notifier Methods 201 | 202 | // Notifier 203 | // NOTE: This uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD 204 | // - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS. 205 | // INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want) 206 | 207 | -(BOOL)startNotifier 208 | { 209 | SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL }; 210 | 211 | // this should do a retain on ourself, so as long as we're in notifier mode we shouldn't disappear out from under ourselves 212 | // woah 213 | self.reachabilityObject = self; 214 | 215 | 216 | 217 | // First, we need to create a serial queue. 218 | // We allocate this once for the lifetime of the notifier. 219 | self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL); 220 | if(!self.reachabilitySerialQueue) 221 | { 222 | return NO; 223 | } 224 | 225 | #if __has_feature(objc_arc) 226 | context.info = (__bridge void *)self; 227 | #else 228 | context.info = (void *)self; 229 | #endif 230 | 231 | if (!SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context)) 232 | { 233 | #ifdef DEBUG 234 | NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError())); 235 | #endif 236 | 237 | // Clear out the dispatch queue 238 | if(self.reachabilitySerialQueue) 239 | { 240 | #if NEEDS_DISPATCH_RETAIN_RELEASE 241 | dispatch_release(self.reachabilitySerialQueue); 242 | #endif 243 | self.reachabilitySerialQueue = nil; 244 | } 245 | 246 | self.reachabilityObject = nil; 247 | 248 | return NO; 249 | } 250 | 251 | // Set it as our reachability queue, which will retain the queue 252 | if(!SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue)) 253 | { 254 | #ifdef DEBUG 255 | NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError())); 256 | #endif 257 | 258 | // UH OH - FAILURE! 259 | 260 | // First stop, any callbacks! 261 | SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); 262 | 263 | // Then clear out the dispatch queue. 264 | if(self.reachabilitySerialQueue) 265 | { 266 | #if NEEDS_DISPATCH_RETAIN_RELEASE 267 | dispatch_release(self.reachabilitySerialQueue); 268 | #endif 269 | self.reachabilitySerialQueue = nil; 270 | } 271 | 272 | self.reachabilityObject = nil; 273 | 274 | return NO; 275 | } 276 | 277 | return YES; 278 | } 279 | 280 | -(void)stopNotifier 281 | { 282 | // First stop, any callbacks! 283 | SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); 284 | 285 | // Unregister target from the GCD serial dispatch queue. 286 | SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL); 287 | 288 | if(self.reachabilitySerialQueue) 289 | { 290 | #if NEEDS_DISPATCH_RETAIN_RELEASE 291 | dispatch_release(self.reachabilitySerialQueue); 292 | #endif 293 | self.reachabilitySerialQueue = nil; 294 | } 295 | 296 | self.reachabilityObject = nil; 297 | } 298 | 299 | #pragma mark - reachability tests 300 | 301 | // This is for the case where you flick the airplane mode; 302 | // you end up getting something like this: 303 | //Reachability: WR ct----- 304 | //Reachability: -- ------- 305 | //Reachability: WR ct----- 306 | //Reachability: -- ------- 307 | // We treat this as 4 UNREACHABLE triggers - really apple should do better than this 308 | 309 | #define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection) 310 | 311 | -(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags 312 | { 313 | BOOL connectionUP = YES; 314 | 315 | if(!(flags & kSCNetworkReachabilityFlagsReachable)) 316 | connectionUP = NO; 317 | 318 | if( (flags & testcase) == testcase ) 319 | connectionUP = NO; 320 | 321 | #if TARGET_OS_IPHONE 322 | if(flags & kSCNetworkReachabilityFlagsIsWWAN) 323 | { 324 | // We're on 3G. 325 | if(!self.reachableOnWWAN) 326 | { 327 | // We don't want to connect when on 3G. 328 | connectionUP = NO; 329 | } 330 | } 331 | #endif 332 | 333 | return connectionUP; 334 | } 335 | 336 | -(BOOL)isReachable 337 | { 338 | SCNetworkReachabilityFlags flags; 339 | 340 | if(!SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) 341 | return NO; 342 | 343 | return [self isReachableWithFlags:flags]; 344 | } 345 | 346 | -(BOOL)isReachableViaWWAN 347 | { 348 | #if TARGET_OS_IPHONE 349 | 350 | SCNetworkReachabilityFlags flags = 0; 351 | 352 | if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 353 | { 354 | // Check we're REACHABLE 355 | if(flags & kSCNetworkReachabilityFlagsReachable) 356 | { 357 | // Now, check we're on WWAN 358 | if(flags & kSCNetworkReachabilityFlagsIsWWAN) 359 | { 360 | return YES; 361 | } 362 | } 363 | } 364 | #endif 365 | 366 | return NO; 367 | } 368 | 369 | -(BOOL)isReachableViaWiFi 370 | { 371 | SCNetworkReachabilityFlags flags = 0; 372 | 373 | if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 374 | { 375 | // Check we're reachable 376 | if((flags & kSCNetworkReachabilityFlagsReachable)) 377 | { 378 | #if TARGET_OS_IPHONE 379 | // Check we're NOT on WWAN 380 | if((flags & kSCNetworkReachabilityFlagsIsWWAN)) 381 | { 382 | return NO; 383 | } 384 | #endif 385 | return YES; 386 | } 387 | } 388 | 389 | return NO; 390 | } 391 | 392 | 393 | // WWAN may be available, but not active until a connection has been established. 394 | // WiFi may require a connection for VPN on Demand. 395 | -(BOOL)isConnectionRequired 396 | { 397 | return [self connectionRequired]; 398 | } 399 | 400 | -(BOOL)connectionRequired 401 | { 402 | SCNetworkReachabilityFlags flags; 403 | 404 | if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 405 | { 406 | return (flags & kSCNetworkReachabilityFlagsConnectionRequired); 407 | } 408 | 409 | return NO; 410 | } 411 | 412 | // Dynamic, on demand connection? 413 | -(BOOL)isConnectionOnDemand 414 | { 415 | SCNetworkReachabilityFlags flags; 416 | 417 | if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 418 | { 419 | return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && 420 | (flags & (kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand))); 421 | } 422 | 423 | return NO; 424 | } 425 | 426 | // Is user intervention required? 427 | -(BOOL)isInterventionRequired 428 | { 429 | SCNetworkReachabilityFlags flags; 430 | 431 | if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 432 | { 433 | return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && 434 | (flags & kSCNetworkReachabilityFlagsInterventionRequired)); 435 | } 436 | 437 | return NO; 438 | } 439 | 440 | 441 | #pragma mark - reachability status stuff 442 | 443 | -(NetworkStatus)currentReachabilityStatus 444 | { 445 | if([self isReachable]) 446 | { 447 | if([self isReachableViaWiFi]) 448 | return ReachableViaWiFi; 449 | 450 | #if TARGET_OS_IPHONE 451 | return ReachableViaWWAN; 452 | #endif 453 | } 454 | 455 | return NotReachable; 456 | } 457 | 458 | -(SCNetworkReachabilityFlags)reachabilityFlags 459 | { 460 | SCNetworkReachabilityFlags flags = 0; 461 | 462 | if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 463 | { 464 | return flags; 465 | } 466 | 467 | return 0; 468 | } 469 | 470 | -(NSString*)currentReachabilityString 471 | { 472 | NetworkStatus temp = [self currentReachabilityStatus]; 473 | 474 | if(temp == reachableOnWWAN) 475 | { 476 | // Updated for the fact that we have CDMA phones now! 477 | return NSLocalizedString(@"Cellular", @""); 478 | } 479 | if (temp == ReachableViaWiFi) 480 | { 481 | return NSLocalizedString(@"WiFi", @""); 482 | } 483 | 484 | return NSLocalizedString(@"No Connection", @""); 485 | } 486 | 487 | -(NSString*)currentReachabilityFlags 488 | { 489 | return reachabilityFlags([self reachabilityFlags]); 490 | } 491 | 492 | #pragma mark - Callback function calls this method 493 | 494 | -(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags 495 | { 496 | if([self isReachableWithFlags:flags]) 497 | { 498 | if(self.reachableBlock) 499 | { 500 | self.reachableBlock(self); 501 | } 502 | } 503 | else 504 | { 505 | if(self.unreachableBlock) 506 | { 507 | self.unreachableBlock(self); 508 | } 509 | } 510 | 511 | // this makes sure the change notification happens on the MAIN THREAD 512 | dispatch_async(dispatch_get_main_queue(), ^{ 513 | [[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification 514 | object:self]; 515 | }); 516 | } 517 | 518 | #pragma mark - Debug Description 519 | 520 | - (NSString *) description; 521 | { 522 | NSString *description = [NSString stringWithFormat:@"<%@: %#x>", 523 | NSStringFromClass([self class]), (unsigned int) self]; 524 | return description; 525 | } 526 | 527 | @end 528 | -------------------------------------------------------------------------------- /ConnectTest.xcodeproj/xcuserdata/smalltask.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 18 | 19 | 31 | 32 | 44 | 45 | 57 | 58 | 70 | 71 | 83 | 84 | 96 | 97 | 109 | 110 | 122 | 123 | 135 | 136 | 148 | 149 | 161 | 162 | 174 | 175 | 187 | 188 | 200 | 201 | 213 | 214 | 226 | 227 | 239 | 240 | 252 | 253 | 265 | 266 | 278 | 279 | 291 | 292 | 304 | 305 | 317 | 318 | 330 | 331 | 343 | 344 | 356 | 357 | 369 | 370 | 382 | 383 | 395 | 396 | 408 | 409 | 421 | 422 | 423 | 424 | -------------------------------------------------------------------------------- /vendor/DDAbstractDatabaseLogger.m: -------------------------------------------------------------------------------- 1 | #import "DDAbstractDatabaseLogger.h" 2 | #import 3 | 4 | /** 5 | * Welcome to Cocoa Lumberjack! 6 | * 7 | * The project page has a wealth of documentation if you have any questions. 8 | * https://github.com/robbiehanson/CocoaLumberjack 9 | * 10 | * If you're new to the project you may wish to read the "Getting Started" wiki. 11 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 12 | **/ 13 | 14 | #if ! __has_feature(objc_arc) 15 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 16 | #endif 17 | 18 | /** 19 | * Does ARC support support GCD objects? 20 | * It does if the minimum deployment target is iOS 6+ or Mac OS X 8+ 21 | **/ 22 | #if TARGET_OS_IPHONE 23 | 24 | // Compiling for iOS 25 | 26 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 // iOS 6.0 or later 27 | #define NEEDS_DISPATCH_RETAIN_RELEASE 0 28 | #else // iOS 5.X or earlier 29 | #define NEEDS_DISPATCH_RETAIN_RELEASE 1 30 | #endif 31 | 32 | #else 33 | 34 | // Compiling for Mac OS X 35 | 36 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 // Mac OS X 10.8 or later 37 | #define NEEDS_DISPATCH_RETAIN_RELEASE 0 38 | #else 39 | #define NEEDS_DISPATCH_RETAIN_RELEASE 1 // Mac OS X 10.7 or earlier 40 | #endif 41 | 42 | #endif 43 | 44 | @interface DDAbstractDatabaseLogger () 45 | - (void)destroySaveTimer; 46 | - (void)destroyDeleteTimer; 47 | @end 48 | 49 | #pragma mark - 50 | 51 | @implementation DDAbstractDatabaseLogger 52 | 53 | - (id)init 54 | { 55 | if ((self = [super init])) 56 | { 57 | saveThreshold = 500; 58 | saveInterval = 60; // 60 seconds 59 | maxAge = (60 * 60 * 24 * 7); // 7 days 60 | deleteInterval = (60 * 5); // 5 minutes 61 | } 62 | return self; 63 | } 64 | 65 | - (void)dealloc 66 | { 67 | [self destroySaveTimer]; 68 | [self destroyDeleteTimer]; 69 | 70 | } 71 | 72 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 73 | #pragma mark Override Me 74 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 75 | 76 | - (BOOL)db_log:(DDLogMessage *)logMessage 77 | { 78 | // Override me and add your implementation. 79 | // 80 | // Return YES if an item was added to the buffer. 81 | // Return NO if the logMessage was ignored. 82 | 83 | return NO; 84 | } 85 | 86 | - (void)db_save 87 | { 88 | // Override me and add your implementation. 89 | } 90 | 91 | - (void)db_delete 92 | { 93 | // Override me and add your implementation. 94 | } 95 | 96 | - (void)db_saveAndDelete 97 | { 98 | // Override me and add your implementation. 99 | } 100 | 101 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 102 | #pragma mark Private API 103 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 104 | 105 | - (void)performSaveAndSuspendSaveTimer 106 | { 107 | if (unsavedCount > 0) 108 | { 109 | if (deleteOnEverySave) 110 | [self db_saveAndDelete]; 111 | else 112 | [self db_save]; 113 | } 114 | 115 | unsavedCount = 0; 116 | unsavedTime = 0; 117 | 118 | if (saveTimer && !saveTimerSuspended) 119 | { 120 | dispatch_suspend(saveTimer); 121 | saveTimerSuspended = YES; 122 | } 123 | } 124 | 125 | - (void)performDelete 126 | { 127 | if (maxAge > 0.0) 128 | { 129 | [self db_delete]; 130 | 131 | lastDeleteTime = dispatch_time(DISPATCH_TIME_NOW, 0); 132 | } 133 | } 134 | 135 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 136 | #pragma mark Timers 137 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 138 | 139 | - (void)destroySaveTimer 140 | { 141 | if (saveTimer) 142 | { 143 | dispatch_source_cancel(saveTimer); 144 | if (saveTimerSuspended) 145 | { 146 | // Must resume a timer before releasing it (or it will crash) 147 | dispatch_resume(saveTimer); 148 | saveTimerSuspended = NO; 149 | } 150 | #if NEEDS_DISPATCH_RETAIN_RELEASE 151 | dispatch_release(saveTimer); 152 | #endif 153 | saveTimer = NULL; 154 | } 155 | } 156 | 157 | - (void)updateAndResumeSaveTimer 158 | { 159 | if ((saveTimer != NULL) && (saveInterval > 0.0) && (unsavedTime > 0.0)) 160 | { 161 | uint64_t interval = saveInterval * NSEC_PER_SEC; 162 | dispatch_time_t startTime = dispatch_time(unsavedTime, interval); 163 | 164 | dispatch_source_set_timer(saveTimer, startTime, interval, 1.0); 165 | 166 | if (saveTimerSuspended) 167 | { 168 | dispatch_resume(saveTimer); 169 | saveTimerSuspended = NO; 170 | } 171 | } 172 | } 173 | 174 | - (void)createSuspendedSaveTimer 175 | { 176 | if ((saveTimer == NULL) && (saveInterval > 0.0)) 177 | { 178 | saveTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, loggerQueue); 179 | 180 | dispatch_source_set_event_handler(saveTimer, ^{ @autoreleasepool { 181 | 182 | [self performSaveAndSuspendSaveTimer]; 183 | 184 | }}); 185 | 186 | saveTimerSuspended = YES; 187 | } 188 | } 189 | 190 | - (void)destroyDeleteTimer 191 | { 192 | if (deleteTimer) 193 | { 194 | dispatch_source_cancel(deleteTimer); 195 | #if NEEDS_DISPATCH_RETAIN_RELEASE 196 | dispatch_release(deleteTimer); 197 | #endif 198 | deleteTimer = NULL; 199 | } 200 | } 201 | 202 | - (void)updateDeleteTimer 203 | { 204 | if ((deleteTimer != NULL) && (deleteInterval > 0.0) && (maxAge > 0.0)) 205 | { 206 | uint64_t interval = deleteInterval * NSEC_PER_SEC; 207 | dispatch_time_t startTime; 208 | 209 | if (lastDeleteTime > 0) 210 | startTime = dispatch_time(lastDeleteTime, interval); 211 | else 212 | startTime = dispatch_time(DISPATCH_TIME_NOW, interval); 213 | 214 | dispatch_source_set_timer(deleteTimer, startTime, interval, 1.0); 215 | } 216 | } 217 | 218 | - (void)createAndStartDeleteTimer 219 | { 220 | if ((deleteTimer == NULL) && (deleteInterval > 0.0) && (maxAge > 0.0)) 221 | { 222 | deleteTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, loggerQueue); 223 | 224 | dispatch_source_set_event_handler(deleteTimer, ^{ @autoreleasepool { 225 | 226 | [self performDelete]; 227 | 228 | }}); 229 | 230 | [self updateDeleteTimer]; 231 | 232 | dispatch_resume(deleteTimer); 233 | } 234 | } 235 | 236 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 237 | #pragma mark Configuration 238 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 239 | 240 | - (NSUInteger)saveThreshold 241 | { 242 | if (dispatch_get_current_queue() == loggerQueue) 243 | { 244 | return saveThreshold; 245 | } 246 | else 247 | { 248 | __block NSUInteger result; 249 | 250 | dispatch_sync(loggerQueue, ^{ 251 | result = saveThreshold; 252 | }); 253 | 254 | return result; 255 | } 256 | } 257 | 258 | - (void)setSaveThreshold:(NSUInteger)threshold 259 | { 260 | dispatch_block_t block = ^{ 261 | 262 | if (saveThreshold != threshold) 263 | { 264 | saveThreshold = threshold; 265 | 266 | // Since the saveThreshold has changed, 267 | // we check to see if the current unsavedCount has surpassed the new threshold. 268 | // 269 | // If it has, we immediately save the log. 270 | 271 | if ((unsavedCount >= saveThreshold) && (saveThreshold > 0)) 272 | { 273 | @autoreleasepool { 274 | 275 | [self performSaveAndSuspendSaveTimer]; 276 | 277 | } 278 | } 279 | } 280 | }; 281 | 282 | if (dispatch_get_current_queue() == loggerQueue) 283 | block(); 284 | else 285 | dispatch_async(loggerQueue, block); 286 | } 287 | 288 | - (NSTimeInterval)saveInterval 289 | { 290 | if (dispatch_get_current_queue() == loggerQueue) 291 | { 292 | return saveInterval; 293 | } 294 | else 295 | { 296 | __block NSTimeInterval result; 297 | 298 | dispatch_sync(loggerQueue, ^{ 299 | result = saveInterval; 300 | }); 301 | 302 | return result; 303 | } 304 | } 305 | 306 | - (void)setSaveInterval:(NSTimeInterval)interval 307 | { 308 | dispatch_block_t block = ^{ 309 | 310 | // C99 recommended floating point comparison macro 311 | // Read: isLessThanOrGreaterThan(floatA, floatB) 312 | 313 | if (/* saveInterval != interval */ islessgreater(saveInterval, interval)) 314 | { 315 | saveInterval = interval; 316 | 317 | // There are several cases we need to handle here. 318 | // 319 | // 1. If the saveInterval was previously enabled and it just got disabled, 320 | // then we need to stop the saveTimer. (And we might as well release it.) 321 | // 322 | // 2. If the saveInterval was previously disabled and it just got enabled, 323 | // then we need to setup the saveTimer. (Plus we might need to do an immediate save.) 324 | // 325 | // 3. If the saveInterval increased, then we need to reset the timer so that it fires at the later date. 326 | // 327 | // 4. If the saveInterval decreased, then we need to reset the timer so that it fires at an earlier date. 328 | // (Plus we might need to do an immediate save.) 329 | 330 | if (saveInterval > 0.0) 331 | { 332 | @autoreleasepool 333 | { 334 | if (saveTimer == NULL) 335 | { 336 | // Handles #2 337 | // 338 | // Since the saveTimer uses the unsavedTime to calculate it's first fireDate, 339 | // if a save is needed the timer will fire immediately. 340 | 341 | [self createSuspendedSaveTimer]; 342 | [self updateAndResumeSaveTimer]; 343 | } 344 | else 345 | { 346 | // Handles #3 347 | // Handles #4 348 | // 349 | // Since the saveTimer uses the unsavedTime to calculate it's first fireDate, 350 | // if a save is needed the timer will fire immediately. 351 | 352 | [self updateAndResumeSaveTimer]; 353 | } 354 | } 355 | } 356 | else if (saveTimer) 357 | { 358 | // Handles #1 359 | 360 | [self destroySaveTimer]; 361 | } 362 | } 363 | }; 364 | 365 | if (dispatch_get_current_queue() == loggerQueue) 366 | block(); 367 | else 368 | dispatch_async(loggerQueue, block); 369 | } 370 | 371 | - (NSTimeInterval)maxAge 372 | { 373 | if (dispatch_get_current_queue() == loggerQueue) 374 | { 375 | return maxAge; 376 | } 377 | else 378 | { 379 | __block NSTimeInterval result; 380 | 381 | dispatch_sync(loggerQueue, ^{ 382 | result = maxAge; 383 | }); 384 | 385 | return result; 386 | } 387 | } 388 | 389 | - (void)setMaxAge:(NSTimeInterval)interval 390 | { 391 | dispatch_block_t block = ^{ 392 | 393 | // C99 recommended floating point comparison macro 394 | // Read: isLessThanOrGreaterThan(floatA, floatB) 395 | 396 | if (/* maxAge != interval */ islessgreater(maxAge, interval)) 397 | { 398 | NSTimeInterval oldMaxAge = maxAge; 399 | NSTimeInterval newMaxAge = interval; 400 | 401 | maxAge = interval; 402 | 403 | // There are several cases we need to handle here. 404 | // 405 | // 1. If the maxAge was previously enabled and it just got disabled, 406 | // then we need to stop the deleteTimer. (And we might as well release it.) 407 | // 408 | // 2. If the maxAge was previously disabled and it just got enabled, 409 | // then we need to setup the deleteTimer. (Plus we might need to do an immediate delete.) 410 | // 411 | // 3. If the maxAge was increased, 412 | // then we don't need to do anything. 413 | // 414 | // 4. If the maxAge was decreased, 415 | // then we should do an immediate delete. 416 | 417 | BOOL shouldDeleteNow = NO; 418 | 419 | if (oldMaxAge > 0.0) 420 | { 421 | if (newMaxAge <= 0.0) 422 | { 423 | // Handles #1 424 | 425 | [self destroyDeleteTimer]; 426 | } 427 | else if (oldMaxAge > newMaxAge) 428 | { 429 | // Handles #4 430 | shouldDeleteNow = YES; 431 | } 432 | } 433 | else if (newMaxAge > 0.0) 434 | { 435 | // Handles #2 436 | shouldDeleteNow = YES; 437 | } 438 | 439 | if (shouldDeleteNow) 440 | { 441 | @autoreleasepool 442 | { 443 | [self performDelete]; 444 | 445 | if (deleteTimer) 446 | [self updateDeleteTimer]; 447 | else 448 | [self createAndStartDeleteTimer]; 449 | } 450 | } 451 | } 452 | }; 453 | 454 | if (dispatch_get_current_queue() == loggerQueue) 455 | block(); 456 | else 457 | dispatch_async(loggerQueue, block); 458 | } 459 | 460 | - (NSTimeInterval)deleteInterval 461 | { 462 | if (dispatch_get_current_queue() == loggerQueue) 463 | { 464 | return deleteInterval; 465 | } 466 | else 467 | { 468 | __block NSTimeInterval result; 469 | 470 | dispatch_sync(loggerQueue, ^{ 471 | result = deleteInterval; 472 | }); 473 | 474 | return result; 475 | } 476 | } 477 | 478 | - (void)setDeleteInterval:(NSTimeInterval)interval 479 | { 480 | dispatch_block_t block = ^{ 481 | 482 | // C99 recommended floating point comparison macro 483 | // Read: isLessThanOrGreaterThan(floatA, floatB) 484 | 485 | if (/* deleteInterval != interval */ islessgreater(deleteInterval, interval)) 486 | { 487 | deleteInterval = interval; 488 | 489 | // There are several cases we need to handle here. 490 | // 491 | // 1. If the deleteInterval was previously enabled and it just got disabled, 492 | // then we need to stop the deleteTimer. (And we might as well release it.) 493 | // 494 | // 2. If the deleteInterval was previously disabled and it just got enabled, 495 | // then we need to setup the deleteTimer. (Plus we might need to do an immediate delete.) 496 | // 497 | // 3. If the deleteInterval increased, then we need to reset the timer so that it fires at the later date. 498 | // 499 | // 4. If the deleteInterval decreased, then we need to reset the timer so that it fires at an earlier date. 500 | // (Plus we might need to do an immediate delete.) 501 | 502 | if (deleteInterval > 0.0) 503 | { 504 | @autoreleasepool 505 | { 506 | if (deleteTimer == NULL) 507 | { 508 | // Handles #2 509 | // 510 | // Since the deleteTimer uses the lastDeleteTime to calculate it's first fireDate, 511 | // if a delete is needed the timer will fire immediately. 512 | 513 | [self createAndStartDeleteTimer]; 514 | } 515 | else 516 | { 517 | // Handles #3 518 | // Handles #4 519 | // 520 | // Since the deleteTimer uses the lastDeleteTime to calculate it's first fireDate, 521 | // if a save is needed the timer will fire immediately. 522 | 523 | [self updateDeleteTimer]; 524 | } 525 | } 526 | } 527 | else if (deleteTimer) 528 | { 529 | // Handles #1 530 | 531 | [self destroyDeleteTimer]; 532 | } 533 | } 534 | }; 535 | 536 | if (dispatch_get_current_queue() == loggerQueue) 537 | block(); 538 | else 539 | dispatch_async(loggerQueue, block); 540 | } 541 | 542 | - (BOOL)deleteOnEverySave 543 | { 544 | if (dispatch_get_current_queue() == loggerQueue) 545 | { 546 | return deleteOnEverySave; 547 | } 548 | else 549 | { 550 | __block BOOL result; 551 | 552 | dispatch_sync(loggerQueue, ^{ 553 | result = deleteOnEverySave; 554 | }); 555 | 556 | return result; 557 | } 558 | } 559 | 560 | - (void)setDeleteOnEverySave:(BOOL)flag 561 | { 562 | dispatch_block_t block = ^{ 563 | 564 | deleteOnEverySave = flag; 565 | }; 566 | 567 | if (dispatch_get_current_queue() == loggerQueue) 568 | block(); 569 | else 570 | dispatch_async(loggerQueue, block); 571 | } 572 | 573 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 574 | #pragma mark Public API 575 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 576 | 577 | - (void)savePendingLogEntries 578 | { 579 | dispatch_block_t block = ^{ @autoreleasepool { 580 | 581 | [self performSaveAndSuspendSaveTimer]; 582 | }}; 583 | 584 | if (dispatch_get_current_queue() == loggerQueue) 585 | block(); 586 | else 587 | dispatch_async(loggerQueue, block); 588 | } 589 | 590 | - (void)deleteOldLogEntries 591 | { 592 | dispatch_block_t block = ^{ @autoreleasepool { 593 | 594 | [self performDelete]; 595 | }}; 596 | 597 | if (dispatch_get_current_queue() == loggerQueue) 598 | block(); 599 | else 600 | dispatch_async(loggerQueue, block); 601 | } 602 | 603 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 604 | #pragma mark DDLogger 605 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 606 | 607 | - (void)didAddLogger 608 | { 609 | // If you override me be sure to invoke [super didAddLogger]; 610 | 611 | [self createSuspendedSaveTimer]; 612 | 613 | [self createAndStartDeleteTimer]; 614 | } 615 | 616 | - (void)willRemoveLogger 617 | { 618 | // If you override me be sure to invoke [super willRemoveLogger]; 619 | 620 | [self performSaveAndSuspendSaveTimer]; 621 | 622 | [self destroySaveTimer]; 623 | [self destroyDeleteTimer]; 624 | } 625 | 626 | - (void)logMessage:(DDLogMessage *)logMessage 627 | { 628 | if ([self db_log:logMessage]) 629 | { 630 | BOOL firstUnsavedEntry = (++unsavedCount == 1); 631 | 632 | if ((unsavedCount >= saveThreshold) && (saveThreshold > 0)) 633 | { 634 | [self performSaveAndSuspendSaveTimer]; 635 | } 636 | else if (firstUnsavedEntry) 637 | { 638 | unsavedTime = dispatch_time(DISPATCH_TIME_NOW, 0); 639 | [self updateAndResumeSaveTimer]; 640 | } 641 | } 642 | } 643 | 644 | - (void)flush 645 | { 646 | // This method is invoked by DDLog's flushLog method. 647 | // 648 | // It is called automatically when the application quits, 649 | // or if the developer invokes DDLog's flushLog method prior to crashing or something. 650 | 651 | [self performSaveAndSuspendSaveTimer]; 652 | } 653 | 654 | @end 655 | -------------------------------------------------------------------------------- /en.lproj/MainWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1024 5 | 10D571 6 | 786 7 | 1038.29 8 | 460.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 112 12 | 13 | 14 | YES 15 | 16 | 17 | 18 | YES 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | YES 23 | 24 | YES 25 | 26 | 27 | YES 28 | 29 | 30 | 31 | YES 32 | 33 | IBFilesOwner 34 | IBCocoaTouchFramework 35 | 36 | 37 | IBFirstResponder 38 | IBCocoaTouchFramework 39 | 40 | 41 | IBCocoaTouchFramework 42 | 43 | 44 | ConnectTestViewController 45 | 46 | 47 | 1 48 | 49 | IBCocoaTouchFramework 50 | NO 51 | 52 | 53 | 54 | 292 55 | {320, 480} 56 | 57 | 1 58 | MSAxIDEAA 59 | 60 | NO 61 | NO 62 | 63 | IBCocoaTouchFramework 64 | YES 65 | 66 | 67 | 68 | 69 | YES 70 | 71 | 72 | delegate 73 | 74 | 75 | 76 | 4 77 | 78 | 79 | 80 | viewController 81 | 82 | 83 | 84 | 11 85 | 86 | 87 | 88 | window 89 | 90 | 91 | 92 | 14 93 | 94 | 95 | 96 | 97 | YES 98 | 99 | 0 100 | 101 | 102 | 103 | 104 | 105 | -1 106 | 107 | 108 | File's Owner 109 | 110 | 111 | 3 112 | 113 | 114 | ConnectTest App Delegate 115 | 116 | 117 | -2 118 | 119 | 120 | 121 | 122 | 10 123 | 124 | 125 | 126 | 127 | 12 128 | 129 | 130 | 131 | 132 | 133 | 134 | YES 135 | 136 | YES 137 | -1.CustomClassName 138 | -2.CustomClassName 139 | 10.CustomClassName 140 | 10.IBEditorWindowLastContentRect 141 | 10.IBPluginDependency 142 | 12.IBEditorWindowLastContentRect 143 | 12.IBPluginDependency 144 | 3.CustomClassName 145 | 3.IBPluginDependency 146 | 147 | 148 | YES 149 | UIApplication 150 | UIResponder 151 | ConnectTestViewController 152 | {{234, 376}, {320, 480}} 153 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 154 | {{525, 346}, {320, 480}} 155 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 156 | ConnectTestAppDelegate 157 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 158 | 159 | 160 | 161 | YES 162 | 163 | 164 | YES 165 | 166 | 167 | 168 | 169 | YES 170 | 171 | 172 | YES 173 | 174 | 175 | 176 | 15 177 | 178 | 179 | 180 | YES 181 | 182 | UIWindow 183 | UIView 184 | 185 | IBUserSource 186 | 187 | 188 | 189 | 190 | ConnectTestAppDelegate 191 | NSObject 192 | 193 | YES 194 | 195 | YES 196 | viewController 197 | window 198 | 199 | 200 | YES 201 | ConnectTestViewController 202 | UIWindow 203 | 204 | 205 | 206 | YES 207 | 208 | YES 209 | viewController 210 | window 211 | 212 | 213 | YES 214 | 215 | viewController 216 | ConnectTestViewController 217 | 218 | 219 | window 220 | UIWindow 221 | 222 | 223 | 224 | 225 | IBProjectSource 226 | ConnectTestAppDelegate.h 227 | 228 | 229 | 230 | ConnectTestAppDelegate 231 | NSObject 232 | 233 | IBUserSource 234 | 235 | 236 | 237 | 238 | ConnectTestViewController 239 | UIViewController 240 | 241 | IBProjectSource 242 | ConnectTestViewController.h 243 | 244 | 245 | 246 | 247 | YES 248 | 249 | NSObject 250 | 251 | IBFrameworkSource 252 | Foundation.framework/Headers/NSError.h 253 | 254 | 255 | 256 | NSObject 257 | 258 | IBFrameworkSource 259 | Foundation.framework/Headers/NSFileManager.h 260 | 261 | 262 | 263 | NSObject 264 | 265 | IBFrameworkSource 266 | Foundation.framework/Headers/NSKeyValueCoding.h 267 | 268 | 269 | 270 | NSObject 271 | 272 | IBFrameworkSource 273 | Foundation.framework/Headers/NSKeyValueObserving.h 274 | 275 | 276 | 277 | NSObject 278 | 279 | IBFrameworkSource 280 | Foundation.framework/Headers/NSKeyedArchiver.h 281 | 282 | 283 | 284 | NSObject 285 | 286 | IBFrameworkSource 287 | Foundation.framework/Headers/NSObject.h 288 | 289 | 290 | 291 | NSObject 292 | 293 | IBFrameworkSource 294 | Foundation.framework/Headers/NSRunLoop.h 295 | 296 | 297 | 298 | NSObject 299 | 300 | IBFrameworkSource 301 | Foundation.framework/Headers/NSThread.h 302 | 303 | 304 | 305 | NSObject 306 | 307 | IBFrameworkSource 308 | Foundation.framework/Headers/NSURL.h 309 | 310 | 311 | 312 | NSObject 313 | 314 | IBFrameworkSource 315 | Foundation.framework/Headers/NSURLConnection.h 316 | 317 | 318 | 319 | NSObject 320 | 321 | IBFrameworkSource 322 | UIKit.framework/Headers/UIAccessibility.h 323 | 324 | 325 | 326 | NSObject 327 | 328 | IBFrameworkSource 329 | UIKit.framework/Headers/UINibLoading.h 330 | 331 | 332 | 333 | NSObject 334 | 335 | IBFrameworkSource 336 | UIKit.framework/Headers/UIResponder.h 337 | 338 | 339 | 340 | UIApplication 341 | UIResponder 342 | 343 | IBFrameworkSource 344 | UIKit.framework/Headers/UIApplication.h 345 | 346 | 347 | 348 | UIResponder 349 | NSObject 350 | 351 | 352 | 353 | UISearchBar 354 | UIView 355 | 356 | IBFrameworkSource 357 | UIKit.framework/Headers/UISearchBar.h 358 | 359 | 360 | 361 | UISearchDisplayController 362 | NSObject 363 | 364 | IBFrameworkSource 365 | UIKit.framework/Headers/UISearchDisplayController.h 366 | 367 | 368 | 369 | UIView 370 | 371 | IBFrameworkSource 372 | UIKit.framework/Headers/UITextField.h 373 | 374 | 375 | 376 | UIView 377 | UIResponder 378 | 379 | IBFrameworkSource 380 | UIKit.framework/Headers/UIView.h 381 | 382 | 383 | 384 | UIViewController 385 | 386 | IBFrameworkSource 387 | UIKit.framework/Headers/UINavigationController.h 388 | 389 | 390 | 391 | UIViewController 392 | 393 | IBFrameworkSource 394 | UIKit.framework/Headers/UIPopoverController.h 395 | 396 | 397 | 398 | UIViewController 399 | 400 | IBFrameworkSource 401 | UIKit.framework/Headers/UISplitViewController.h 402 | 403 | 404 | 405 | UIViewController 406 | 407 | IBFrameworkSource 408 | UIKit.framework/Headers/UITabBarController.h 409 | 410 | 411 | 412 | UIViewController 413 | UIResponder 414 | 415 | IBFrameworkSource 416 | UIKit.framework/Headers/UIViewController.h 417 | 418 | 419 | 420 | UIWindow 421 | UIView 422 | 423 | IBFrameworkSource 424 | UIKit.framework/Headers/UIWindow.h 425 | 426 | 427 | 428 | 429 | 0 430 | IBCocoaTouchFramework 431 | 432 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 433 | 434 | 435 | 436 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 437 | 438 | 439 | YES 440 | ConnectTest.xcodeproj 441 | 3 442 | 112 443 | 444 | 445 | -------------------------------------------------------------------------------- /vendor/DDLog.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | * Welcome to Cocoa Lumberjack! 5 | * 6 | * The project page has a wealth of documentation if you have any questions. 7 | * https://github.com/robbiehanson/CocoaLumberjack 8 | * 9 | * If you're new to the project you may wish to read the "Getting Started" wiki. 10 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted 11 | * 12 | * Otherwise, here is a quick refresher. 13 | * There are three steps to using the macros: 14 | * 15 | * Step 1: 16 | * Import the header in your implementation file: 17 | * 18 | * #import "DDLog.h" 19 | * 20 | * Step 2: 21 | * Define your logging level in your implementation file: 22 | * 23 | * // Log levels: off, error, warn, info, verbose 24 | * static const int ddLogLevel = LOG_LEVEL_VERBOSE; 25 | * 26 | * Step 3: 27 | * Replace your NSLog statements with DDLog statements according to the severity of the message. 28 | * 29 | * NSLog(@"Fatal error, no dohickey found!"); -> DDLogError(@"Fatal error, no dohickey found!"); 30 | * 31 | * DDLog works exactly the same as NSLog. 32 | * This means you can pass it multiple variables just like NSLog. 33 | **/ 34 | 35 | 36 | @class DDLogMessage; 37 | 38 | @protocol DDLogger; 39 | @protocol DDLogFormatter; 40 | 41 | /** 42 | * This is the single macro that all other macros below compile into. 43 | * This big multiline macro makes all the other macros easier to read. 44 | **/ 45 | 46 | #define LOG_MACRO(isAsynchronous, lvl, flg, ctx, atag, fnct, frmt, ...) \ 47 | [DDLog log:isAsynchronous \ 48 | level:lvl \ 49 | flag:flg \ 50 | context:ctx \ 51 | file:__FILE__ \ 52 | function:fnct \ 53 | line:__LINE__ \ 54 | tag:atag \ 55 | format:(frmt), ##__VA_ARGS__] 56 | 57 | /** 58 | * Define the Objective-C and C versions of the macro. 59 | * These automatically inject the proper function name for either an objective-c method or c function. 60 | * 61 | * We also define shorthand versions for asynchronous and synchronous logging. 62 | **/ 63 | 64 | #define LOG_OBJC_MACRO(async, lvl, flg, ctx, frmt, ...) \ 65 | LOG_MACRO(async, lvl, flg, ctx, nil, sel_getName(_cmd), frmt, ##__VA_ARGS__) 66 | 67 | #define LOG_C_MACRO(async, lvl, flg, ctx, frmt, ...) \ 68 | LOG_MACRO(async, lvl, flg, ctx, nil, __FUNCTION__, frmt, ##__VA_ARGS__) 69 | 70 | #define SYNC_LOG_OBJC_MACRO(lvl, flg, ctx, frmt, ...) \ 71 | LOG_OBJC_MACRO( NO, lvl, flg, ctx, frmt, ##__VA_ARGS__) 72 | 73 | #define ASYNC_LOG_OBJC_MACRO(lvl, flg, ctx, frmt, ...) \ 74 | LOG_OBJC_MACRO(YES, lvl, flg, ctx, frmt, ##__VA_ARGS__) 75 | 76 | #define SYNC_LOG_C_MACRO(lvl, flg, ctx, frmt, ...) \ 77 | LOG_C_MACRO( NO, lvl, flg, ctx, frmt, ##__VA_ARGS__) 78 | 79 | #define ASYNC_LOG_C_MACRO(lvl, flg, ctx, frmt, ...) \ 80 | LOG_C_MACRO(YES, lvl, flg, ctx, frmt, ##__VA_ARGS__) 81 | 82 | /** 83 | * Define version of the macro that only execute if the logLevel is above the threshold. 84 | * The compiled versions essentially look like this: 85 | * 86 | * if (logFlagForThisLogMsg & ddLogLevel) { execute log message } 87 | * 88 | * As shown further below, Lumberjack actually uses a bitmask as opposed to primitive log levels. 89 | * This allows for a great amount of flexibility and some pretty advanced fine grained logging techniques. 90 | * 91 | * Note that when compiler optimizations are enabled (as they are for your release builds), 92 | * the log messages above your logging threshold will automatically be compiled out. 93 | * 94 | * (If the compiler sees ddLogLevel declared as a constant, the compiler simply checks to see if the 'if' statement 95 | * would execute, and if not it strips it from the binary.) 96 | * 97 | * We also define shorthand versions for asynchronous and synchronous logging. 98 | **/ 99 | 100 | #define LOG_MAYBE(async, lvl, flg, ctx, fnct, frmt, ...) \ 101 | do { if(lvl & flg) LOG_MACRO(async, lvl, flg, ctx, nil, fnct, frmt, ##__VA_ARGS__); } while(0) 102 | 103 | #define LOG_OBJC_MAYBE(async, lvl, flg, ctx, frmt, ...) \ 104 | LOG_MAYBE(async, lvl, flg, ctx, sel_getName(_cmd), frmt, ##__VA_ARGS__) 105 | 106 | #define LOG_C_MAYBE(async, lvl, flg, ctx, frmt, ...) \ 107 | LOG_MAYBE(async, lvl, flg, ctx, __FUNCTION__, frmt, ##__VA_ARGS__) 108 | 109 | #define SYNC_LOG_OBJC_MAYBE(lvl, flg, ctx, frmt, ...) \ 110 | LOG_OBJC_MAYBE( NO, lvl, flg, ctx, frmt, ##__VA_ARGS__) 111 | 112 | #define ASYNC_LOG_OBJC_MAYBE(lvl, flg, ctx, frmt, ...) \ 113 | LOG_OBJC_MAYBE(YES, lvl, flg, ctx, frmt, ##__VA_ARGS__) 114 | 115 | #define SYNC_LOG_C_MAYBE(lvl, flg, ctx, frmt, ...) \ 116 | LOG_C_MAYBE( NO, lvl, flg, ctx, frmt, ##__VA_ARGS__) 117 | 118 | #define ASYNC_LOG_C_MAYBE(lvl, flg, ctx, frmt, ...) \ 119 | LOG_C_MAYBE(YES, lvl, flg, ctx, frmt, ##__VA_ARGS__) 120 | 121 | /** 122 | * Define versions of the macros that also accept tags. 123 | * 124 | * The DDLogMessage object includes a 'tag' ivar that may be used for a variety of purposes. 125 | * It may be used to pass custom information to loggers or formatters. 126 | * Or it may be used by 3rd party extensions to the framework. 127 | * 128 | * Thes macros just make it a little easier to extend logging functionality. 129 | **/ 130 | 131 | #define LOG_OBJC_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, ...) \ 132 | LOG_MACRO(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, ##__VA_ARGS__) 133 | 134 | #define LOG_C_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, ...) \ 135 | LOG_MACRO(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, ##__VA_ARGS__) 136 | 137 | #define LOG_TAG_MAYBE(async, lvl, flg, ctx, tag, fnct, frmt, ...) \ 138 | do { if(lvl & flg) LOG_MACRO(async, lvl, flg, ctx, tag, fnct, frmt, ##__VA_ARGS__); } while(0) 139 | 140 | #define LOG_OBJC_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, ...) \ 141 | LOG_TAG_MAYBE(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, ##__VA_ARGS__) 142 | 143 | #define LOG_C_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, ...) \ 144 | LOG_TAG_MAYBE(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, ##__VA_ARGS__) 145 | 146 | /** 147 | * Define the standard options. 148 | * 149 | * We default to only 4 levels because it makes it easier for beginners 150 | * to make the transition to a logging framework. 151 | * 152 | * More advanced users may choose to completely customize the levels (and level names) to suite their needs. 153 | * For more information on this see the "Custom Log Levels" page: 154 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomLogLevels 155 | * 156 | * Advanced users may also notice that we're using a bitmask. 157 | * This is to allow for custom fine grained logging: 158 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/FineGrainedLogging 159 | * 160 | * -- Flags -- 161 | * 162 | * Typically you will use the LOG_LEVELS (see below), but the flags may be used directly in certain situations. 163 | * For example, say you have a lot of warning log messages, and you wanted to disable them. 164 | * However, you still needed to see your error and info log messages. 165 | * You could accomplish that with the following: 166 | * 167 | * static const int ddLogLevel = LOG_FLAG_ERROR | LOG_FLAG_INFO; 168 | * 169 | * Flags may also be consulted when writing custom log formatters, 170 | * as the DDLogMessage class captures the individual flag that caused the log message to fire. 171 | * 172 | * -- Levels -- 173 | * 174 | * Log levels are simply the proper bitmask of the flags. 175 | * 176 | * -- Booleans -- 177 | * 178 | * The booleans may be used when your logging code involves more than one line. 179 | * For example: 180 | * 181 | * if (LOG_VERBOSE) { 182 | * for (id sprocket in sprockets) 183 | * DDLogVerbose(@"sprocket: %@", [sprocket description]) 184 | * } 185 | * 186 | * -- Async -- 187 | * 188 | * Defines the default asynchronous options. 189 | * The default philosophy for asynchronous logging is very simple: 190 | * 191 | * Log messages with errors should be executed synchronously. 192 | * After all, an error just occurred. The application could be unstable. 193 | * 194 | * All other log messages, such as debug output, are executed asynchronously. 195 | * After all, if it wasn't an error, then it was just informational output, 196 | * or something the application was easily able to recover from. 197 | * 198 | * -- Changes -- 199 | * 200 | * You are strongly discouraged from modifying this file. 201 | * If you do, you make it more difficult on yourself to merge future bug fixes and improvements from the project. 202 | * Instead, create your own MyLogging.h or ApplicationNameLogging.h or CompanyLogging.h 203 | * 204 | * For an example of customizing your logging experience, see the "Custom Log Levels" page: 205 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomLogLevels 206 | **/ 207 | 208 | #define LOG_FLAG_ERROR (1 << 0) // 0...0001 209 | #define LOG_FLAG_WARN (1 << 1) // 0...0010 210 | #define LOG_FLAG_INFO (1 << 2) // 0...0100 211 | #define LOG_FLAG_VERBOSE (1 << 3) // 0...1000 212 | 213 | #define LOG_LEVEL_OFF 0 214 | #define LOG_LEVEL_ERROR (LOG_FLAG_ERROR) // 0...0001 215 | #define LOG_LEVEL_WARN (LOG_FLAG_ERROR | LOG_FLAG_WARN) // 0...0011 216 | #define LOG_LEVEL_INFO (LOG_FLAG_ERROR | LOG_FLAG_WARN | LOG_FLAG_INFO) // 0...0111 217 | #define LOG_LEVEL_VERBOSE (LOG_FLAG_ERROR | LOG_FLAG_WARN | LOG_FLAG_INFO | LOG_FLAG_VERBOSE) // 0...1111 218 | 219 | #define LOG_ERROR (ddLogLevel & LOG_FLAG_ERROR) 220 | #define LOG_WARN (ddLogLevel & LOG_FLAG_WARN) 221 | #define LOG_INFO (ddLogLevel & LOG_FLAG_INFO) 222 | #define LOG_VERBOSE (ddLogLevel & LOG_FLAG_VERBOSE) 223 | 224 | #define LOG_ASYNC_ENABLED YES 225 | 226 | #define LOG_ASYNC_ERROR ( NO && LOG_ASYNC_ENABLED) 227 | #define LOG_ASYNC_WARN (YES && LOG_ASYNC_ENABLED) 228 | #define LOG_ASYNC_INFO (YES && LOG_ASYNC_ENABLED) 229 | #define LOG_ASYNC_VERBOSE (YES && LOG_ASYNC_ENABLED) 230 | 231 | #define DDLogError(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_ERROR, ddLogLevel, LOG_FLAG_ERROR, 0, frmt, ##__VA_ARGS__) 232 | #define DDLogWarn(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_WARN, ddLogLevel, LOG_FLAG_WARN, 0, frmt, ##__VA_ARGS__) 233 | #define DDLogInfo(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_INFO, ddLogLevel, LOG_FLAG_INFO, 0, frmt, ##__VA_ARGS__) 234 | #define DDLogVerbose(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_VERBOSE, ddLogLevel, LOG_FLAG_VERBOSE, 0, frmt, ##__VA_ARGS__) 235 | 236 | #define DDLogCError(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_ERROR, ddLogLevel, LOG_FLAG_ERROR, 0, frmt, ##__VA_ARGS__) 237 | #define DDLogCWarn(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_WARN, ddLogLevel, LOG_FLAG_WARN, 0, frmt, ##__VA_ARGS__) 238 | #define DDLogCInfo(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_INFO, ddLogLevel, LOG_FLAG_INFO, 0, frmt, ##__VA_ARGS__) 239 | #define DDLogCVerbose(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_VERBOSE, ddLogLevel, LOG_FLAG_VERBOSE, 0, frmt, ##__VA_ARGS__) 240 | 241 | /** 242 | * The THIS_FILE macro gives you an NSString of the file name. 243 | * For simplicity and clarity, the file name does not include the full path or file extension. 244 | * 245 | * For example: DDLogWarn(@"%@: Unable to find thingy", THIS_FILE) -> @"MyViewController: Unable to find thingy" 246 | **/ 247 | 248 | NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy); 249 | 250 | #define THIS_FILE (DDExtractFileNameWithoutExtension(__FILE__, NO)) 251 | 252 | /** 253 | * The THIS_METHOD macro gives you the name of the current objective-c method. 254 | * 255 | * For example: DDLogWarn(@"%@ - Requires non-nil strings") -> @"setMake:model: requires non-nil strings" 256 | * 257 | * Note: This does NOT work in straight C functions (non objective-c). 258 | * Instead you should use the predefined __FUNCTION__ macro. 259 | **/ 260 | 261 | #define THIS_METHOD NSStringFromSelector(_cmd) 262 | 263 | 264 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 265 | #pragma mark - 266 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 267 | 268 | @interface DDLog : NSObject 269 | 270 | /** 271 | * Provides access to the underlying logging queue. 272 | * This may be helpful to Logger classes for things like thread synchronization. 273 | **/ 274 | 275 | + (dispatch_queue_t)loggingQueue; 276 | 277 | /** 278 | * Logging Primitive. 279 | * 280 | * This method is used by the macros above. 281 | * It is suggested you stick with the macros as they're easier to use. 282 | **/ 283 | 284 | + (void)log:(BOOL)synchronous 285 | level:(int)level 286 | flag:(int)flag 287 | context:(int)context 288 | file:(const char *)file 289 | function:(const char *)function 290 | line:(int)line 291 | tag:(id)tag 292 | format:(NSString *)format, ... __attribute__ ((format (__NSString__, 9, 10))); 293 | 294 | /** 295 | * Logging Primitive. 296 | * 297 | * This method can be used if you have a prepared va_list. 298 | **/ 299 | 300 | + (void)log:(BOOL)asynchronous 301 | level:(int)level 302 | flag:(int)flag 303 | context:(int)context 304 | file:(const char *)file 305 | function:(const char *)function 306 | line:(int)line 307 | tag:(id)tag 308 | format:(NSString *)format 309 | args:(va_list)argList; 310 | 311 | 312 | /** 313 | * Since logging can be asynchronous, there may be times when you want to flush the logs. 314 | * The framework invokes this automatically when the application quits. 315 | **/ 316 | 317 | + (void)flushLog; 318 | 319 | /** 320 | * Loggers 321 | * 322 | * If you want your log statements to go somewhere, 323 | * you should create and add a logger. 324 | **/ 325 | 326 | + (void)addLogger:(id )logger; 327 | + (void)removeLogger:(id )logger; 328 | 329 | + (void)removeAllLoggers; 330 | 331 | /** 332 | * Registered Dynamic Logging 333 | * 334 | * These methods allow you to obtain a list of classes that are using registered dynamic logging, 335 | * and also provides methods to get and set their log level during run time. 336 | **/ 337 | 338 | + (NSArray *)registeredClasses; 339 | + (NSArray *)registeredClassNames; 340 | 341 | + (int)logLevelForClass:(Class)aClass; 342 | + (int)logLevelForClassWithName:(NSString *)aClassName; 343 | 344 | + (void)setLogLevel:(int)logLevel forClass:(Class)aClass; 345 | + (void)setLogLevel:(int)logLevel forClassWithName:(NSString *)aClassName; 346 | 347 | @end 348 | 349 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 350 | #pragma mark - 351 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 352 | 353 | @protocol DDLogger 354 | @required 355 | 356 | - (void)logMessage:(DDLogMessage *)logMessage; 357 | 358 | /** 359 | * Formatters may optionally be added to any logger. 360 | * 361 | * If no formatter is set, the logger simply logs the message as it is given in logMessage, 362 | * or it may use its own built in formatting style. 363 | **/ 364 | - (id )logFormatter; 365 | - (void)setLogFormatter:(id )formatter; 366 | 367 | @optional 368 | 369 | /** 370 | * Since logging is asynchronous, adding and removing loggers is also asynchronous. 371 | * In other words, the loggers are added and removed at appropriate times with regards to log messages. 372 | * 373 | * - Loggers will not receive log messages that were executed prior to when they were added. 374 | * - Loggers will not receive log messages that were executed after they were removed. 375 | * 376 | * These methods are executed in the logging thread/queue. 377 | * This is the same thread/queue that will execute every logMessage: invocation. 378 | * Loggers may use these methods for thread synchronization or other setup/teardown tasks. 379 | **/ 380 | - (void)didAddLogger; 381 | - (void)willRemoveLogger; 382 | 383 | /** 384 | * Some loggers may buffer IO for optimization purposes. 385 | * For example, a database logger may only save occasionaly as the disk IO is slow. 386 | * In such loggers, this method should be implemented to flush any pending IO. 387 | * 388 | * This allows invocations of DDLog's flushLog method to be propogated to loggers that need it. 389 | * 390 | * Note that DDLog's flushLog method is invoked automatically when the application quits, 391 | * and it may be also invoked manually by the developer prior to application crashes, or other such reasons. 392 | **/ 393 | - (void)flush; 394 | 395 | /** 396 | * Each logger is executed concurrently with respect to the other loggers. 397 | * Thus, a dedicated dispatch queue is used for each logger. 398 | * Logger implementations may optionally choose to provide their own dispatch queue. 399 | **/ 400 | - (dispatch_queue_t)loggerQueue; 401 | 402 | /** 403 | * If the logger implementation does not choose to provide its own queue, 404 | * one will automatically be created for it. 405 | * The created queue will receive its name from this method. 406 | * This may be helpful for debugging or profiling reasons. 407 | **/ 408 | - (NSString *)loggerName; 409 | 410 | @end 411 | 412 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 413 | #pragma mark - 414 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 415 | 416 | @protocol DDLogFormatter 417 | @required 418 | 419 | /** 420 | * Formatters may optionally be added to any logger. 421 | * This allows for increased flexibility in the logging environment. 422 | * For example, log messages for log files may be formatted differently than log messages for the console. 423 | * 424 | * For more information about formatters, see the "Custom Formatters" page: 425 | * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomFormatters 426 | * 427 | * The formatter may also optionally filter the log message by returning nil, 428 | * in which case the logger will not log the message. 429 | **/ 430 | 431 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage; 432 | 433 | @end 434 | 435 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 436 | #pragma mark - 437 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 438 | 439 | @protocol DDRegisteredDynamicLogging 440 | 441 | /** 442 | * Implement these methods to allow a file's log level to be managed from a central location. 443 | * 444 | * This is useful if you'd like to be able to change log levels for various parts 445 | * of your code from within the running application. 446 | * 447 | * Imagine pulling up the settings for your application, 448 | * and being able to configure the logging level on a per file basis. 449 | * 450 | * The implementation can be very straight-forward: 451 | * 452 | * + (int)ddLogLevel 453 | * { 454 | * return ddLogLevel; 455 | * } 456 | * 457 | * + (void)ddSetLogLevel:(int)logLevel 458 | * { 459 | * ddLogLevel = logLevel; 460 | * } 461 | **/ 462 | 463 | + (int)ddLogLevel; 464 | + (void)ddSetLogLevel:(int)logLevel; 465 | 466 | @end 467 | 468 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 469 | #pragma mark - 470 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 471 | 472 | /** 473 | * The DDLogMessage class encapsulates information about the log message. 474 | * If you write custom loggers or formatters, you will be dealing with objects of this class. 475 | **/ 476 | 477 | enum { 478 | DDLogMessageCopyFile = 1 << 0, 479 | DDLogMessageCopyFunction = 1 << 1, 480 | }; 481 | typedef int DDLogMessageOptions; 482 | 483 | @interface DDLogMessage : NSObject 484 | { 485 | 486 | // The public variables below can be accessed directly (for speed). 487 | // For example: logMessage->logLevel 488 | 489 | @public 490 | int logLevel; 491 | int logFlag; 492 | int logContext; 493 | NSString *logMsg; 494 | NSDate *timestamp; 495 | char *file; 496 | char *function; 497 | int lineNumber; 498 | mach_port_t machThreadID; 499 | char *queueLabel; 500 | NSString *threadName; 501 | 502 | // For 3rd party extensions to the framework, where flags and contexts aren't enough. 503 | id tag; 504 | 505 | // For 3rd party extensions that manually create DDLogMessage instances. 506 | DDLogMessageOptions options; 507 | } 508 | 509 | /** 510 | * Standard init method for a log message object. 511 | * Used by the logging primitives. (And the macros use the logging primitives.) 512 | * 513 | * If you find need to manually create logMessage objects, there is one thing you should be aware of: 514 | * 515 | * If no flags are passed, the method expects the file and function parameters to be string literals. 516 | * That is, it expects the given strings to exist for the duration of the object's lifetime, 517 | * and it expects the given strings to be immutable. 518 | * In other words, it does not copy these strings, it simply points to them. 519 | * This is due to the fact that __FILE__ and __FUNCTION__ are usually used to specify these parameters, 520 | * so it makes sense to optimize and skip the unnecessary allocations. 521 | * However, if you need them to be copied you may use the options parameter to specify this. 522 | * Options is a bitmask which supports DDLogMessageCopyFile and DDLogMessageCopyFunction. 523 | **/ 524 | - (id)initWithLogMsg:(NSString *)logMsg 525 | level:(int)logLevel 526 | flag:(int)logFlag 527 | context:(int)logContext 528 | file:(const char *)file 529 | function:(const char *)function 530 | line:(int)line 531 | tag:(id)tag 532 | options:(DDLogMessageOptions)optionsMask; 533 | 534 | /** 535 | * Returns the threadID as it appears in NSLog. 536 | * That is, it is a hexadecimal value which is calculated from the machThreadID. 537 | **/ 538 | - (NSString *)threadID; 539 | 540 | /** 541 | * Convenience property to get just the file name, as the file variable is generally the full file path. 542 | * This method does not include the file extension, which is generally unwanted for logging purposes. 543 | **/ 544 | - (NSString *)fileName; 545 | 546 | /** 547 | * Returns the function variable in NSString form. 548 | **/ 549 | - (NSString *)methodName; 550 | 551 | @end 552 | 553 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 554 | #pragma mark - 555 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 556 | 557 | /** 558 | * The DDLogger protocol specifies that an optional formatter can be added to a logger. 559 | * Most (but not all) loggers will want to support formatters. 560 | * 561 | * However, writting getters and setters in a thread safe manner, 562 | * while still maintaining maximum speed for the logging process, is a difficult task. 563 | * 564 | * To do it right, the implementation of the getter/setter has strict requiremenets: 565 | * - Must NOT require the logMessage method to acquire a lock. 566 | * - Must NOT require the logMessage method to access an atomic property (also a lock of sorts). 567 | * 568 | * To simplify things, an abstract logger is provided that implements the getter and setter. 569 | * 570 | * Logger implementations may simply extend this class, 571 | * and they can ACCESS THE FORMATTER VARIABLE DIRECTLY from within their logMessage method! 572 | **/ 573 | 574 | @interface DDAbstractLogger : NSObject 575 | { 576 | id formatter; 577 | 578 | dispatch_queue_t loggerQueue; 579 | } 580 | 581 | - (id )logFormatter; 582 | - (void)setLogFormatter:(id )formatter; 583 | 584 | @end 585 | -------------------------------------------------------------------------------- /ConnectTest.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1A0386EA17BCB41A00899D3A /* TestUI.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A0386E817BCB41A00899D3A /* TestUI.m */; }; 11 | 1A0386EB17BCB41A00899D3A /* TestUI.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1A0386E917BCB41A00899D3A /* TestUI.xib */; }; 12 | 1A0386EE17BCB56200899D3A /* TcpClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A0386ED17BCB56200899D3A /* TcpClient.m */; }; 13 | 1A0386F117BCBFE300899D3A /* readme.txt in Resources */ = {isa = PBXBuildFile; fileRef = 1A0386F017BCBFE300899D3A /* readme.txt */; }; 14 | 1A46BFC917C79FCA0059853D /* DDAbstractDatabaseLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A46BFC017C79FCA0059853D /* DDAbstractDatabaseLogger.m */; }; 15 | 1A46BFCA17C79FCA0059853D /* DDASLLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A46BFC217C79FCA0059853D /* DDASLLogger.m */; }; 16 | 1A46BFCB17C79FCA0059853D /* DDFileLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A46BFC417C79FCA0059853D /* DDFileLogger.m */; }; 17 | 1A46BFCC17C79FCA0059853D /* DDLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A46BFC617C79FCA0059853D /* DDLog.m */; }; 18 | 1A46BFCD17C79FCA0059853D /* DDTTYLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A46BFC817C79FCA0059853D /* DDTTYLogger.m */; }; 19 | 1A46BFD217C79FD30059853D /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A46BFCF17C79FD30059853D /* GCDAsyncSocket.m */; }; 20 | 1A46BFD317C79FD30059853D /* GCDAsyncUdpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A46BFD117C79FD30059853D /* GCDAsyncUdpSocket.m */; }; 21 | 1A46BFD917C7A1990059853D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A46BFD817C7A1990059853D /* main.m */; }; 22 | 1A4FCC2017C613190045DDB8 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A4FCC1F17C613180045DDB8 /* Reachability.m */; }; 23 | 1A4FCC2217C6144E0045DDB8 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A4FCC2117C6144D0045DDB8 /* SystemConfiguration.framework */; }; 24 | 1AFC85D617C8FE2300D9DA0B /* ConnectTestViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1AFC85D017C8FE2300D9DA0B /* ConnectTestViewController.xib */; }; 25 | 1AFC85D717C8FE2300D9DA0B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1AFC85D217C8FE2300D9DA0B /* InfoPlist.strings */; }; 26 | 1AFC85D817C8FE2300D9DA0B /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1AFC85D417C8FE2300D9DA0B /* MainWindow.xib */; }; 27 | DC5889A5158DE310007AFCFC /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC5889A4158DE310007AFCFC /* Security.framework */; }; 28 | DCDE285D13DDEC74006BFCC0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDE285C13DDEC74006BFCC0 /* UIKit.framework */; }; 29 | DCDE285F13DDEC74006BFCC0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDE285E13DDEC74006BFCC0 /* Foundation.framework */; }; 30 | DCDE286113DDEC74006BFCC0 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDE286013DDEC74006BFCC0 /* CoreGraphics.framework */; }; 31 | DCDE286D13DDEC74006BFCC0 /* ConnectTestAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDE286C13DDEC74006BFCC0 /* ConnectTestAppDelegate.m */; }; 32 | DCDE287313DDEC74006BFCC0 /* ConnectTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDE287213DDEC74006BFCC0 /* ConnectTestViewController.m */; }; 33 | DCDE289913DDECF1006BFCC0 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCDE289813DDECF1006BFCC0 /* CFNetwork.framework */; }; 34 | /* End PBXBuildFile section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | 1A0386E717BCB41A00899D3A /* TestUI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestUI.h; sourceTree = ""; }; 38 | 1A0386E817BCB41A00899D3A /* TestUI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestUI.m; sourceTree = ""; }; 39 | 1A0386E917BCB41A00899D3A /* TestUI.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TestUI.xib; sourceTree = ""; }; 40 | 1A0386EC17BCB56200899D3A /* TcpClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TcpClient.h; sourceTree = ""; }; 41 | 1A0386ED17BCB56200899D3A /* TcpClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TcpClient.m; sourceTree = ""; }; 42 | 1A0386F017BCBFE300899D3A /* readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = readme.txt; sourceTree = ""; }; 43 | 1A46BFBF17C79FCA0059853D /* DDAbstractDatabaseLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDAbstractDatabaseLogger.h; sourceTree = ""; }; 44 | 1A46BFC017C79FCA0059853D /* DDAbstractDatabaseLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDAbstractDatabaseLogger.m; sourceTree = ""; }; 45 | 1A46BFC117C79FCA0059853D /* DDASLLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDASLLogger.h; sourceTree = ""; }; 46 | 1A46BFC217C79FCA0059853D /* DDASLLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDASLLogger.m; sourceTree = ""; }; 47 | 1A46BFC317C79FCA0059853D /* DDFileLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDFileLogger.h; sourceTree = ""; }; 48 | 1A46BFC417C79FCA0059853D /* DDFileLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDFileLogger.m; sourceTree = ""; }; 49 | 1A46BFC517C79FCA0059853D /* DDLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDLog.h; sourceTree = ""; }; 50 | 1A46BFC617C79FCA0059853D /* DDLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDLog.m; sourceTree = ""; }; 51 | 1A46BFC717C79FCA0059853D /* DDTTYLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDTTYLogger.h; sourceTree = ""; }; 52 | 1A46BFC817C79FCA0059853D /* DDTTYLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDTTYLogger.m; sourceTree = ""; }; 53 | 1A46BFCE17C79FD30059853D /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = ""; }; 54 | 1A46BFCF17C79FD30059853D /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = ""; }; 55 | 1A46BFD017C79FD30059853D /* GCDAsyncUdpSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncUdpSocket.h; sourceTree = ""; }; 56 | 1A46BFD117C79FD30059853D /* GCDAsyncUdpSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncUdpSocket.m; sourceTree = ""; }; 57 | 1A46BFD517C7A06C0059853D /* ConnectTest-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ConnectTest-Prefix.pch"; sourceTree = SOURCE_ROOT; }; 58 | 1A46BFD817C7A1990059853D /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 59 | 1A4FCC1D17C5F8560045DDB8 /* ITcpClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ITcpClient.h; sourceTree = ""; }; 60 | 1A4FCC1E17C613170045DDB8 /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = ""; }; 61 | 1A4FCC1F17C613180045DDB8 /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = ""; }; 62 | 1A4FCC2117C6144D0045DDB8 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 63 | 1AFC85D117C8FE2300D9DA0B /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ConnectTestViewController.xib; sourceTree = ""; }; 64 | 1AFC85D317C8FE2300D9DA0B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; 65 | 1AFC85D517C8FE2300D9DA0B /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = MainWindow.xib; sourceTree = ""; }; 66 | DC5889A4158DE310007AFCFC /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 67 | DCDE285813DDEC74006BFCC0 /* ConnectTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ConnectTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | DCDE285C13DDEC74006BFCC0 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 69 | DCDE285E13DDEC74006BFCC0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 70 | DCDE286013DDEC74006BFCC0 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 71 | DCDE286413DDEC74006BFCC0 /* ConnectTest-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ConnectTest-Info.plist"; sourceTree = ""; }; 72 | DCDE286B13DDEC74006BFCC0 /* ConnectTestAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ConnectTestAppDelegate.h; sourceTree = ""; }; 73 | DCDE286C13DDEC74006BFCC0 /* ConnectTestAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ConnectTestAppDelegate.m; sourceTree = ""; }; 74 | DCDE287113DDEC74006BFCC0 /* ConnectTestViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ConnectTestViewController.h; sourceTree = ""; }; 75 | DCDE287213DDEC74006BFCC0 /* ConnectTestViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ConnectTestViewController.m; sourceTree = ""; }; 76 | DCDE289813DDECF1006BFCC0 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 77 | /* End PBXFileReference section */ 78 | 79 | /* Begin PBXFrameworksBuildPhase section */ 80 | DCDE285513DDEC74006BFCC0 /* Frameworks */ = { 81 | isa = PBXFrameworksBuildPhase; 82 | buildActionMask = 2147483647; 83 | files = ( 84 | 1A4FCC2217C6144E0045DDB8 /* SystemConfiguration.framework in Frameworks */, 85 | DC5889A5158DE310007AFCFC /* Security.framework in Frameworks */, 86 | DCDE289913DDECF1006BFCC0 /* CFNetwork.framework in Frameworks */, 87 | DCDE285D13DDEC74006BFCC0 /* UIKit.framework in Frameworks */, 88 | DCDE285F13DDEC74006BFCC0 /* Foundation.framework in Frameworks */, 89 | DCDE286113DDEC74006BFCC0 /* CoreGraphics.framework in Frameworks */, 90 | ); 91 | runOnlyForDeploymentPostprocessing = 0; 92 | }; 93 | /* End PBXFrameworksBuildPhase section */ 94 | 95 | /* Begin PBXGroup section */ 96 | 1A0386EF17BCBFCE00899D3A /* res */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 1A0386F017BCBFE300899D3A /* readme.txt */, 100 | ); 101 | path = res; 102 | sourceTree = SOURCE_ROOT; 103 | }; 104 | 1A46BFBE17C79FCA0059853D /* vendor */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 1A46BFBF17C79FCA0059853D /* DDAbstractDatabaseLogger.h */, 108 | 1A46BFC017C79FCA0059853D /* DDAbstractDatabaseLogger.m */, 109 | 1A46BFC117C79FCA0059853D /* DDASLLogger.h */, 110 | 1A46BFC217C79FCA0059853D /* DDASLLogger.m */, 111 | 1A46BFC317C79FCA0059853D /* DDFileLogger.h */, 112 | 1A46BFC417C79FCA0059853D /* DDFileLogger.m */, 113 | 1A46BFC517C79FCA0059853D /* DDLog.h */, 114 | 1A46BFC617C79FCA0059853D /* DDLog.m */, 115 | 1A46BFC717C79FCA0059853D /* DDTTYLogger.h */, 116 | 1A46BFC817C79FCA0059853D /* DDTTYLogger.m */, 117 | ); 118 | path = vendor; 119 | sourceTree = ""; 120 | }; 121 | 1AFC85CF17C8FE2300D9DA0B /* en.lproj */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 1AFC85D017C8FE2300D9DA0B /* ConnectTestViewController.xib */, 125 | 1AFC85D217C8FE2300D9DA0B /* InfoPlist.strings */, 126 | 1AFC85D417C8FE2300D9DA0B /* MainWindow.xib */, 127 | ); 128 | name = en.lproj; 129 | path = ../en.lproj; 130 | sourceTree = ""; 131 | }; 132 | DCDE284D13DDEC74006BFCC0 = { 133 | isa = PBXGroup; 134 | children = ( 135 | 1A46BFCE17C79FD30059853D /* GCDAsyncSocket.h */, 136 | 1A46BFCF17C79FD30059853D /* GCDAsyncSocket.m */, 137 | 1A46BFD017C79FD30059853D /* GCDAsyncUdpSocket.h */, 138 | 1A46BFD117C79FD30059853D /* GCDAsyncUdpSocket.m */, 139 | 1A46BFBE17C79FCA0059853D /* vendor */, 140 | DCDE286213DDEC74006BFCC0 /* ConnectTest */, 141 | DCDE285B13DDEC74006BFCC0 /* Frameworks */, 142 | DCDE285913DDEC74006BFCC0 /* Products */, 143 | ); 144 | sourceTree = ""; 145 | }; 146 | DCDE285913DDEC74006BFCC0 /* Products */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | DCDE285813DDEC74006BFCC0 /* ConnectTest.app */, 150 | ); 151 | name = Products; 152 | sourceTree = ""; 153 | }; 154 | DCDE285B13DDEC74006BFCC0 /* Frameworks */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 1A4FCC2117C6144D0045DDB8 /* SystemConfiguration.framework */, 158 | DCDE285C13DDEC74006BFCC0 /* UIKit.framework */, 159 | DCDE285E13DDEC74006BFCC0 /* Foundation.framework */, 160 | DCDE286013DDEC74006BFCC0 /* CoreGraphics.framework */, 161 | DCDE289813DDECF1006BFCC0 /* CFNetwork.framework */, 162 | DC5889A4158DE310007AFCFC /* Security.framework */, 163 | ); 164 | name = Frameworks; 165 | sourceTree = ""; 166 | }; 167 | DCDE286213DDEC74006BFCC0 /* ConnectTest */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | 1A0386E717BCB41A00899D3A /* TestUI.h */, 171 | 1A0386E817BCB41A00899D3A /* TestUI.m */, 172 | 1A0386E917BCB41A00899D3A /* TestUI.xib */, 173 | 1A0386EC17BCB56200899D3A /* TcpClient.h */, 174 | 1A0386ED17BCB56200899D3A /* TcpClient.m */, 175 | 1A4FCC1D17C5F8560045DDB8 /* ITcpClient.h */, 176 | 1A46BFD817C7A1990059853D /* main.m */, 177 | 1A46BFD517C7A06C0059853D /* ConnectTest-Prefix.pch */, 178 | 1A4FCC1E17C613170045DDB8 /* Reachability.h */, 179 | 1A4FCC1F17C613180045DDB8 /* Reachability.m */, 180 | DCDE286B13DDEC74006BFCC0 /* ConnectTestAppDelegate.h */, 181 | DCDE286C13DDEC74006BFCC0 /* ConnectTestAppDelegate.m */, 182 | DCDE287113DDEC74006BFCC0 /* ConnectTestViewController.h */, 183 | DCDE287213DDEC74006BFCC0 /* ConnectTestViewController.m */, 184 | DCDE286313DDEC74006BFCC0 /* Supporting Files */, 185 | ); 186 | path = ConnectTest; 187 | sourceTree = ""; 188 | }; 189 | DCDE286313DDEC74006BFCC0 /* Supporting Files */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 1AFC85CF17C8FE2300D9DA0B /* en.lproj */, 193 | 1A0386EF17BCBFCE00899D3A /* res */, 194 | DCDE286413DDEC74006BFCC0 /* ConnectTest-Info.plist */, 195 | ); 196 | name = "Supporting Files"; 197 | sourceTree = ""; 198 | }; 199 | /* End PBXGroup section */ 200 | 201 | /* Begin PBXNativeTarget section */ 202 | DCDE285713DDEC74006BFCC0 /* ConnectTest */ = { 203 | isa = PBXNativeTarget; 204 | buildConfigurationList = DCDE287913DDEC74006BFCC0 /* Build configuration list for PBXNativeTarget "ConnectTest" */; 205 | buildPhases = ( 206 | DCDE285413DDEC74006BFCC0 /* Sources */, 207 | DCDE285513DDEC74006BFCC0 /* Frameworks */, 208 | DCDE285613DDEC74006BFCC0 /* Resources */, 209 | ); 210 | buildRules = ( 211 | ); 212 | dependencies = ( 213 | ); 214 | name = ConnectTest; 215 | productName = ConnectTest; 216 | productReference = DCDE285813DDEC74006BFCC0 /* ConnectTest.app */; 217 | productType = "com.apple.product-type.application"; 218 | }; 219 | /* End PBXNativeTarget section */ 220 | 221 | /* Begin PBXProject section */ 222 | DCDE284F13DDEC74006BFCC0 /* Project object */ = { 223 | isa = PBXProject; 224 | attributes = { 225 | LastUpgradeCheck = 0420; 226 | }; 227 | buildConfigurationList = DCDE285213DDEC74006BFCC0 /* Build configuration list for PBXProject "ConnectTest" */; 228 | compatibilityVersion = "Xcode 3.2"; 229 | developmentRegion = English; 230 | hasScannedForEncodings = 0; 231 | knownRegions = ( 232 | en, 233 | ); 234 | mainGroup = DCDE284D13DDEC74006BFCC0; 235 | productRefGroup = DCDE285913DDEC74006BFCC0 /* Products */; 236 | projectDirPath = ""; 237 | projectRoot = ""; 238 | targets = ( 239 | DCDE285713DDEC74006BFCC0 /* ConnectTest */, 240 | ); 241 | }; 242 | /* End PBXProject section */ 243 | 244 | /* Begin PBXResourcesBuildPhase section */ 245 | DCDE285613DDEC74006BFCC0 /* Resources */ = { 246 | isa = PBXResourcesBuildPhase; 247 | buildActionMask = 2147483647; 248 | files = ( 249 | 1A0386EB17BCB41A00899D3A /* TestUI.xib in Resources */, 250 | 1A0386F117BCBFE300899D3A /* readme.txt in Resources */, 251 | 1AFC85D617C8FE2300D9DA0B /* ConnectTestViewController.xib in Resources */, 252 | 1AFC85D717C8FE2300D9DA0B /* InfoPlist.strings in Resources */, 253 | 1AFC85D817C8FE2300D9DA0B /* MainWindow.xib in Resources */, 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | /* End PBXResourcesBuildPhase section */ 258 | 259 | /* Begin PBXSourcesBuildPhase section */ 260 | DCDE285413DDEC74006BFCC0 /* Sources */ = { 261 | isa = PBXSourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | DCDE286D13DDEC74006BFCC0 /* ConnectTestAppDelegate.m in Sources */, 265 | DCDE287313DDEC74006BFCC0 /* ConnectTestViewController.m in Sources */, 266 | 1A0386EA17BCB41A00899D3A /* TestUI.m in Sources */, 267 | 1A0386EE17BCB56200899D3A /* TcpClient.m in Sources */, 268 | 1A4FCC2017C613190045DDB8 /* Reachability.m in Sources */, 269 | 1A46BFC917C79FCA0059853D /* DDAbstractDatabaseLogger.m in Sources */, 270 | 1A46BFCA17C79FCA0059853D /* DDASLLogger.m in Sources */, 271 | 1A46BFCB17C79FCA0059853D /* DDFileLogger.m in Sources */, 272 | 1A46BFCC17C79FCA0059853D /* DDLog.m in Sources */, 273 | 1A46BFCD17C79FCA0059853D /* DDTTYLogger.m in Sources */, 274 | 1A46BFD217C79FD30059853D /* GCDAsyncSocket.m in Sources */, 275 | 1A46BFD317C79FD30059853D /* GCDAsyncUdpSocket.m in Sources */, 276 | 1A46BFD917C7A1990059853D /* main.m in Sources */, 277 | ); 278 | runOnlyForDeploymentPostprocessing = 0; 279 | }; 280 | /* End PBXSourcesBuildPhase section */ 281 | 282 | /* Begin PBXVariantGroup section */ 283 | 1AFC85D017C8FE2300D9DA0B /* ConnectTestViewController.xib */ = { 284 | isa = PBXVariantGroup; 285 | children = ( 286 | 1AFC85D117C8FE2300D9DA0B /* en */, 287 | ); 288 | name = ConnectTestViewController.xib; 289 | sourceTree = ""; 290 | }; 291 | 1AFC85D217C8FE2300D9DA0B /* InfoPlist.strings */ = { 292 | isa = PBXVariantGroup; 293 | children = ( 294 | 1AFC85D317C8FE2300D9DA0B /* en */, 295 | ); 296 | name = InfoPlist.strings; 297 | sourceTree = ""; 298 | }; 299 | 1AFC85D417C8FE2300D9DA0B /* MainWindow.xib */ = { 300 | isa = PBXVariantGroup; 301 | children = ( 302 | 1AFC85D517C8FE2300D9DA0B /* en */, 303 | ); 304 | name = MainWindow.xib; 305 | sourceTree = ""; 306 | }; 307 | /* End PBXVariantGroup section */ 308 | 309 | /* Begin XCBuildConfiguration section */ 310 | DCDE287713DDEC74006BFCC0 /* Debug */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 314 | CLANG_ENABLE_OBJC_ARC = YES; 315 | CLANG_WARN_OBJCPP_ARC_ABI = YES; 316 | CODE_SIGN_IDENTITY = "iPhone Developer: Zhang Yin (PP7PPJ23GT)"; 317 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 318 | GCC_C_LANGUAGE_STANDARD = gnu99; 319 | GCC_OPTIMIZATION_LEVEL = 0; 320 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG; 321 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 322 | GCC_VERSION = com.apple.compilers.llvmgcc42; 323 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 324 | GCC_WARN_UNUSED_VARIABLE = YES; 325 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 326 | PROVISIONING_PROFILE = "9733BF74-9A37-4F17-8719-619890C8E30C"; 327 | SDKROOT = iphoneos; 328 | }; 329 | name = Debug; 330 | }; 331 | DCDE287813DDEC74006BFCC0 /* Release */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 335 | CLANG_ENABLE_OBJC_ARC = YES; 336 | CLANG_WARN_OBJCPP_ARC_ABI = YES; 337 | CODE_SIGN_IDENTITY = "iPhone Distribution: Zhang Yin (YEQSU47H36)"; 338 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 339 | GCC_C_LANGUAGE_STANDARD = gnu99; 340 | GCC_VERSION = com.apple.compilers.llvmgcc42; 341 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 342 | GCC_WARN_UNUSED_VARIABLE = YES; 343 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 344 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 345 | PROVISIONING_PROFILE = "E92000B5-1010-4F04-A1F6-1AFF51CEEBF4"; 346 | SDKROOT = iphoneos; 347 | }; 348 | name = Release; 349 | }; 350 | DCDE287A13DDEC74006BFCC0 /* Debug */ = { 351 | isa = XCBuildConfiguration; 352 | buildSettings = { 353 | ALWAYS_SEARCH_USER_PATHS = NO; 354 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Zhang Yin (PP7PPJ23GT)"; 355 | COPY_PHASE_STRIP = NO; 356 | GCC_DYNAMIC_NO_PIC = NO; 357 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 358 | GCC_PREFIX_HEADER = "ConnectTest/ConnectTest-Prefix.pch"; 359 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 360 | INFOPLIST_FILE = "$(SRCROOT)/ConnectTest-Info.plist"; 361 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 362 | PRODUCT_NAME = "$(TARGET_NAME)"; 363 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = "9733BF74-9A37-4F17-8719-619890C8E30C"; 364 | WRAPPER_EXTENSION = app; 365 | }; 366 | name = Debug; 367 | }; 368 | DCDE287B13DDEC74006BFCC0 /* Release */ = { 369 | isa = XCBuildConfiguration; 370 | buildSettings = { 371 | ALWAYS_SEARCH_USER_PATHS = NO; 372 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Zhang Yin (YEQSU47H36)"; 373 | COPY_PHASE_STRIP = YES; 374 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 375 | GCC_PREFIX_HEADER = "ConnectTest/ConnectTest-Prefix.pch"; 376 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 377 | INFOPLIST_FILE = "$(SRCROOT)/ConnectTest-Info.plist"; 378 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 379 | PRODUCT_NAME = "$(TARGET_NAME)"; 380 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = "E92000B5-1010-4F04-A1F6-1AFF51CEEBF4"; 381 | VALIDATE_PRODUCT = YES; 382 | WRAPPER_EXTENSION = app; 383 | }; 384 | name = Release; 385 | }; 386 | /* End XCBuildConfiguration section */ 387 | 388 | /* Begin XCConfigurationList section */ 389 | DCDE285213DDEC74006BFCC0 /* Build configuration list for PBXProject "ConnectTest" */ = { 390 | isa = XCConfigurationList; 391 | buildConfigurations = ( 392 | DCDE287713DDEC74006BFCC0 /* Debug */, 393 | DCDE287813DDEC74006BFCC0 /* Release */, 394 | ); 395 | defaultConfigurationIsVisible = 0; 396 | defaultConfigurationName = Release; 397 | }; 398 | DCDE287913DDEC74006BFCC0 /* Build configuration list for PBXNativeTarget "ConnectTest" */ = { 399 | isa = XCConfigurationList; 400 | buildConfigurations = ( 401 | DCDE287A13DDEC74006BFCC0 /* Debug */, 402 | DCDE287B13DDEC74006BFCC0 /* Release */, 403 | ); 404 | defaultConfigurationIsVisible = 0; 405 | defaultConfigurationName = Release; 406 | }; 407 | /* End XCConfigurationList section */ 408 | }; 409 | rootObject = DCDE284F13DDEC74006BFCC0 /* Project object */; 410 | } 411 | --------------------------------------------------------------------------------