├── MMPrinterDemo
├── kfc.gif
├── ViewController.h
├── AppDelegate.h
├── main.m
├── PrinterManager
│ ├── MMQRCode.h
│ ├── MMSocketManager.h
│ ├── MMReceiptManager.h
│ ├── IGThermalSupport.h
│ ├── MMSocketManager.m
│ ├── MMPrinterManager.h
│ ├── MMQRCode.m
│ ├── MMPrinterManager.m
│ ├── MMReceiptManager.m
│ ├── IGThermalSupport.m
│ └── AsyncSocket.h
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Info.plist
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── AppDelegate.m
└── ViewController.m
├── README.md
├── MMPrinterDemo.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ ├── Mike.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ │ └── MikeZhao.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── xcuserdata
│ ├── Mike.xcuserdatad
│ │ └── xcschemes
│ │ │ ├── xcschememanagement.plist
│ │ │ └── MMPrinterDemo.xcscheme
│ └── MikeZhao.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── MMPrinterDemo.xcscheme
└── project.pbxproj
├── MMPrinterDemoTests
├── Info.plist
└── MMPrinterDemoTests.m
└── MMPrinterDemoUITests
├── Info.plist
└── MMPrinterDemoUITests.m
/MMPrinterDemo/kfc.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/songxiaam/MMPrinterDemo/HEAD/MMPrinterDemo/kfc.gif
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MMPrinterDemo
2 | 使用socket连接小票打印机打印小票的Demo,使用ESC/POS指令.
3 | http://www.jianshu.com/p/52bdd2e41b11
4 | 这是我在简书写的使用方法,可以参考下
5 |
--------------------------------------------------------------------------------
/MMPrinterDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MMPrinterDemo.xcodeproj/project.xcworkspace/xcuserdata/Mike.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/songxiaam/MMPrinterDemo/HEAD/MMPrinterDemo.xcodeproj/project.xcworkspace/xcuserdata/Mike.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/MMPrinterDemo.xcodeproj/project.xcworkspace/xcuserdata/MikeZhao.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/songxiaam/MMPrinterDemo/HEAD/MMPrinterDemo.xcodeproj/project.xcworkspace/xcuserdata/MikeZhao.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/MMPrinterDemo/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // MMPrinterDemo
4 | //
5 | // Created by Zhaomike on 16/3/17.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/MMPrinterDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // MMPrinterDemo
4 | //
5 | // Created by Zhaomike on 16/3/17.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/MMPrinterDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // MMPrinterDemo
4 | //
5 | // Created by Zhaomike on 16/3/17.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/MMPrinterDemo/PrinterManager/MMQRCode.h:
--------------------------------------------------------------------------------
1 | //
2 | // MMQRCode.h
3 | // RevoSysAuto
4 | //
5 | // Created by Zhaomike on 16/1/20.
6 | // Copyright © 2016年 leyutech. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface MMQRCode : NSObject
13 |
14 | + (UIImage *)qrCodeWithString:(NSString *)string logoName:(NSString *)name size:(CGFloat)width;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/MMPrinterDemo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/MMPrinterDemoTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/MMPrinterDemoUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/MMPrinterDemo.xcodeproj/xcuserdata/Mike.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | MMPrinterDemo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | C8066CC61C9A4A1600DE1D90
16 |
17 | primary
18 |
19 |
20 | C8066CDF1C9A4A1600DE1D90
21 |
22 | primary
23 |
24 |
25 | C8066CEA1C9A4A1600DE1D90
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/MMPrinterDemo.xcodeproj/xcuserdata/MikeZhao.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | MMPrinterDemo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | C8066CC61C9A4A1600DE1D90
16 |
17 | primary
18 |
19 |
20 | C8066CDF1C9A4A1600DE1D90
21 |
22 | primary
23 |
24 |
25 | C8066CEA1C9A4A1600DE1D90
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/MMPrinterDemo/PrinterManager/MMSocketManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // MMSocketManager.h
3 | // MMPrinterDemo
4 | //
5 | // Created by Zhaomike on 16/3/17.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AsyncSocket.h"
11 |
12 | @interface MMSocketManager : NSObject
13 |
14 | //打印
15 | @property (strong, nonatomic) void (^blockPrintData)();
16 | //检查缓存数据(连接断开时,检查缓存数据)
17 | //可能遇到的问题
18 | //打印机只能同时连接一个socket
19 | //1.wifi打印机:当wifi打印机一直连接着一个socket01,这时如果另一个socket02想要连接时,会将socket01会断开,连上socket02,可以正常打印
20 | //2.有线打印机:当wifi打印机一直连接着一个socket01,这时如果另一个socket02想要连接时,会将socket01不会断开,因此socket02不能正常打印
21 | //对于问题2,将timeout设置为10,连接10秒连不上断开,检查数据,如果有数据,再次连接.,同时设置[sock disconnectAfterWriting];(写入数据后连接断开)
22 | @property (strong, nonatomic) void (^blockCheckData)();
23 |
24 | //连接打印机
25 | - (void)socketConnectToPrint:(NSString *)host port:(UInt16)port timeout:(NSTimeInterval)timeout;
26 | //发送数据
27 | - (void)socketWriteData:(NSData *)data;
28 | //检查是否连接
29 | - (BOOL)socketIsConnect;
30 | //断开连接
31 | - (void)socketDisconnectSocket;
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/MMPrinterDemoTests/MMPrinterDemoTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // MMPrinterDemoTests.m
3 | // MMPrinterDemoTests
4 | //
5 | // Created by Zhaomike on 16/3/17.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MMPrinterDemoTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation MMPrinterDemoTests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 | // Put setup code here. This method is called before the invocation of each test method in the class.
20 | }
21 |
22 | - (void)tearDown {
23 | // Put teardown code here. This method is called after the invocation of each test method in the class.
24 | [super tearDown];
25 | }
26 |
27 | - (void)testExample {
28 | // This is an example of a functional test case.
29 | // Use XCTAssert and related functions to verify your tests produce the correct results.
30 | }
31 |
32 | - (void)testPerformanceExample {
33 | // This is an example of a performance test case.
34 | [self measureBlock:^{
35 | // Put the code you want to measure the time of here.
36 | }];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/MMPrinterDemo/PrinterManager/MMReceiptManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // MMReceiptManager.h
3 | // MMPrinterDemo
4 | //
5 | // Created by Zhaomike on 16/3/18.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "MMPrinterManager.h"
11 | #import "MMSocketManager.h"
12 |
13 | @interface MMReceiptManager : NSObject
14 |
15 | @property (nonatomic, strong) MMSocketManager *asynaSocket;
16 | @property (nonatomic, strong) MMPrinterManager *printerManager;
17 |
18 | - (instancetype)initWithHost:(NSString *)host port:(UInt16)port timeout:(NSTimeInterval)timeout;
19 | - (void)connectWithHost:(NSString *)host port:(UInt16)port timeout:(NSTimeInterval)timeout;
20 | //基础设置
21 | - (void)basicSetting;
22 | //清空缓存数据
23 | - (void)clearData;
24 | //写入单行文字
25 | - (void)writeData_title:(NSString *)title Scale:(kCharScale)scale Type:(kAlignmentType)type;
26 | //写入多行文字
27 | - (void)writeData_items:(NSArray *)items;
28 | //打印图片
29 | - (void)writeData_image:(UIImage *)image alignment:(kAlignmentType)alignment maxWidth:(CGFloat)maxWidth;
30 | //条目,菜单,有间隔
31 | - (void)writeData_content:(NSArray *)items;
32 | //打印分割线
33 | - (void)writeData_line;
34 | //打开钱箱
35 | - (void)openCashDrawer;
36 | //打印小票
37 | - (void)printReceipt;
38 | @end
39 |
--------------------------------------------------------------------------------
/MMPrinterDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/MMPrinterDemoUITests/MMPrinterDemoUITests.m:
--------------------------------------------------------------------------------
1 | //
2 | // MMPrinterDemoUITests.m
3 | // MMPrinterDemoUITests
4 | //
5 | // Created by Zhaomike on 16/3/17.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MMPrinterDemoUITests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation MMPrinterDemoUITests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 |
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 |
22 | // In UI tests it is usually best to stop immediately when a failure occurs.
23 | self.continueAfterFailure = NO;
24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
25 | [[[XCUIApplication alloc] init] launch];
26 |
27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
28 | }
29 |
30 | - (void)tearDown {
31 | // Put teardown code here. This method is called after the invocation of each test method in the class.
32 | [super tearDown];
33 | }
34 |
35 | - (void)testExample {
36 | // Use recording to get started writing UI tests.
37 | // Use XCTAssert and related functions to verify your tests produce the correct results.
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/MMPrinterDemo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/MMPrinterDemo/PrinterManager/IGThermalSupport.h:
--------------------------------------------------------------------------------
1 | //
2 | // IGThermalSupport.h
3 | //
4 | // This class is released in the MIT license.
5 | // Created by Chris Chan in 12 Aug 2012.
6 | // Copyright (c) 2012 IGPSD Ltd.
7 | //
8 | // https://github.com/moming2k/ThermalPrinterKit.git
9 | //
10 | // Version 1.0.3
11 |
12 | #import
13 | #import
14 |
15 | typedef enum {
16 | ALPHA = 0,
17 | BLUE = 1,
18 | GREEN = 2,
19 | RED = 3
20 | } PIXELS;
21 |
22 | @interface IGThermalSupport : NSObject
23 |
24 | + (NSData *) imageToThermalData:(UIImage*)image;
25 | + (CGContextRef) newBitmapRGBA8ContextFromImage:(CGImageRef) image;
26 | + (NSData *)cutLine;
27 | + (NSData *)feedLines:(int)lines;
28 | + (UIImage*)mergeImage:(UIImage*)first withShopLogo:(UIImage*)shopLogo withColorType:(NSString*)colorType withNumber:(int)number;
29 | + (UIImage*)mergeImageQrcode:(UIImage*)first withShopLogo:(UIImage*)shopLogo withImageInfo:(UIImage*)imageInfo withQRCode:(NSString*)qrcode withColorType:(NSString*)colorType withNumber:(int)number withShopName:(NSString*)shopName withShopInfo:(NSString*)shopInfo withTicketTime:(NSString*)ticketTime withTicketDetail:(NSString*)ticketDetail;
30 | + (UIImage*)mergeImageStore:(UIImage*)first withImageInfo:(UIImage*)imageInfo withQRCode:(NSString*)qrcode withNumber:(int)number withShopName:(NSString*)shopName withShopInfo:(NSString*)shopInfo withTicketTime:(NSString*)ticketTime withTicketDetail:(NSString*)ticketDetail;
31 | + (UIImage*)drawText:(NSString*)text inImage:(UIImage*)image atPoint:(CGPoint)point withFont:(UIFont *)font;
32 | + (UIImage*)mergeImage2:(UIImage*)first withQRCode:(NSString*)qrcode withNumber:(int)number;
33 | + (UIImage *) receiptImage:(UIImage*)image withNumber:(int)number;
34 | + (CGFloat)widthOfString:(NSString *)string withFont:(UIFont *)font;
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/MMPrinterDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // MMPrinterDemo
4 | //
5 | // Created by Zhaomike on 16/3/17.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 | - (void)applicationWillResignActive:(UIApplication *)application {
24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
26 | }
27 |
28 | - (void)applicationDidEnterBackground:(UIApplication *)application {
29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | - (void)applicationWillEnterForeground:(UIApplication *)application {
34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
35 | }
36 |
37 | - (void)applicationDidBecomeActive:(UIApplication *)application {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/MMPrinterDemo/PrinterManager/MMSocketManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // MMSocketManager.m
3 | // MMPrinterDemo
4 | //
5 | // Created by Zhaomike on 16/3/17.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import "MMSocketManager.h"
10 |
11 | @interface MMSocketManager()
12 |
13 | @property (nonatomic, strong) AsyncSocket *asyncSocket;
14 |
15 | @end
16 |
17 | @implementation MMSocketManager
18 |
19 | -(instancetype)init {
20 | if (self = [super init]) {
21 | self.asyncSocket = [[AsyncSocket alloc] initWithDelegate:self];
22 | [self.asyncSocket setRunLoopModes:@[NSRunLoopCommonModes]];
23 | }
24 | return self;
25 | }
26 |
27 | //连接打印机
28 | -(void)socketConnectToPrint:(NSString *)host port:(UInt16)port timeout:(NSTimeInterval)timeout {
29 | NSError *error = nil;
30 | [self.asyncSocket connectToHost:host onPort:port withTimeout:timeout error:&error];
31 | }
32 | //检查连接状态
33 | -(BOOL)socketIsConnect
34 | {
35 | BOOL isConn = [self.asyncSocket isConnected];
36 | if (isConn) {
37 | NSLog(@"host=%@\nport=%hu\nlocalHost=%@\nlocalPort=%hu",self.asyncSocket.connectedHost,self.asyncSocket.connectedPort,self.asyncSocket.localHost,self.asyncSocket.localPort);
38 | }
39 | return isConn;
40 | }
41 | //发送数据
42 | - (void)socketWriteData:(NSData *)data {
43 | [self.asyncSocket writeData:data withTimeout:-1 tag:0];
44 | }
45 | //手动断开连接
46 | - (void)socketDisconnectSocket {
47 | [self.asyncSocket disconnect];
48 | }
49 |
50 | #pragma mark - Delegate
51 | - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
52 | if (_blockCheckData) {
53 | _blockPrintData();
54 | }
55 | [sock disconnectAfterWriting];
56 | }
57 |
58 | - (void)onSocketDidDisconnect:(AsyncSocket *)sock {
59 | if (_blockCheckData) {
60 | _blockCheckData();
61 | }
62 | }
63 | //
64 | - (BOOL)onSocketWillConnect:(AsyncSocket *)sock {
65 | return YES;
66 | }
67 |
68 | - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
69 | NSLog(@"读取完成");
70 | }
71 |
72 | - (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag {
73 | NSLog(@"写入完成");
74 | }
75 |
76 | - (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err {
77 | NSLog(@"即将断开");
78 | }
79 | @end
80 |
--------------------------------------------------------------------------------
/MMPrinterDemo/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // MMPrinterDemo
4 | //
5 | // Created by Zhaomike on 16/3/17.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "MMReceiptManager.h"
11 | #import "MMQRCode.h"
12 |
13 | @interface ViewController ()
14 |
15 | @property (strong, nonatomic) MMReceiptManager *manager;
16 |
17 | @property (weak, nonatomic) IBOutlet UITextField *ipTextField;
18 | @property (weak, nonatomic) IBOutlet UITextField *portTextField;
19 |
20 |
21 | @end
22 |
23 | @implementation ViewController
24 |
25 | - (void)viewDidLoad {
26 | [super viewDidLoad];
27 | // Do any additional setup after loading the view, typically from a nib.
28 | }
29 |
30 | - (IBAction)printReceipt:(id)sender {
31 |
32 | NSString *host = @"192.168.1.241";
33 | UInt16 port = 9100;
34 | // NSString *host = _ipTextField.text;
35 | // UInt16 port = (UInt16)[_portTextField.text integerValue];
36 | NSTimeInterval timeout = 10;
37 | MMReceiptManager *manager = [[MMReceiptManager alloc] initWithHost:host port:port timeout:timeout];
38 | [manager basicSetting];
39 | [manager writeData_title:@"肯德基" Scale:scale_2 Type:MiddleAlignment];
40 | [manager writeData_items:@[@"收银员:001", @"交易时间:2016-03-17", @"交易号:201603170001"]];
41 | [manager writeData_line];
42 | [manager writeData_content:@[@{@"key01":@"名称", @"key02":@"单价", @"key03":@"数量", @"key04":@"总价"}]];
43 | [manager writeData_line];
44 | [manager writeData_content:@[@{@"key01":@"汉堡", @"key02":@"10.00", @"key03":@"2", @"key04":@"20.00"}, @{@"key01":@"炸鸡", @"key02":@"8.00", @"key03":@"1", @"key04":@"8.00"}]];
45 | [manager writeData_line];
46 | [manager writeData_items:@[@"支付方式:现金", @"应收:28.00", @"实际:30.00", @"找零:2.00"]];
47 | UIImage *qrImage = [MMQRCode qrCodeWithString:@"www.google.cn" logoName:@"kfc.gif" size:400];
48 | [manager writeData_image:qrImage alignment:MiddleAlignment maxWidth:400];
49 | [manager openCashDrawer];
50 | [manager printReceipt];
51 |
52 | }
53 |
54 |
55 |
56 | - (void)didReceiveMemoryWarning {
57 | [super didReceiveMemoryWarning];
58 | // Dispose of any resources that can be recreated.
59 | }
60 |
61 | @end
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/MMPrinterDemo/PrinterManager/MMPrinterManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // MMPrinterManager.h
3 | // MMPrinterDemo
4 | //
5 | // Created by Zhaomike on 16/3/17.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | //横向或纵向移动单位
13 | #define DotSpace 0.1
14 | @interface MMPrinterManager : NSObject
15 |
16 | //对齐方式
17 | typedef enum :UInt8 {
18 | LeftAlignment = 0x30,
19 | MiddleAlignment = 0x31,
20 | RightAlignment = 0x32,
21 | }kAlignmentType;
22 |
23 | //页模式下打印区域方向
24 | typedef enum {
25 | LeftToRight = 0x30,
26 | DownToUP = 0x31,
27 | RightToLeft = 0x32,
28 | UpToDown = 0x33,
29 | }kPrintOrientation;
30 |
31 | //字符放大倍数
32 | typedef enum: UInt8 {
33 | scale_1 = 0x00,
34 | scale_2 = 0x11,
35 | scale_3 = 0x22,
36 | scale_4 = 0x33,
37 | scale_5 = 0x44,
38 | scale_6 = 0x55,
39 | scale_7 = 0x66,
40 | scale_8 = 0x77,
41 | }kCharScale;
42 |
43 | //选择字体
44 | typedef enum: UInt8 {
45 | standardFont = 0x30,
46 | smallerFont = 0x31,
47 | }kCharFont;
48 |
49 | //切纸模式
50 | typedef enum :UInt8 {
51 | fullCut = 0x30,
52 | halfCut = 0x31,
53 | feedPaperHalfCut = 0x42,
54 | }kCutPaperModel;
55 |
56 | //打印数据(文字图片信息)
57 | @property (nonatomic, strong) NSMutableData *sendData;
58 |
59 | //0.录入文字
60 | -(void)printAddText:(NSString *)text;
61 |
62 | //2.打印并换行
63 | -(void)printAndGotoNextLine;
64 |
65 | //11.设置绝对打印位置
66 | -(void)printAbsolutePosition:(NSInteger)location;
67 |
68 | //14.选择位图模式
69 | - (void)printBitmapModel:(UIImage *)bitmap;
70 |
71 | //16.设置默认行间距(约3.75mm)
72 | - (void)printDefaultLineSpace;
73 |
74 | //20.初始化打印机
75 | - (void)printInitialize;
76 |
77 | //24.打印并走纸
78 | - (void)printPrintAndFeedPaper:(CGFloat)space;
79 |
80 | //26.设置字号
81 | - (void)printSelectFont:(kCharFont)size;
82 |
83 | //28.设置成标准模式
84 | - (void)printSetStanderModel;
85 |
86 | //33.设置对齐方式
87 | -(void)printAlignmentType:(kAlignmentType)type;
88 |
89 | //38.产生钱箱控制脉冲
90 | -(void)printOpenCashDrawer;
91 |
92 | //43.选择字符大小
93 | -(void)printCharSize:(kCharScale)scale;
94 |
95 | //51.设置左边距
96 | - (void)printLeftMargin:(CGFloat)left;
97 |
98 | //52.设置横向和纵向移动单位
99 | - (void)printDotDistanceW:(CGFloat)w h:(CGFloat)h;
100 |
101 | //53.选择切纸模式并切纸
102 | -(void)printCutPaper:(kCutPaperModel)model Num:(UInt8)n;
103 |
104 | //54.设置每行打印宽度
105 | - (void)printAreaWidth:(CGFloat)width;
106 |
107 | @end
108 |
--------------------------------------------------------------------------------
/MMPrinterDemo/PrinterManager/MMQRCode.m:
--------------------------------------------------------------------------------
1 | //
2 | // MMQRCode.m
3 | // RevoSysAuto
4 | //
5 | // Created by Zhaomike on 16/1/20.
6 | // Copyright © 2016年 leyutech. All rights reserved.
7 | //
8 |
9 | #import "MMQRCode.h"
10 |
11 | @implementation MMQRCode
12 |
13 | + (UIImage *)qrCodeWithString:(NSString *)string logoName:(NSString *)name size:(CGFloat)width {
14 | if (string) {
15 | NSData *strData = [string dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO];
16 | //创建二维码滤镜
17 | CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
18 | [qrFilter setValue:strData forKey:@"inputMessage"];
19 | [qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"];
20 | CIImage *qrImage = qrFilter.outputImage;
21 | //颜色滤镜
22 | CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"];
23 | [colorFilter setDefaults];
24 | [colorFilter setValue:qrImage forKey:kCIInputImageKey];
25 | [colorFilter setValue:[CIColor colorWithRed:0 green:0 blue:0] forKey:@"inputColor0"];
26 | [colorFilter setValue:[CIColor colorWithRed:0.3 green:0.8 blue:0.2] forKey:@"inputColor1"];
27 | CIImage *colorImage = colorFilter.outputImage;
28 | //返回二维码
29 | CGFloat scale = width/31;
30 | UIImage *codeImage = [UIImage imageWithCIImage:[colorImage imageByApplyingTransform:CGAffineTransformMakeScale(scale, scale)]];
31 | //定制logo
32 | if (name) {
33 | UIImage *logo = [UIImage imageNamed:name];
34 | //二维码rect
35 | CGRect rect = CGRectMake(0, 0, codeImage.size.width, codeImage.size.height);
36 | UIGraphicsBeginImageContext(rect.size);
37 | [codeImage drawInRect:rect];
38 | //icon尺寸,UIBezierPath
39 | CGSize logoSize = CGSizeMake(rect.size.width*0.2, rect.size.height*0.2);
40 | CGFloat x = CGRectGetMidX(rect) - logoSize.width*0.5;
41 | CGFloat y = CGRectGetMidY(rect) - logoSize.height*0.5;
42 | CGRect logoFrame = CGRectMake(x, y, logoSize.width, logoSize.height);
43 | [[UIBezierPath bezierPathWithRoundedRect:logoFrame cornerRadius:10] addClip];
44 |
45 | [logo drawInRect:logoFrame];
46 | UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
47 | UIGraphicsEndImageContext();
48 | return resultImage;
49 | }
50 | return codeImage;
51 | }
52 | return nil;
53 | }
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/MMPrinterDemo/PrinterManager/MMPrinterManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // MMPrinterManager.m
3 | // MMPrinterDemo
4 | //
5 | // Created by Zhaomike on 16/3/17.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | #import "MMPrinterManager.h"
10 | #import "IGThermalSupport.h"
11 |
12 | @implementation MMPrinterManager
13 |
14 | -(instancetype)init {
15 | if (self = [super init]) {
16 | _sendData = [NSMutableData dataWithCapacity:0];
17 | }
18 | return self;
19 | }
20 |
21 | - (void)addBytesCommand:(const void *)command Length:(NSUInteger)length {
22 | [self.sendData appendBytes:command length:length];
23 | }
24 |
25 | //0.录入文字
26 | -(void)printAddText:(NSString *)text {
27 | NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
28 | NSData *data = [text dataUsingEncoding:enc];
29 | NSUInteger size = data.length;
30 | void *textdata = malloc(size);
31 | [data getBytes:textdata length:size];
32 | [self addBytesCommand:textdata Length:size];
33 | free(textdata);
34 | }
35 |
36 | //2.打印并换行
37 | -(void)printAndGotoNextLine {
38 | unsigned char data[] = {0x0A};
39 | [self addBytesCommand:data Length:1];
40 | }
41 |
42 | //11.设置绝对打印位置
43 | -(void)printAbsolutePosition:(NSInteger)location {
44 | unsigned char nL = location % 256;
45 | unsigned char nH = location / 256;
46 | unsigned char data[] = {0x1B, 0x24, nL, nH};
47 | [self addBytesCommand:data Length:4];
48 | }
49 |
50 | //14.选择位图模式
51 | - (void)printBitmapModel:(UIImage *)bitmap {
52 | NSData *data = [IGThermalSupport imageToThermalData:bitmap];
53 | NSUInteger size = data.length;
54 | void *picSize = malloc(size);
55 | [data getBytes:picSize length:size];
56 | [self addBytesCommand:picSize Length:size];
57 | free(picSize);
58 | }
59 |
60 | //16.设置默认行间距(约3.75mm)
61 | - (void)printDefaultLineSpace {
62 | unsigned char data[] = {0x1B,0x32};
63 | [self addBytesCommand:data Length:2];
64 | }
65 |
66 | //20.初始化打印机
67 | - (void)printInitialize {
68 | unsigned char data[] = {0x1B, 0x40};
69 | [self addBytesCommand:data Length:2];
70 | }
71 |
72 | //24.打印并走纸
73 | - (void)printPrintAndFeedPaper:(CGFloat)space {
74 | unsigned char n = (UInt8)(space/DotSpace);
75 | unsigned char data[] = {0x1B, 0x4A, n};
76 | [self addBytesCommand:data Length:3];
77 | }
78 |
79 | //26.设置字号
80 | - (void)printSelectFont:(kCharFont)size {
81 | unsigned char data[] = {0x1B,0x4D,size};
82 | [self addBytesCommand:data Length:3];
83 | }
84 |
85 | //28.设置成标准模式
86 | - (void)printSetStanderModel {
87 | unsigned char data[] = {0x1B,0x53};
88 | [self addBytesCommand:data Length:2];
89 | }
90 |
91 | //33.设置对齐方式
92 | -(void)printAlignmentType:(kAlignmentType)type {
93 | unsigned char data[] = {0x1B,0x61,type};
94 | [self addBytesCommand:data Length:3];
95 | }
96 |
97 | //38.产生钱箱控制脉冲
98 | -(void)printOpenCashDrawer {
99 | unsigned char data[5] = {0x1B, 0x70, 0x00, 0x80, 0xFF};
100 | [self addBytesCommand:data Length:5];
101 | }
102 |
103 | //43.选择字符大小
104 | -(void)printCharSize:(kCharScale)scale {
105 | unsigned char data[] = {0x0A,0x1D,0x21,scale};
106 | [self addBytesCommand:data Length:4];
107 | }
108 |
109 | //51.设置左边距
110 | - (void)printLeftMargin:(CGFloat)left {
111 | NSInteger t = left/DotSpace;
112 | unsigned char nL = t%256;
113 | unsigned char nH = t/256;
114 | unsigned char data[] = {0x1D,0x4C,nL,nH};
115 | [self addBytesCommand:data Length:4];
116 | }
117 |
118 | //52.设置横向和纵向移动单位
119 | - (void)printDotDistanceW:(CGFloat)w h:(CGFloat)h {
120 | unsigned char width = (unsigned char)(25.4/w);
121 | unsigned char height = (unsigned char)(25.4/h);
122 | unsigned char data[] = {0x1D,0x50,width,height};
123 | [self addBytesCommand:data Length:4];
124 | }
125 |
126 | //53.选择切纸模式并切纸
127 | -(void)printCutPaper:(kCutPaperModel)model Num:(UInt8)n {
128 | unsigned char m = 0;
129 | if (model == feedPaperHalfCut) {
130 | m = n;
131 | }
132 | unsigned char data[] = {0x1D, 0x56, model, m};
133 | [self addBytesCommand:data Length:4];
134 | }
135 |
136 | //54.设置每行打印宽度
137 | - (void)printAreaWidth:(CGFloat)width {
138 | unsigned char nL = (int)(width / DotSpace) % 256;
139 | unsigned char nH = (int)(width / DotSpace) / 256;
140 | unsigned char data[] = {0x1D,0x57,nL,nH};
141 | [self addBytesCommand:data Length:4];
142 | }
143 |
144 | @end
145 |
--------------------------------------------------------------------------------
/MMPrinterDemo.xcodeproj/xcuserdata/Mike.xcuserdatad/xcschemes/MMPrinterDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
59 |
60 |
61 |
62 |
63 |
64 |
74 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/MMPrinterDemo.xcodeproj/xcuserdata/MikeZhao.xcuserdatad/xcschemes/MMPrinterDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
59 |
60 |
61 |
62 |
63 |
64 |
74 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/MMPrinterDemo/PrinterManager/MMReceiptManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // MMReceiptManager.m
3 | // MMPrinterDemo
4 | //
5 | // Created by Zhaomike on 16/3/18.
6 | // Copyright © 2016年 mikezhao. All rights reserved.
7 | //
8 |
9 | //小票管理类,根据需求自行定制
10 | #import "MMReceiptManager.h"
11 |
12 | @implementation MMReceiptManager
13 |
14 | - (instancetype)initWithHost:(NSString *)host port:(UInt16)port timeout:(NSTimeInterval)timeout {
15 | if (self = [super init])
16 | {
17 | [self.asynaSocket socketConnectToPrint:host port:port timeout:timeout];
18 | }
19 | return self;
20 | }
21 | - (void)connectWithHost:(NSString *)host port:(UInt16)port timeout:(NSTimeInterval)timeout {
22 | [self.asynaSocket socketConnectToPrint:host port:port timeout:timeout];
23 | }
24 | - (MMSocketManager *)asynaSocket {
25 | if (!_asynaSocket) {
26 | _asynaSocket = [[MMSocketManager alloc] init];
27 | }
28 | return _asynaSocket;
29 | }
30 | - (MMPrinterManager *)printerManager {
31 | if (!_printerManager) {
32 | _printerManager = [[MMPrinterManager alloc] init];
33 | }
34 | return _printerManager;
35 | }
36 | //基础设置
37 | - (void)basicSetting {
38 | [self.printerManager printInitialize];
39 | [self.printerManager printSetStanderModel];
40 | [self.printerManager printDotDistanceW:DotSpace h:DotSpace];
41 | // [self.printerManager printLeftMargin:5.0];
42 | [self.printerManager printDefaultLineSpace];
43 | // [self.printerManager printAreaWidth:70];
44 | [self.printerManager printSelectFont:standardFont];
45 | }
46 | //清空缓存数据
47 | - (void)clearData {
48 | self.printerManager.sendData.length = 0;
49 | }
50 | //写入单行文字
51 | - (void)writeData_title:(NSString *)title Scale:(kCharScale)scale Type:(kAlignmentType)type {
52 | [_printerManager printCharSize:scale];
53 | [_printerManager printAlignmentType:type];
54 | [_printerManager printAddText:title];
55 | [_printerManager printAndGotoNextLine];
56 | }
57 | //写入多行文字
58 | - (void)writeData_items:(NSArray *)items {
59 | [self.printerManager printCharSize:scale_1];
60 | [_printerManager printAlignmentType:LeftAlignment];
61 | for (NSString *item in items) {
62 | [_printerManager printAddText:item];
63 | [_printerManager printAndGotoNextLine];
64 | }
65 | }
66 | //打印图片
67 | - (void)writeData_image:(UIImage *)image alignment:(kAlignmentType)alignment maxWidth:(CGFloat)maxWidth {
68 | [self.printerManager printAlignmentType:alignment];
69 | // UIImage *inImage = image;
70 | CGFloat width = image.size.width;
71 | if (width > maxWidth) {
72 | CGFloat height = image.size.height;
73 | CGFloat maxHeight = maxWidth * height / width;
74 | image = [self createCurrentImage:image width:maxWidth height:maxHeight];
75 | }
76 | [self.printerManager printBitmapModel:image];
77 | [self.printerManager printAndGotoNextLine];
78 | }
79 | // 缩放图片
80 | - (UIImage *)createCurrentImage:(UIImage *)inImage width:(CGFloat)width height:(CGFloat)height {
81 | CGSize size = CGSizeMake(width, height);
82 | UIGraphicsBeginImageContext(size);
83 | [inImage drawInRect:CGRectMake(0, 0, width, height)];
84 | UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
85 | UIGraphicsEndImageContext();
86 | return resultImage;
87 | }
88 |
89 | //func createCurrentImage(inImage:UIImage, width:CGFloat, height:CGFloat)->UIImage{
90 | // // let w = CGFloat(width)
91 | // // let h = CGFloat(height)
92 | // let size = CGSizeMake(width, height)
93 | // UIGraphicsBeginImageContext(size)
94 | // inImage.drawInRect(CGRectMake(0, 0, width, height))
95 | // let image = UIGraphicsGetImageFromCurrentImageContext()
96 | // UIGraphicsEndImageContext()
97 | // return image
98 | //}
99 |
100 | //条目,菜单,有间隔,如:
101 | // 炸鸡排 2 12.50 25.00
102 | - (void)writeData_content:(NSArray *)items {
103 | [self.printerManager printCharSize:scale_1];
104 | [_printerManager printAlignmentType:LeftAlignment];
105 | for (NSDictionary *dict in items) {
106 | [self writeData_spaceItem:dict];
107 | }
108 | }
109 | - (void)writeData_spaceItem:(NSDictionary *)item {
110 | [_printerManager printAddText:[item objectForKey:@"key01"]];
111 | [_printerManager printAbsolutePosition:350];
112 | [_printerManager printAddText:[item objectForKey:@"key02"]];
113 | [_printerManager printAbsolutePosition:500];
114 | [_printerManager printAddText:[item objectForKey:@"key03"]];
115 | [_printerManager printAbsolutePosition:640];
116 | [_printerManager printAddText:[item objectForKey:@"key04"]];
117 | [_printerManager printAndGotoNextLine];
118 | }
119 | //打印分割线
120 | - (void)writeData_line {
121 | [self.printerManager printAlignmentType:MiddleAlignment];
122 | [self.printerManager printAddText:@"------------------------------------------"];
123 | [self.printerManager printAndGotoNextLine];
124 | }
125 | //打开钱箱
126 | - (void)openCashDrawer {
127 | [self.printerManager printOpenCashDrawer];
128 | }
129 | //打印小票
130 | - (void)printReceipt {
131 | [self.printerManager printCutPaper:feedPaperHalfCut Num:12];
132 | [_asynaSocket socketWriteData:[self.printerManager sendData]];
133 | }
134 |
135 | @end
136 |
--------------------------------------------------------------------------------
/MMPrinterDemo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/MMPrinterDemo/PrinterManager/IGThermalSupport.m:
--------------------------------------------------------------------------------
1 | //
2 | // IGThermalSupport.m
3 | //
4 | // This class is released in the MIT license.
5 | // Created by Chris Chan in 12 Aug 2012.
6 | // Copyright (c) 2012 IGPSD Ltd.
7 | //
8 | // https://github.com/moming2k/ThermalPrinterKit.git
9 | //
10 | // Version 1.0.3
11 |
12 | #import "IGThermalSupport.h"
13 | //#import "FileManager.h"
14 | //#import "Barcode.h"
15 |
16 | @implementation IGThermalSupport
17 |
18 | + (NSData *) imageToThermalData:(UIImage*)image
19 | {
20 | CGImageRef imageRef = image.CGImage;
21 |
22 | // Create a bitmap context to draw the uiimage into
23 | CGContextRef context = [self newBitmapRGBA8ContextFromImage:imageRef];
24 |
25 | if(!context) {
26 | return NULL;
27 | }
28 |
29 | size_t width = CGImageGetWidth(imageRef);
30 | size_t height = CGImageGetHeight(imageRef);
31 |
32 | CGRect rect = CGRectMake(0, 0, width, height);
33 |
34 | // Draw image into the context to get the raw image data
35 | CGContextDrawImage(context, rect, imageRef);
36 |
37 | // Get a pointer to the data
38 | uint32_t *bitmapData = (uint32_t *)CGBitmapContextGetData(context);
39 |
40 | if(bitmapData) {
41 |
42 | uint8_t *m_imageData = (uint8_t *) malloc(width * height/8 + 8*height/8);
43 | memset(m_imageData, 0, width * height/8 + 8*height/8);
44 | int result_index = 0;
45 |
46 | for(int y = 0; (y + 24) < height; ) {
47 | m_imageData[result_index++] = 27;
48 | m_imageData[result_index++] = 51;
49 | m_imageData[result_index++] = 0;
50 |
51 | m_imageData[result_index++] = 27;
52 | m_imageData[result_index++] = 42;
53 | m_imageData[result_index++] = 33;
54 |
55 | m_imageData[result_index++] = width%256;
56 | m_imageData[result_index++] = width/256;
57 | for(int x = 0; x < width; x++) {
58 | int value = 0;
59 | for (int temp_y = 0 ; temp_y < 8; ++temp_y)
60 | {
61 | uint8_t *rgbaPixel = (uint8_t *) &bitmapData[(y+temp_y) * width + x];
62 | uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE];
63 |
64 | if (gray < 127)
65 | {
66 | value += 1<<(7-temp_y)&255;
67 | }
68 |
69 | }
70 | m_imageData[result_index++] = value;
71 |
72 | value = 0;
73 | for (int temp_y = 8 ; temp_y < 16; ++temp_y)
74 | {
75 | uint8_t *rgbaPixel = (uint8_t *) &bitmapData[(y+temp_y) * width + x];
76 | uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE];
77 |
78 | if (gray < 127)
79 | {
80 | value += 1<<(7-temp_y%8)&255;
81 | }
82 |
83 | }
84 | m_imageData[result_index++] = value;
85 |
86 | value = 0;
87 | for (int temp_y = 16 ; temp_y < 24; ++temp_y)
88 | {
89 | uint8_t *rgbaPixel = (uint8_t *) &bitmapData[(y+temp_y) * width + x];
90 | uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE];
91 |
92 | if (gray < 127)
93 | {
94 | value += 1<<(7-temp_y%8)&255;
95 | }
96 |
97 | }
98 | m_imageData[result_index++] = value;
99 | }
100 | m_imageData[result_index++] = 13;
101 | m_imageData[result_index++] = 10;
102 | y += 24;
103 | }
104 |
105 | NSMutableData *data = [[NSMutableData alloc] initWithCapacity:0];
106 | [data appendBytes:m_imageData length:result_index];
107 |
108 | free(bitmapData);
109 | return data;
110 |
111 | } else {
112 | NSLog(@"Error getting bitmap pixel data\n");
113 | }
114 |
115 | CGContextRelease(context);
116 |
117 | return nil ;
118 | }
119 |
120 |
121 | + (CGContextRef) newBitmapRGBA8ContextFromImage:(CGImageRef) image {
122 | CGContextRef context = NULL;
123 | CGColorSpaceRef colorSpace;
124 | uint32_t *bitmapData;
125 |
126 | size_t bitsPerPixel = 32;
127 | size_t bitsPerComponent = 8;
128 | size_t bytesPerPixel = bitsPerPixel / bitsPerComponent;
129 |
130 | size_t width = CGImageGetWidth(image);
131 | size_t height = CGImageGetHeight(image);
132 |
133 | size_t bytesPerRow = width * bytesPerPixel;
134 | size_t bufferLength = bytesPerRow * height;
135 |
136 | colorSpace = CGColorSpaceCreateDeviceRGB();
137 |
138 | if(!colorSpace) {
139 | NSLog(@"Error allocating color space RGB\n");
140 | return NULL;
141 | }
142 |
143 | // Allocate memory for image data
144 | bitmapData = (uint32_t *)malloc(bufferLength);
145 |
146 | if(!bitmapData) {
147 | NSLog(@"Error allocating memory for bitmap\n");
148 | CGColorSpaceRelease(colorSpace);
149 | return NULL;
150 | }
151 |
152 | //Create bitmap context
153 |
154 | context = CGBitmapContextCreate(bitmapData,
155 | width,
156 | height,
157 | bitsPerComponent,
158 | bytesPerRow,
159 | colorSpace,
160 | kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast); // RGBA
161 | if(!context) {
162 | free(bitmapData);
163 | NSLog(@"Bitmap context not created");
164 | }
165 |
166 | CGColorSpaceRelease(colorSpace);
167 |
168 | return context;
169 | }
170 |
171 | + (UIImage*)mergeImage:(UIImage*)first withShopLogo:(UIImage*)shopLogo withColorType:(NSString*)colorType withNumber:(int)number
172 | {
173 | // get size of the first image
174 | CGImageRef firstImageRef = first.CGImage;
175 | CGFloat firstWidth = CGImageGetWidth(firstImageRef);
176 | CGFloat firstHeight = CGImageGetHeight(firstImageRef);
177 |
178 | // get size of the logo image
179 | CGImageRef shopLogoImageRef = shopLogo.CGImage;
180 | CGFloat shopLogoWidth = CGImageGetWidth(shopLogoImageRef);
181 | CGFloat shopLogoHeight = CGImageGetHeight(shopLogoImageRef);
182 |
183 | // get size of the number image
184 | int first_num = number/100;
185 | int secord_num = (number - first_num*100)/10;
186 | int third_num = number - first_num*100 - secord_num*10;
187 |
188 | UIImage *ticket_type = [UIImage imageNamed:[NSString stringWithFormat:@"char-%@",colorType]];
189 | UIImage *first_number = [UIImage imageNamed:[NSString stringWithFormat:@"char-%i",first_num]];
190 | UIImage *secord_number = [UIImage imageNamed:[NSString stringWithFormat:@"char-%i",secord_num]];
191 | UIImage *third_number = [UIImage imageNamed:[NSString stringWithFormat:@"char-%i",third_num]];
192 |
193 | CGImageRef secondImageRef = first_number.CGImage;
194 | CGFloat secondWidth = CGImageGetWidth(secondImageRef);
195 | CGFloat secondHeight = CGImageGetHeight(secondImageRef);
196 |
197 | // build merged size
198 | CGSize mergedSize = CGSizeMake(530, firstHeight + shopLogoHeight);
199 | // CGSize mergedSize = CGSizeMake(MAX(firstWidth, shopLogoWidth), MAX(firstHeight, shopLogoHeight));
200 |
201 | // capture image context ref
202 | UIGraphicsBeginImageContext(mergedSize);
203 |
204 | //Draw images onto the context
205 | [first drawInRect:CGRectMake(0, 0, firstWidth, firstHeight)];
206 | [shopLogo drawInRect:CGRectMake(0, firstHeight, shopLogoWidth, shopLogoHeight)];
207 | [ticket_type drawInRect:CGRectMake(220, 280, secondWidth, secondHeight)];
208 | [first_number drawInRect:CGRectMake(280, 280, secondWidth, secondHeight)];
209 | [secord_number drawInRect:CGRectMake(340, 280, secondWidth, secondHeight)];
210 | [third_number drawInRect:CGRectMake(400, 280, secondWidth, secondHeight)];
211 |
212 | // assign context to new UIImage
213 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
214 |
215 | // end context
216 | UIGraphicsEndImageContext();
217 |
218 | return newImage;
219 | }
220 |
221 | /*
222 | + (UIImage*)mergeImageQrcode:(UIImage*)first withShopLogo:(UIImage*)shopLogo withImageInfo:(UIImage*)imageInfo withQRCode:(NSString*)qrcode withColorType:(NSString*)colorType withNumber:(int)number withShopName:(NSString*)shopName withShopInfo:(NSString*)shopInfo withTicketTime:(NSString*)ticketTime withTicketDetail:(NSString*)ticketDetail
223 | {
224 | // get size of the first image
225 | CGImageRef firstImageRef = first.CGImage;
226 | CGFloat firstWidth = CGImageGetWidth(firstImageRef);
227 | CGFloat firstHeight = CGImageGetHeight(firstImageRef);
228 |
229 | // get size of the logo image
230 | CGImageRef shopLogoImageRef = shopLogo.CGImage;
231 | CGFloat shopLogoWidth = CGImageGetWidth(shopLogoImageRef);
232 | CGFloat shopLogoHeight = CGImageGetHeight(shopLogoImageRef);
233 |
234 | // get size of the number image
235 | int first_num = number/100;
236 | int secord_num = (number - first_num*100)/10;
237 | int third_num = number - first_num*100 - secord_num*10;
238 |
239 | UIImage *ticket_bg = [UIImage imageNamed:[NSString stringWithFormat:@"ticket_white_bg"]];
240 | UIImage *ticket_type = [UIImage imageNamed:[NSString stringWithFormat:@"char-%@",colorType]];
241 | UIImage *first_number = [UIImage imageNamed:[NSString stringWithFormat:@"char-%i",first_num]];
242 | UIImage *secord_number = [UIImage imageNamed:[NSString stringWithFormat:@"char-%i",secord_num]];
243 | UIImage *third_number = [UIImage imageNamed:[NSString stringWithFormat:@"char-%i",third_num]];
244 |
245 | CGImageRef secondImageRef = first_number.CGImage;
246 | CGFloat secondWidth = CGImageGetWidth(secondImageRef);
247 | CGFloat secondHeight = CGImageGetHeight(secondImageRef);
248 |
249 | // get size of the info image
250 | CGImageRef infoImageRef = imageInfo.CGImage;
251 | CGFloat infoWidth = CGImageGetWidth(infoImageRef);
252 | CGFloat infoHeight = CGImageGetHeight(infoImageRef);
253 | CGFloat info_y = firstHeight + shopLogoHeight + 100;
254 |
255 | // gen qr code
256 | Barcode *barcode = [[Barcode alloc] init];
257 | [barcode setupQRCode:qrcode];
258 | UIImage *image_qrcode = barcode.qRBarcode;
259 | CGFloat qrcode_y = info_y + infoHeight + 20;
260 |
261 | // build merged size
262 | CGSize mergedSize = CGSizeMake(520, qrcode_y + 200);
263 | // CGSize mergedSize = CGSizeMake(MAX(firstWidth, secondWidth), MAX(firstHeight, secondHeight));
264 |
265 | // capture image context ref
266 | UIGraphicsBeginImageContext(mergedSize);
267 |
268 | //Draw images onto the context
269 | [ticket_bg drawInRect:CGRectMake(0, 0, firstWidth, qrcode_y + 200)];
270 | [first drawInRect:CGRectMake(0, 0, firstWidth, firstHeight)];
271 | [shopLogo drawInRect:CGRectMake(0, firstHeight, shopLogoWidth, shopLogoHeight)];
272 | [ticket_type drawInRect:CGRectMake(220, 280, secondWidth, secondHeight)];
273 | [first_number drawInRect:CGRectMake(280, 280, secondWidth, secondHeight)];
274 | [secord_number drawInRect:CGRectMake(340, 280, secondWidth, secondHeight)];
275 | [third_number drawInRect:CGRectMake(400, 280, secondWidth, secondHeight)];
276 | [imageInfo drawInRect:CGRectMake(0, info_y, infoWidth, infoHeight)];
277 | [image_qrcode drawInRect:CGRectMake(25, qrcode_y, 200, 200)];
278 |
279 |
280 | // assign context to new UIImage
281 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
282 |
283 | UIFont *font = [UIFont boldSystemFontOfSize:18];
284 | CGFloat textwidth = [IGThermalSupport widthOfString:shopName withFont:font];
285 | UIImage *newImageWithText = [IGThermalSupport drawText:shopName inImage:newImage atPoint:CGPointMake((530 - textwidth)/2, firstHeight + shopLogoHeight + 20) withFont:(UIFont *)font];
286 | textwidth = [IGThermalSupport widthOfString:shopInfo withFont:font];
287 | UIImage *newImageWithText1 = [IGThermalSupport drawText:shopInfo inImage:newImageWithText atPoint:CGPointMake((530 - textwidth)/2, firstHeight + shopLogoHeight + 40) withFont:(UIFont *)font];
288 | textwidth = [IGThermalSupport widthOfString:ticketTime withFont:font];
289 | UIImage *newImageWithText2 = [IGThermalSupport drawText:ticketTime inImage:newImageWithText1 atPoint:CGPointMake((530 - textwidth)/2, firstHeight + shopLogoHeight + 60) withFont:(UIFont *)font];
290 | textwidth = [IGThermalSupport widthOfString:ticketDetail withFont:font];
291 | UIImage *newImageWithText3 = [IGThermalSupport drawText:ticketDetail inImage:newImageWithText2 atPoint:CGPointMake(230, qrcode_y + 10) withFont:(UIFont *)font];
292 |
293 | // end context
294 | UIGraphicsEndImageContext();
295 |
296 | return newImageWithText3;
297 | }
298 | */
299 | /*
300 | + (UIImage*)mergeImageStore:(UIImage*)first withImageInfo:(UIImage*)imageInfo withQRCode:(NSString*)qrcode withNumber:(int)number withShopName:(NSString*)shopName withShopInfo:(NSString*)shopInfo withTicketTime:(NSString*)ticketTime withTicketDetail:(NSString*)ticketDetail
301 | {
302 | // get size of the first image
303 | CGImageRef firstImageRef = first.CGImage;
304 | CGFloat firstWidth = CGImageGetWidth(firstImageRef);
305 | CGFloat firstHeight = CGImageGetHeight(firstImageRef);
306 |
307 | // get size of the number image
308 | int first_num = number/100;
309 | int secord_num = (number - first_num*100)/10;
310 | int third_num = number - first_num*100 - secord_num*10;
311 |
312 | UIImage *ticket_bg = [UIImage imageNamed:[NSString stringWithFormat:@"ticket_white_bg"]];
313 | UIImage *first_number = [UIImage imageNamed:[NSString stringWithFormat:@"ticket_%i",first_num]];
314 | UIImage *secord_number = [UIImage imageNamed:[NSString stringWithFormat:@"ticket_%i",secord_num]];
315 | UIImage *third_number = [UIImage imageNamed:[NSString stringWithFormat:@"ticket_%i",third_num]];
316 |
317 | CGImageRef secondImageRef = first_number.CGImage;
318 | CGFloat secondWidth = CGImageGetWidth(secondImageRef);
319 | CGFloat secondHeight = CGImageGetHeight(secondImageRef);
320 |
321 | // get size of the info image
322 | CGImageRef infoImageRef = imageInfo.CGImage;
323 | CGFloat infoWidth = CGImageGetWidth(infoImageRef);
324 | CGFloat infoHeight = CGImageGetHeight(infoImageRef);
325 | CGFloat info_y = firstHeight + 100;
326 |
327 | // gen qr code
328 | Barcode *barcode = [[Barcode alloc] init];
329 | [barcode setupQRCode:qrcode];
330 | UIImage *image_qrcode = barcode.qRBarcode;
331 | CGFloat qrcode_y = info_y + infoHeight + 20;
332 |
333 | // build merged size
334 | CGSize mergedSize = CGSizeMake(520, qrcode_y + 200);
335 | // CGSize mergedSize = CGSizeMake(MAX(firstWidth, secondWidth), MAX(firstHeight, secondHeight));
336 |
337 | // capture image context ref
338 | UIGraphicsBeginImageContext(mergedSize);
339 |
340 | //Draw images onto the context
341 | [ticket_bg drawInRect:CGRectMake(0, 0, firstWidth, qrcode_y + 200)];
342 | [first drawInRect:CGRectMake(0, 0, firstWidth, firstHeight)];
343 | [first_number drawInRect:CGRectMake(270, 230, secondWidth, secondHeight)];
344 | [secord_number drawInRect:CGRectMake(340, 230, secondWidth, secondHeight)];
345 | [third_number drawInRect:CGRectMake(410, 230, secondWidth, secondHeight)];
346 | [imageInfo drawInRect:CGRectMake(0, info_y, infoWidth, infoHeight)];
347 | [image_qrcode drawInRect:CGRectMake(25, qrcode_y, 200, 200)];
348 |
349 |
350 | // assign context to new UIImage
351 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
352 |
353 | UIFont *font = [UIFont boldSystemFontOfSize:18];
354 | CGFloat textwidth = [IGThermalSupport widthOfString:shopName withFont:font];
355 | UIImage *newImageWithText = [IGThermalSupport drawText:shopName inImage:newImage atPoint:CGPointMake((530 - textwidth)/2, firstHeight + 20) withFont:(UIFont *)font];
356 | textwidth = [IGThermalSupport widthOfString:shopInfo withFont:font];
357 | UIImage *newImageWithText1 = [IGThermalSupport drawText:shopInfo inImage:newImageWithText atPoint:CGPointMake((530 - textwidth)/2, firstHeight + 40) withFont:(UIFont *)font];
358 | textwidth = [IGThermalSupport widthOfString:ticketTime withFont:font];
359 | UIImage *newImageWithText2 = [IGThermalSupport drawText:ticketTime inImage:newImageWithText1 atPoint:CGPointMake((530 - textwidth)/2, firstHeight + 60) withFont:(UIFont *)font];
360 | textwidth = [IGThermalSupport widthOfString:ticketDetail withFont:font];
361 | UIImage *newImageWithText3 = [IGThermalSupport drawText:ticketDetail inImage:newImageWithText2 atPoint:CGPointMake(230, qrcode_y + 10) withFont:(UIFont *)font];
362 |
363 | // end context
364 | UIGraphicsEndImageContext();
365 |
366 | return newImageWithText3;
367 | }
368 | */
369 |
370 | + (CGFloat)widthOfString:(NSString *)string withFont:(UIFont *)font
371 | {
372 | NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
373 | return [[[NSAttributedString alloc] initWithString:string attributes:attributes] size].width;
374 | }
375 |
376 | + (UIImage*)drawText:(NSString*)text inImage:(UIImage*)image atPoint:(CGPoint)point withFont:(UIFont *)font
377 | {
378 | UIGraphicsBeginImageContext(image.size);
379 | [image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
380 | CGRect rect = CGRectMake(point.x, point.y, image.size.width, image.size.height);
381 | [[UIColor blackColor] set];
382 | [text drawInRect:CGRectIntegral(rect) withAttributes:@{NSFontAttributeName:font}];
383 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
384 | UIGraphicsEndImageContext();
385 |
386 | return newImage;
387 | }
388 |
389 | + (UIImage*)mergeImage2:(UIImage*)first withNumber:(int)number
390 | {
391 | // get size of the first image
392 |
393 | CGImageRef firstImageRef = first.CGImage;
394 | CGFloat firstWidth = CGImageGetWidth(firstImageRef);
395 | CGFloat firstHeight = CGImageGetHeight(firstImageRef);
396 |
397 | // get size of the second image
398 |
399 | int first_num = number/100;
400 | int secord_num = (number - first_num*100)/10;
401 | int third_num = number - first_num*100 - secord_num*10;
402 |
403 | UIImage *first_number = [UIImage imageNamed:[NSString stringWithFormat:@"ticket_%i",first_num]];
404 | UIImage *secord_number = [UIImage imageNamed:[NSString stringWithFormat:@"ticket_%i",secord_num]];
405 | UIImage *third_number = [UIImage imageNamed:[NSString stringWithFormat:@"ticket_%i",third_num]];
406 |
407 | CGImageRef secondImageRef = first_number.CGImage ;
408 | CGFloat secondWidth = CGImageGetWidth(secondImageRef);
409 | CGFloat secondHeight = CGImageGetHeight(secondImageRef);
410 |
411 | // build merged size
412 | CGSize mergedSize = CGSizeMake(MAX(firstWidth, secondWidth), MAX(firstHeight, secondHeight));
413 |
414 | // capture image context ref
415 | UIGraphicsBeginImageContext(mergedSize);
416 |
417 | //Draw images onto the context
418 | [first drawInRect:CGRectMake(0, 0, firstWidth, firstHeight)];
419 | [first_number drawInRect:CGRectMake(270, 230, secondWidth, secondHeight)];
420 | [secord_number drawInRect:CGRectMake(340, 230, secondWidth, secondHeight)];
421 | [third_number drawInRect:CGRectMake(410, 230, secondWidth, secondHeight)];
422 |
423 | // assign context to new UIImage
424 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
425 |
426 | // end context
427 | UIGraphicsEndImageContext();
428 |
429 | return newImage;
430 | }
431 |
432 | + (NSData *)cutLine
433 | {
434 | int index = 0;
435 | NSMutableData *data = [[NSMutableData alloc] initWithCapacity:0];
436 | uint8_t *m_imageData = (uint8_t *) malloc(4);
437 | m_imageData[index++] = 29;
438 | m_imageData[index++] = 86;
439 | m_imageData[index++] = 65;
440 | m_imageData[index++] = 10;
441 | [data appendBytes:m_imageData length:4];
442 | return data;
443 |
444 | }
445 |
446 | + (NSData *)feedLines:(int)lines
447 | {
448 | int index = 0;
449 | NSMutableData *data = [[NSMutableData alloc] initWithCapacity:0];
450 | uint8_t *m_imageData = (uint8_t *) malloc(3);
451 | m_imageData[index++] = 27;
452 | m_imageData[index++] = 100;
453 | m_imageData[index++] = lines;
454 | [data appendBytes:m_imageData length:3];
455 | return data;
456 | }
457 |
458 | + (UIImage *) receiptImage:(UIImage*)image withNumber:(int)number
459 | {
460 | UIImage *result = image;
461 | return result;
462 |
463 | // UIImage *bottomImage = [UIImage imageNamed:@"bottom.png"]; //background image
464 | // UIImage *image = [UIImage imageNamed:@"top.png"]; //foreground image
465 | //
466 | // CGSize newSize = CGSizeMake(width, height);
467 | // UIGraphicsBeginImageContext( newSize );
468 | //
469 | // // Use existing opacity as is
470 | // [bottomImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
471 | //
472 | // // Apply supplied opacity if applicable
473 | // [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeNormal alpha:0.8];
474 | //
475 | // UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
476 | //
477 | // UIGraphicsEndImageContext();
478 | }
479 |
480 |
481 | @end
482 |
--------------------------------------------------------------------------------
/MMPrinterDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 279DD8971C9DA71B00CEA250 /* IGThermalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 279DD8961C9DA71B00CEA250 /* IGThermalSupport.m */; };
11 | 279DD89A1C9DA97900CEA250 /* MMQRCode.m in Sources */ = {isa = PBXBuildFile; fileRef = 279DD8991C9DA97900CEA250 /* MMQRCode.m */; };
12 | 279DD89E1C9DC05F00CEA250 /* kfc.gif in Resources */ = {isa = PBXBuildFile; fileRef = 279DD89D1C9DC05F00CEA250 /* kfc.gif */; };
13 | C8066CCC1C9A4A1600DE1D90 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C8066CCB1C9A4A1600DE1D90 /* main.m */; };
14 | C8066CCF1C9A4A1600DE1D90 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C8066CCE1C9A4A1600DE1D90 /* AppDelegate.m */; };
15 | C8066CD21C9A4A1600DE1D90 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C8066CD11C9A4A1600DE1D90 /* ViewController.m */; };
16 | C8066CD51C9A4A1600DE1D90 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C8066CD31C9A4A1600DE1D90 /* Main.storyboard */; };
17 | C8066CD71C9A4A1600DE1D90 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C8066CD61C9A4A1600DE1D90 /* Assets.xcassets */; };
18 | C8066CDA1C9A4A1600DE1D90 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C8066CD81C9A4A1600DE1D90 /* LaunchScreen.storyboard */; };
19 | C8066CE51C9A4A1600DE1D90 /* MMPrinterDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C8066CE41C9A4A1600DE1D90 /* MMPrinterDemoTests.m */; };
20 | C8066CF01C9A4A1600DE1D90 /* MMPrinterDemoUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = C8066CEF1C9A4A1600DE1D90 /* MMPrinterDemoUITests.m */; };
21 | C8066D001C9A4B4300DE1D90 /* AsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = C8066CFF1C9A4B4300DE1D90 /* AsyncSocket.m */; };
22 | C8066D061C9A4BBF00DE1D90 /* MMPrinterManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C8066D051C9A4BBF00DE1D90 /* MMPrinterManager.m */; };
23 | C8066D091C9A86D600DE1D90 /* MMSocketManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C8066D081C9A86D600DE1D90 /* MMSocketManager.m */; };
24 | C8AD0B7F1C9BA33100FFFAB6 /* MMReceiptManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C8AD0B7E1C9BA33100FFFAB6 /* MMReceiptManager.m */; };
25 | /* End PBXBuildFile section */
26 |
27 | /* Begin PBXContainerItemProxy section */
28 | C8066CE11C9A4A1600DE1D90 /* PBXContainerItemProxy */ = {
29 | isa = PBXContainerItemProxy;
30 | containerPortal = C8066CBF1C9A4A1600DE1D90 /* Project object */;
31 | proxyType = 1;
32 | remoteGlobalIDString = C8066CC61C9A4A1600DE1D90;
33 | remoteInfo = MMPrinterDemo;
34 | };
35 | C8066CEC1C9A4A1600DE1D90 /* PBXContainerItemProxy */ = {
36 | isa = PBXContainerItemProxy;
37 | containerPortal = C8066CBF1C9A4A1600DE1D90 /* Project object */;
38 | proxyType = 1;
39 | remoteGlobalIDString = C8066CC61C9A4A1600DE1D90;
40 | remoteInfo = MMPrinterDemo;
41 | };
42 | /* End PBXContainerItemProxy section */
43 |
44 | /* Begin PBXFileReference section */
45 | 279DD8951C9DA71B00CEA250 /* IGThermalSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGThermalSupport.h; sourceTree = ""; };
46 | 279DD8961C9DA71B00CEA250 /* IGThermalSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGThermalSupport.m; sourceTree = ""; };
47 | 279DD8981C9DA97900CEA250 /* MMQRCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMQRCode.h; sourceTree = ""; };
48 | 279DD8991C9DA97900CEA250 /* MMQRCode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMQRCode.m; sourceTree = ""; };
49 | 279DD89D1C9DC05F00CEA250 /* kfc.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = kfc.gif; sourceTree = ""; };
50 | C8066CC71C9A4A1600DE1D90 /* MMPrinterDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MMPrinterDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
51 | C8066CCB1C9A4A1600DE1D90 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
52 | C8066CCD1C9A4A1600DE1D90 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
53 | C8066CCE1C9A4A1600DE1D90 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
54 | C8066CD01C9A4A1600DE1D90 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
55 | C8066CD11C9A4A1600DE1D90 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
56 | C8066CD41C9A4A1600DE1D90 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
57 | C8066CD61C9A4A1600DE1D90 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
58 | C8066CD91C9A4A1600DE1D90 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
59 | C8066CDB1C9A4A1600DE1D90 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
60 | C8066CE01C9A4A1600DE1D90 /* MMPrinterDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MMPrinterDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
61 | C8066CE41C9A4A1600DE1D90 /* MMPrinterDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MMPrinterDemoTests.m; sourceTree = ""; };
62 | C8066CE61C9A4A1600DE1D90 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
63 | C8066CEB1C9A4A1600DE1D90 /* MMPrinterDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MMPrinterDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
64 | C8066CEF1C9A4A1600DE1D90 /* MMPrinterDemoUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MMPrinterDemoUITests.m; sourceTree = ""; };
65 | C8066CF11C9A4A1600DE1D90 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
66 | C8066CFE1C9A4B4300DE1D90 /* AsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncSocket.h; sourceTree = ""; };
67 | C8066CFF1C9A4B4300DE1D90 /* AsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AsyncSocket.m; sourceTree = ""; };
68 | C8066D041C9A4BBF00DE1D90 /* MMPrinterManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMPrinterManager.h; sourceTree = ""; };
69 | C8066D051C9A4BBF00DE1D90 /* MMPrinterManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMPrinterManager.m; sourceTree = ""; };
70 | C8066D071C9A86D600DE1D90 /* MMSocketManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMSocketManager.h; sourceTree = ""; };
71 | C8066D081C9A86D600DE1D90 /* MMSocketManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMSocketManager.m; sourceTree = ""; };
72 | C8AD0B7D1C9BA33100FFFAB6 /* MMReceiptManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMReceiptManager.h; sourceTree = ""; };
73 | C8AD0B7E1C9BA33100FFFAB6 /* MMReceiptManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMReceiptManager.m; sourceTree = ""; };
74 | /* End PBXFileReference section */
75 |
76 | /* Begin PBXFrameworksBuildPhase section */
77 | C8066CC41C9A4A1600DE1D90 /* Frameworks */ = {
78 | isa = PBXFrameworksBuildPhase;
79 | buildActionMask = 2147483647;
80 | files = (
81 | );
82 | runOnlyForDeploymentPostprocessing = 0;
83 | };
84 | C8066CDD1C9A4A1600DE1D90 /* Frameworks */ = {
85 | isa = PBXFrameworksBuildPhase;
86 | buildActionMask = 2147483647;
87 | files = (
88 | );
89 | runOnlyForDeploymentPostprocessing = 0;
90 | };
91 | C8066CE81C9A4A1600DE1D90 /* Frameworks */ = {
92 | isa = PBXFrameworksBuildPhase;
93 | buildActionMask = 2147483647;
94 | files = (
95 | );
96 | runOnlyForDeploymentPostprocessing = 0;
97 | };
98 | /* End PBXFrameworksBuildPhase section */
99 |
100 | /* Begin PBXGroup section */
101 | C8066CBE1C9A4A1600DE1D90 = {
102 | isa = PBXGroup;
103 | children = (
104 | C8066CC91C9A4A1600DE1D90 /* MMPrinterDemo */,
105 | C8066CE31C9A4A1600DE1D90 /* MMPrinterDemoTests */,
106 | C8066CEE1C9A4A1600DE1D90 /* MMPrinterDemoUITests */,
107 | C8066CC81C9A4A1600DE1D90 /* Products */,
108 | );
109 | sourceTree = "";
110 | };
111 | C8066CC81C9A4A1600DE1D90 /* Products */ = {
112 | isa = PBXGroup;
113 | children = (
114 | C8066CC71C9A4A1600DE1D90 /* MMPrinterDemo.app */,
115 | C8066CE01C9A4A1600DE1D90 /* MMPrinterDemoTests.xctest */,
116 | C8066CEB1C9A4A1600DE1D90 /* MMPrinterDemoUITests.xctest */,
117 | );
118 | name = Products;
119 | sourceTree = "";
120 | };
121 | C8066CC91C9A4A1600DE1D90 /* MMPrinterDemo */ = {
122 | isa = PBXGroup;
123 | children = (
124 | C8066CCD1C9A4A1600DE1D90 /* AppDelegate.h */,
125 | C8066CCE1C9A4A1600DE1D90 /* AppDelegate.m */,
126 | C8066CD01C9A4A1600DE1D90 /* ViewController.h */,
127 | C8066CD11C9A4A1600DE1D90 /* ViewController.m */,
128 | 279DD89D1C9DC05F00CEA250 /* kfc.gif */,
129 | C8066CFD1C9A4A5400DE1D90 /* PrinterManager */,
130 | C8066CD31C9A4A1600DE1D90 /* Main.storyboard */,
131 | C8066CD61C9A4A1600DE1D90 /* Assets.xcassets */,
132 | C8066CD81C9A4A1600DE1D90 /* LaunchScreen.storyboard */,
133 | C8066CDB1C9A4A1600DE1D90 /* Info.plist */,
134 | C8066CCA1C9A4A1600DE1D90 /* Supporting Files */,
135 | );
136 | path = MMPrinterDemo;
137 | sourceTree = "";
138 | };
139 | C8066CCA1C9A4A1600DE1D90 /* Supporting Files */ = {
140 | isa = PBXGroup;
141 | children = (
142 | C8066CCB1C9A4A1600DE1D90 /* main.m */,
143 | );
144 | name = "Supporting Files";
145 | sourceTree = "";
146 | };
147 | C8066CE31C9A4A1600DE1D90 /* MMPrinterDemoTests */ = {
148 | isa = PBXGroup;
149 | children = (
150 | C8066CE41C9A4A1600DE1D90 /* MMPrinterDemoTests.m */,
151 | C8066CE61C9A4A1600DE1D90 /* Info.plist */,
152 | );
153 | path = MMPrinterDemoTests;
154 | sourceTree = "";
155 | };
156 | C8066CEE1C9A4A1600DE1D90 /* MMPrinterDemoUITests */ = {
157 | isa = PBXGroup;
158 | children = (
159 | C8066CEF1C9A4A1600DE1D90 /* MMPrinterDemoUITests.m */,
160 | C8066CF11C9A4A1600DE1D90 /* Info.plist */,
161 | );
162 | path = MMPrinterDemoUITests;
163 | sourceTree = "";
164 | };
165 | C8066CFD1C9A4A5400DE1D90 /* PrinterManager */ = {
166 | isa = PBXGroup;
167 | children = (
168 | C8066CFE1C9A4B4300DE1D90 /* AsyncSocket.h */,
169 | C8066CFF1C9A4B4300DE1D90 /* AsyncSocket.m */,
170 | 279DD8951C9DA71B00CEA250 /* IGThermalSupport.h */,
171 | 279DD8961C9DA71B00CEA250 /* IGThermalSupport.m */,
172 | 279DD8981C9DA97900CEA250 /* MMQRCode.h */,
173 | 279DD8991C9DA97900CEA250 /* MMQRCode.m */,
174 | C8066D041C9A4BBF00DE1D90 /* MMPrinterManager.h */,
175 | C8066D051C9A4BBF00DE1D90 /* MMPrinterManager.m */,
176 | C8066D071C9A86D600DE1D90 /* MMSocketManager.h */,
177 | C8066D081C9A86D600DE1D90 /* MMSocketManager.m */,
178 | C8AD0B7D1C9BA33100FFFAB6 /* MMReceiptManager.h */,
179 | C8AD0B7E1C9BA33100FFFAB6 /* MMReceiptManager.m */,
180 | );
181 | path = PrinterManager;
182 | sourceTree = "";
183 | };
184 | /* End PBXGroup section */
185 |
186 | /* Begin PBXNativeTarget section */
187 | C8066CC61C9A4A1600DE1D90 /* MMPrinterDemo */ = {
188 | isa = PBXNativeTarget;
189 | buildConfigurationList = C8066CF41C9A4A1600DE1D90 /* Build configuration list for PBXNativeTarget "MMPrinterDemo" */;
190 | buildPhases = (
191 | C8066CC31C9A4A1600DE1D90 /* Sources */,
192 | C8066CC41C9A4A1600DE1D90 /* Frameworks */,
193 | C8066CC51C9A4A1600DE1D90 /* Resources */,
194 | );
195 | buildRules = (
196 | );
197 | dependencies = (
198 | );
199 | name = MMPrinterDemo;
200 | productName = MMPrinterDemo;
201 | productReference = C8066CC71C9A4A1600DE1D90 /* MMPrinterDemo.app */;
202 | productType = "com.apple.product-type.application";
203 | };
204 | C8066CDF1C9A4A1600DE1D90 /* MMPrinterDemoTests */ = {
205 | isa = PBXNativeTarget;
206 | buildConfigurationList = C8066CF71C9A4A1600DE1D90 /* Build configuration list for PBXNativeTarget "MMPrinterDemoTests" */;
207 | buildPhases = (
208 | C8066CDC1C9A4A1600DE1D90 /* Sources */,
209 | C8066CDD1C9A4A1600DE1D90 /* Frameworks */,
210 | C8066CDE1C9A4A1600DE1D90 /* Resources */,
211 | );
212 | buildRules = (
213 | );
214 | dependencies = (
215 | C8066CE21C9A4A1600DE1D90 /* PBXTargetDependency */,
216 | );
217 | name = MMPrinterDemoTests;
218 | productName = MMPrinterDemoTests;
219 | productReference = C8066CE01C9A4A1600DE1D90 /* MMPrinterDemoTests.xctest */;
220 | productType = "com.apple.product-type.bundle.unit-test";
221 | };
222 | C8066CEA1C9A4A1600DE1D90 /* MMPrinterDemoUITests */ = {
223 | isa = PBXNativeTarget;
224 | buildConfigurationList = C8066CFA1C9A4A1600DE1D90 /* Build configuration list for PBXNativeTarget "MMPrinterDemoUITests" */;
225 | buildPhases = (
226 | C8066CE71C9A4A1600DE1D90 /* Sources */,
227 | C8066CE81C9A4A1600DE1D90 /* Frameworks */,
228 | C8066CE91C9A4A1600DE1D90 /* Resources */,
229 | );
230 | buildRules = (
231 | );
232 | dependencies = (
233 | C8066CED1C9A4A1600DE1D90 /* PBXTargetDependency */,
234 | );
235 | name = MMPrinterDemoUITests;
236 | productName = MMPrinterDemoUITests;
237 | productReference = C8066CEB1C9A4A1600DE1D90 /* MMPrinterDemoUITests.xctest */;
238 | productType = "com.apple.product-type.bundle.ui-testing";
239 | };
240 | /* End PBXNativeTarget section */
241 |
242 | /* Begin PBXProject section */
243 | C8066CBF1C9A4A1600DE1D90 /* Project object */ = {
244 | isa = PBXProject;
245 | attributes = {
246 | LastUpgradeCheck = 0720;
247 | ORGANIZATIONNAME = mikezhao;
248 | TargetAttributes = {
249 | C8066CC61C9A4A1600DE1D90 = {
250 | CreatedOnToolsVersion = 7.2.1;
251 | };
252 | C8066CDF1C9A4A1600DE1D90 = {
253 | CreatedOnToolsVersion = 7.2.1;
254 | TestTargetID = C8066CC61C9A4A1600DE1D90;
255 | };
256 | C8066CEA1C9A4A1600DE1D90 = {
257 | CreatedOnToolsVersion = 7.2.1;
258 | TestTargetID = C8066CC61C9A4A1600DE1D90;
259 | };
260 | };
261 | };
262 | buildConfigurationList = C8066CC21C9A4A1600DE1D90 /* Build configuration list for PBXProject "MMPrinterDemo" */;
263 | compatibilityVersion = "Xcode 3.2";
264 | developmentRegion = English;
265 | hasScannedForEncodings = 0;
266 | knownRegions = (
267 | en,
268 | Base,
269 | );
270 | mainGroup = C8066CBE1C9A4A1600DE1D90;
271 | productRefGroup = C8066CC81C9A4A1600DE1D90 /* Products */;
272 | projectDirPath = "";
273 | projectRoot = "";
274 | targets = (
275 | C8066CC61C9A4A1600DE1D90 /* MMPrinterDemo */,
276 | C8066CDF1C9A4A1600DE1D90 /* MMPrinterDemoTests */,
277 | C8066CEA1C9A4A1600DE1D90 /* MMPrinterDemoUITests */,
278 | );
279 | };
280 | /* End PBXProject section */
281 |
282 | /* Begin PBXResourcesBuildPhase section */
283 | C8066CC51C9A4A1600DE1D90 /* Resources */ = {
284 | isa = PBXResourcesBuildPhase;
285 | buildActionMask = 2147483647;
286 | files = (
287 | C8066CDA1C9A4A1600DE1D90 /* LaunchScreen.storyboard in Resources */,
288 | C8066CD71C9A4A1600DE1D90 /* Assets.xcassets in Resources */,
289 | C8066CD51C9A4A1600DE1D90 /* Main.storyboard in Resources */,
290 | 279DD89E1C9DC05F00CEA250 /* kfc.gif in Resources */,
291 | );
292 | runOnlyForDeploymentPostprocessing = 0;
293 | };
294 | C8066CDE1C9A4A1600DE1D90 /* Resources */ = {
295 | isa = PBXResourcesBuildPhase;
296 | buildActionMask = 2147483647;
297 | files = (
298 | );
299 | runOnlyForDeploymentPostprocessing = 0;
300 | };
301 | C8066CE91C9A4A1600DE1D90 /* Resources */ = {
302 | isa = PBXResourcesBuildPhase;
303 | buildActionMask = 2147483647;
304 | files = (
305 | );
306 | runOnlyForDeploymentPostprocessing = 0;
307 | };
308 | /* End PBXResourcesBuildPhase section */
309 |
310 | /* Begin PBXSourcesBuildPhase section */
311 | C8066CC31C9A4A1600DE1D90 /* Sources */ = {
312 | isa = PBXSourcesBuildPhase;
313 | buildActionMask = 2147483647;
314 | files = (
315 | C8066CD21C9A4A1600DE1D90 /* ViewController.m in Sources */,
316 | 279DD89A1C9DA97900CEA250 /* MMQRCode.m in Sources */,
317 | C8066CCF1C9A4A1600DE1D90 /* AppDelegate.m in Sources */,
318 | C8066D091C9A86D600DE1D90 /* MMSocketManager.m in Sources */,
319 | C8066D061C9A4BBF00DE1D90 /* MMPrinterManager.m in Sources */,
320 | C8AD0B7F1C9BA33100FFFAB6 /* MMReceiptManager.m in Sources */,
321 | C8066CCC1C9A4A1600DE1D90 /* main.m in Sources */,
322 | C8066D001C9A4B4300DE1D90 /* AsyncSocket.m in Sources */,
323 | 279DD8971C9DA71B00CEA250 /* IGThermalSupport.m in Sources */,
324 | );
325 | runOnlyForDeploymentPostprocessing = 0;
326 | };
327 | C8066CDC1C9A4A1600DE1D90 /* Sources */ = {
328 | isa = PBXSourcesBuildPhase;
329 | buildActionMask = 2147483647;
330 | files = (
331 | C8066CE51C9A4A1600DE1D90 /* MMPrinterDemoTests.m in Sources */,
332 | );
333 | runOnlyForDeploymentPostprocessing = 0;
334 | };
335 | C8066CE71C9A4A1600DE1D90 /* Sources */ = {
336 | isa = PBXSourcesBuildPhase;
337 | buildActionMask = 2147483647;
338 | files = (
339 | C8066CF01C9A4A1600DE1D90 /* MMPrinterDemoUITests.m in Sources */,
340 | );
341 | runOnlyForDeploymentPostprocessing = 0;
342 | };
343 | /* End PBXSourcesBuildPhase section */
344 |
345 | /* Begin PBXTargetDependency section */
346 | C8066CE21C9A4A1600DE1D90 /* PBXTargetDependency */ = {
347 | isa = PBXTargetDependency;
348 | target = C8066CC61C9A4A1600DE1D90 /* MMPrinterDemo */;
349 | targetProxy = C8066CE11C9A4A1600DE1D90 /* PBXContainerItemProxy */;
350 | };
351 | C8066CED1C9A4A1600DE1D90 /* PBXTargetDependency */ = {
352 | isa = PBXTargetDependency;
353 | target = C8066CC61C9A4A1600DE1D90 /* MMPrinterDemo */;
354 | targetProxy = C8066CEC1C9A4A1600DE1D90 /* PBXContainerItemProxy */;
355 | };
356 | /* End PBXTargetDependency section */
357 |
358 | /* Begin PBXVariantGroup section */
359 | C8066CD31C9A4A1600DE1D90 /* Main.storyboard */ = {
360 | isa = PBXVariantGroup;
361 | children = (
362 | C8066CD41C9A4A1600DE1D90 /* Base */,
363 | );
364 | name = Main.storyboard;
365 | sourceTree = "";
366 | };
367 | C8066CD81C9A4A1600DE1D90 /* LaunchScreen.storyboard */ = {
368 | isa = PBXVariantGroup;
369 | children = (
370 | C8066CD91C9A4A1600DE1D90 /* Base */,
371 | );
372 | name = LaunchScreen.storyboard;
373 | sourceTree = "";
374 | };
375 | /* End PBXVariantGroup section */
376 |
377 | /* Begin XCBuildConfiguration section */
378 | C8066CF21C9A4A1600DE1D90 /* Debug */ = {
379 | isa = XCBuildConfiguration;
380 | buildSettings = {
381 | ALWAYS_SEARCH_USER_PATHS = NO;
382 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
383 | CLANG_CXX_LIBRARY = "libc++";
384 | CLANG_ENABLE_MODULES = YES;
385 | CLANG_ENABLE_OBJC_ARC = YES;
386 | CLANG_WARN_BOOL_CONVERSION = YES;
387 | CLANG_WARN_CONSTANT_CONVERSION = YES;
388 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
389 | CLANG_WARN_EMPTY_BODY = YES;
390 | CLANG_WARN_ENUM_CONVERSION = YES;
391 | CLANG_WARN_INT_CONVERSION = YES;
392 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
393 | CLANG_WARN_UNREACHABLE_CODE = YES;
394 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
395 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
396 | COPY_PHASE_STRIP = NO;
397 | DEBUG_INFORMATION_FORMAT = dwarf;
398 | ENABLE_STRICT_OBJC_MSGSEND = YES;
399 | ENABLE_TESTABILITY = YES;
400 | GCC_C_LANGUAGE_STANDARD = gnu99;
401 | GCC_DYNAMIC_NO_PIC = NO;
402 | GCC_NO_COMMON_BLOCKS = YES;
403 | GCC_OPTIMIZATION_LEVEL = 0;
404 | GCC_PREPROCESSOR_DEFINITIONS = (
405 | "DEBUG=1",
406 | "$(inherited)",
407 | );
408 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
409 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
410 | GCC_WARN_UNDECLARED_SELECTOR = YES;
411 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
412 | GCC_WARN_UNUSED_FUNCTION = YES;
413 | GCC_WARN_UNUSED_VARIABLE = YES;
414 | IPHONEOS_DEPLOYMENT_TARGET = 9.2;
415 | MTL_ENABLE_DEBUG_INFO = YES;
416 | ONLY_ACTIVE_ARCH = YES;
417 | SDKROOT = iphoneos;
418 | };
419 | name = Debug;
420 | };
421 | C8066CF31C9A4A1600DE1D90 /* Release */ = {
422 | isa = XCBuildConfiguration;
423 | buildSettings = {
424 | ALWAYS_SEARCH_USER_PATHS = NO;
425 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
426 | CLANG_CXX_LIBRARY = "libc++";
427 | CLANG_ENABLE_MODULES = YES;
428 | CLANG_ENABLE_OBJC_ARC = YES;
429 | CLANG_WARN_BOOL_CONVERSION = YES;
430 | CLANG_WARN_CONSTANT_CONVERSION = YES;
431 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
432 | CLANG_WARN_EMPTY_BODY = YES;
433 | CLANG_WARN_ENUM_CONVERSION = YES;
434 | CLANG_WARN_INT_CONVERSION = YES;
435 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
436 | CLANG_WARN_UNREACHABLE_CODE = YES;
437 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
438 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
439 | COPY_PHASE_STRIP = NO;
440 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
441 | ENABLE_NS_ASSERTIONS = NO;
442 | ENABLE_STRICT_OBJC_MSGSEND = YES;
443 | GCC_C_LANGUAGE_STANDARD = gnu99;
444 | GCC_NO_COMMON_BLOCKS = YES;
445 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
446 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
447 | GCC_WARN_UNDECLARED_SELECTOR = YES;
448 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
449 | GCC_WARN_UNUSED_FUNCTION = YES;
450 | GCC_WARN_UNUSED_VARIABLE = YES;
451 | IPHONEOS_DEPLOYMENT_TARGET = 9.2;
452 | MTL_ENABLE_DEBUG_INFO = NO;
453 | SDKROOT = iphoneos;
454 | VALIDATE_PRODUCT = YES;
455 | };
456 | name = Release;
457 | };
458 | C8066CF51C9A4A1600DE1D90 /* Debug */ = {
459 | isa = XCBuildConfiguration;
460 | buildSettings = {
461 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
462 | CODE_SIGN_IDENTITY = "iPhone Developer";
463 | INFOPLIST_FILE = MMPrinterDemo/Info.plist;
464 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
465 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
466 | PRODUCT_BUNDLE_IDENTIFIER = com.mikezhao.MMPrinterDemo;
467 | PRODUCT_NAME = "$(TARGET_NAME)";
468 | };
469 | name = Debug;
470 | };
471 | C8066CF61C9A4A1600DE1D90 /* Release */ = {
472 | isa = XCBuildConfiguration;
473 | buildSettings = {
474 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
475 | CODE_SIGN_IDENTITY = "iPhone Developer";
476 | INFOPLIST_FILE = MMPrinterDemo/Info.plist;
477 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
478 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
479 | PRODUCT_BUNDLE_IDENTIFIER = com.mikezhao.MMPrinterDemo;
480 | PRODUCT_NAME = "$(TARGET_NAME)";
481 | };
482 | name = Release;
483 | };
484 | C8066CF81C9A4A1600DE1D90 /* Debug */ = {
485 | isa = XCBuildConfiguration;
486 | buildSettings = {
487 | BUNDLE_LOADER = "$(TEST_HOST)";
488 | INFOPLIST_FILE = MMPrinterDemoTests/Info.plist;
489 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
490 | PRODUCT_BUNDLE_IDENTIFIER = com.mikezhao.MMPrinterDemoTests;
491 | PRODUCT_NAME = "$(TARGET_NAME)";
492 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MMPrinterDemo.app/MMPrinterDemo";
493 | };
494 | name = Debug;
495 | };
496 | C8066CF91C9A4A1600DE1D90 /* Release */ = {
497 | isa = XCBuildConfiguration;
498 | buildSettings = {
499 | BUNDLE_LOADER = "$(TEST_HOST)";
500 | INFOPLIST_FILE = MMPrinterDemoTests/Info.plist;
501 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
502 | PRODUCT_BUNDLE_IDENTIFIER = com.mikezhao.MMPrinterDemoTests;
503 | PRODUCT_NAME = "$(TARGET_NAME)";
504 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MMPrinterDemo.app/MMPrinterDemo";
505 | };
506 | name = Release;
507 | };
508 | C8066CFB1C9A4A1600DE1D90 /* Debug */ = {
509 | isa = XCBuildConfiguration;
510 | buildSettings = {
511 | CODE_SIGN_IDENTITY = "iPhone Developer";
512 | INFOPLIST_FILE = MMPrinterDemoUITests/Info.plist;
513 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
514 | PRODUCT_BUNDLE_IDENTIFIER = com.mikezhao.MMPrinterDemoUITests;
515 | PRODUCT_NAME = "$(TARGET_NAME)";
516 | TEST_TARGET_NAME = MMPrinterDemo;
517 | USES_XCTRUNNER = YES;
518 | };
519 | name = Debug;
520 | };
521 | C8066CFC1C9A4A1600DE1D90 /* Release */ = {
522 | isa = XCBuildConfiguration;
523 | buildSettings = {
524 | CODE_SIGN_IDENTITY = "iPhone Developer";
525 | INFOPLIST_FILE = MMPrinterDemoUITests/Info.plist;
526 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
527 | PRODUCT_BUNDLE_IDENTIFIER = com.mikezhao.MMPrinterDemoUITests;
528 | PRODUCT_NAME = "$(TARGET_NAME)";
529 | TEST_TARGET_NAME = MMPrinterDemo;
530 | USES_XCTRUNNER = YES;
531 | };
532 | name = Release;
533 | };
534 | /* End XCBuildConfiguration section */
535 |
536 | /* Begin XCConfigurationList section */
537 | C8066CC21C9A4A1600DE1D90 /* Build configuration list for PBXProject "MMPrinterDemo" */ = {
538 | isa = XCConfigurationList;
539 | buildConfigurations = (
540 | C8066CF21C9A4A1600DE1D90 /* Debug */,
541 | C8066CF31C9A4A1600DE1D90 /* Release */,
542 | );
543 | defaultConfigurationIsVisible = 0;
544 | defaultConfigurationName = Release;
545 | };
546 | C8066CF41C9A4A1600DE1D90 /* Build configuration list for PBXNativeTarget "MMPrinterDemo" */ = {
547 | isa = XCConfigurationList;
548 | buildConfigurations = (
549 | C8066CF51C9A4A1600DE1D90 /* Debug */,
550 | C8066CF61C9A4A1600DE1D90 /* Release */,
551 | );
552 | defaultConfigurationIsVisible = 0;
553 | defaultConfigurationName = Release;
554 | };
555 | C8066CF71C9A4A1600DE1D90 /* Build configuration list for PBXNativeTarget "MMPrinterDemoTests" */ = {
556 | isa = XCConfigurationList;
557 | buildConfigurations = (
558 | C8066CF81C9A4A1600DE1D90 /* Debug */,
559 | C8066CF91C9A4A1600DE1D90 /* Release */,
560 | );
561 | defaultConfigurationIsVisible = 0;
562 | defaultConfigurationName = Release;
563 | };
564 | C8066CFA1C9A4A1600DE1D90 /* Build configuration list for PBXNativeTarget "MMPrinterDemoUITests" */ = {
565 | isa = XCConfigurationList;
566 | buildConfigurations = (
567 | C8066CFB1C9A4A1600DE1D90 /* Debug */,
568 | C8066CFC1C9A4A1600DE1D90 /* Release */,
569 | );
570 | defaultConfigurationIsVisible = 0;
571 | defaultConfigurationName = Release;
572 | };
573 | /* End XCConfigurationList section */
574 | };
575 | rootObject = C8066CBF1C9A4A1600DE1D90 /* Project object */;
576 | }
577 |
--------------------------------------------------------------------------------
/MMPrinterDemo/PrinterManager/AsyncSocket.h:
--------------------------------------------------------------------------------
1 | //
2 | // AsyncSocket.h
3 | //
4 | // This class is in the public domain.
5 | // Originally created by Dustin Voss on Wed Jan 29 2003.
6 | // Updated and maintained by Deusty Designs and the Mac development community.
7 | //
8 | // http://code.google.com/p/cocoaasyncsocket/
9 | //
10 |
11 | #import
12 |
13 | @class AsyncSocket;
14 | @class AsyncReadPacket;
15 | @class AsyncWritePacket;
16 |
17 | extern NSString *const AsyncSocketException;
18 | extern NSString *const AsyncSocketErrorDomain;
19 |
20 | typedef NS_ENUM(NSInteger, AsyncSocketError) {
21 | AsyncSocketCFSocketError = kCFSocketError, // From CFSocketError enum.
22 | AsyncSocketNoError = 0, // Never used.
23 | AsyncSocketCanceledError, // onSocketWillConnect: returned NO.
24 | AsyncSocketConnectTimeoutError,
25 | AsyncSocketReadMaxedOutError, // Reached set maxLength without completing
26 | AsyncSocketReadTimeoutError,
27 | AsyncSocketWriteTimeoutError
28 | };
29 |
30 | @protocol AsyncSocketDelegate
31 | @optional
32 |
33 | /**
34 | * In the event of an error, the socket is closed.
35 | * You may call "unreadData" during this call-back to get the last bit of data off the socket.
36 | * When connecting, this delegate method may be called
37 | * before"onSocket:didAcceptNewSocket:" or "onSocket:didConnectToHost:".
38 | **/
39 | - (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;
40 |
41 | /**
42 | * Called when a socket disconnects with or without error. If you want to release a socket after it disconnects,
43 | * do so here. It is not safe to do that during "onSocket:willDisconnectWithError:".
44 | *
45 | * If you call the disconnect method, and the socket wasn't already disconnected,
46 | * this delegate method will be called before the disconnect method returns.
47 | **/
48 | - (void)onSocketDidDisconnect:(AsyncSocket *)sock;
49 |
50 | /**
51 | * Called when a socket accepts a connection. Another socket is spawned to handle it. The new socket will have
52 | * the same delegate and will call "onSocket:didConnectToHost:port:".
53 | **/
54 | - (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
55 |
56 | /**
57 | * Called when a new socket is spawned to handle a connection. This method should return the run-loop of the
58 | * thread on which the new socket and its delegate should operate. If omitted, [NSRunLoop currentRunLoop] is used.
59 | **/
60 | - (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket;
61 |
62 | /**
63 | * Called when a socket is about to connect. This method should return YES to continue, or NO to abort.
64 | * If aborted, will result in AsyncSocketCanceledError.
65 | *
66 | * If the connectToHost:onPort:error: method was called, the delegate will be able to access and configure the
67 | * CFReadStream and CFWriteStream as desired prior to connection.
68 | *
69 | * If the connectToAddress:error: method was called, the delegate will be able to access and configure the
70 | * CFSocket and CFSocketNativeHandle (BSD socket) as desired prior to connection. You will be able to access and
71 | * configure the CFReadStream and CFWriteStream in the onSocket:didConnectToHost:port: method.
72 | **/
73 | - (BOOL)onSocketWillConnect:(AsyncSocket *)sock;
74 |
75 | /**
76 | * Called when a socket connects and is ready for reading and writing.
77 | * The host parameter will be an IP address, not a DNS name.
78 | **/
79 | - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port;
80 |
81 | /**
82 | * Called when a socket has completed reading the requested data into memory.
83 | * Not called if there is an error.
84 | **/
85 | - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;
86 |
87 | /**
88 | * Called when a socket has read in data, but has not yet completed the read.
89 | * This would occur if using readToData: or readToLength: methods.
90 | * It may be used to for things such as updating progress bars.
91 | **/
92 | - (void)onSocket:(AsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;
93 |
94 | /**
95 | * Called when a socket has completed writing the requested data. Not called if there is an error.
96 | **/
97 | - (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;
98 |
99 | /**
100 | * Called when a socket has written some data, but has not yet completed the entire write.
101 | * It may be used to for things such as updating progress bars.
102 | **/
103 | - (void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;
104 |
105 | /**
106 | * Called if a read operation has reached its timeout without completing.
107 | * This method allows you to optionally extend the timeout.
108 | * If you return a positive time interval (> 0) the read's timeout will be extended by the given amount.
109 | * If you don't implement this method, or return a non-positive time interval (<= 0) the read will timeout as usual.
110 | *
111 | * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method.
112 | * The length parameter is the number of bytes that have been read so far for the read operation.
113 | *
114 | * Note that this method may be called multiple times for a single read if you return positive numbers.
115 | **/
116 | - (NSTimeInterval)onSocket:(AsyncSocket *)sock
117 | shouldTimeoutReadWithTag:(long)tag
118 | elapsed:(NSTimeInterval)elapsed
119 | bytesDone:(NSUInteger)length;
120 |
121 | /**
122 | * Called if a write operation has reached its timeout without completing.
123 | * This method allows you to optionally extend the timeout.
124 | * If you return a positive time interval (> 0) the write's timeout will be extended by the given amount.
125 | * If you don't implement this method, or return a non-positive time interval (<= 0) the write will timeout as usual.
126 | *
127 | * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method.
128 | * The length parameter is the number of bytes that have been written so far for the write operation.
129 | *
130 | * Note that this method may be called multiple times for a single write if you return positive numbers.
131 | **/
132 | - (NSTimeInterval)onSocket:(AsyncSocket *)sock
133 | shouldTimeoutWriteWithTag:(long)tag
134 | elapsed:(NSTimeInterval)elapsed
135 | bytesDone:(NSUInteger)length;
136 |
137 | /**
138 | * Called after the socket has successfully completed SSL/TLS negotiation.
139 | * This method is not called unless you use the provided startTLS method.
140 | *
141 | * If a SSL/TLS negotiation fails (invalid certificate, etc) then the socket will immediately close,
142 | * and the onSocket:willDisconnectWithError: delegate method will be called with the specific SSL error code.
143 | **/
144 | - (void)onSocketDidSecure:(AsyncSocket *)sock;
145 |
146 | @end
147 |
148 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
149 | #pragma mark -
150 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
151 |
152 | @interface AsyncSocket : NSObject
153 | {
154 | CFSocketNativeHandle theNativeSocket4;
155 | CFSocketNativeHandle theNativeSocket6;
156 |
157 | CFSocketRef theSocket4; // IPv4 accept or connect socket
158 | CFSocketRef theSocket6; // IPv6 accept or connect socket
159 |
160 | CFReadStreamRef theReadStream;
161 | CFWriteStreamRef theWriteStream;
162 |
163 | CFRunLoopSourceRef theSource4; // For theSocket4
164 | CFRunLoopSourceRef theSource6; // For theSocket6
165 | CFRunLoopRef theRunLoop;
166 | CFSocketContext theContext;
167 | NSArray *theRunLoopModes;
168 |
169 | NSTimer *theConnectTimer;
170 |
171 | NSMutableArray *theReadQueue;
172 | AsyncReadPacket *theCurrentRead;
173 | NSTimer *theReadTimer;
174 | NSMutableData *partialReadBuffer;
175 |
176 | NSMutableArray *theWriteQueue;
177 | AsyncWritePacket *theCurrentWrite;
178 | NSTimer *theWriteTimer;
179 |
180 | id theDelegate;
181 | UInt16 theFlags;
182 |
183 | long theUserData;
184 | }
185 |
186 | - (id)init;
187 | - (id)initWithDelegate:(id)delegate;
188 | - (id)initWithDelegate:(id)delegate userData:(long)userData;
189 |
190 | /* String representation is long but has no "\n". */
191 | - (NSString *)description;
192 |
193 | /**
194 | * Use "canSafelySetDelegate" to see if there is any pending business (reads and writes) with the current delegate
195 | * before changing it. It is, of course, safe to change the delegate before connecting or accepting connections.
196 | **/
197 | - (id)delegate;
198 | - (BOOL)canSafelySetDelegate;
199 | - (void)setDelegate:(id)delegate;
200 |
201 | /* User data can be a long, or an id or void * cast to a long. */
202 | - (long)userData;
203 | - (void)setUserData:(long)userData;
204 |
205 | /* Don't use these to read or write. And don't close them either! */
206 | - (CFSocketRef)getCFSocket;
207 | - (CFReadStreamRef)getCFReadStream;
208 | - (CFWriteStreamRef)getCFWriteStream;
209 |
210 | // Once one of the accept or connect methods are called, the AsyncSocket instance is locked in
211 | // and the other accept/connect methods can't be called without disconnecting the socket first.
212 | // If the attempt fails or times out, these methods either return NO or
213 | // call "onSocket:willDisconnectWithError:" and "onSockedDidDisconnect:".
214 |
215 | // When an incoming connection is accepted, AsyncSocket invokes several delegate methods.
216 | // These methods are (in chronological order):
217 | // 1. onSocket:didAcceptNewSocket:
218 | // 2. onSocket:wantsRunLoopForNewSocket:
219 | // 3. onSocketWillConnect:
220 | //
221 | // Your server code will need to retain the accepted socket (if you want to accept it).
222 | // The best place to do this is probably in the onSocket:didAcceptNewSocket: method.
223 | //
224 | // After the read and write streams have been setup for the newly accepted socket,
225 | // the onSocket:didConnectToHost:port: method will be called on the proper run loop.
226 | //
227 | // Multithreading Note: If you're going to be moving the newly accepted socket to another run
228 | // loop by implementing onSocket:wantsRunLoopForNewSocket:, then you should wait until the
229 | // onSocket:didConnectToHost:port: method before calling read, write, or startTLS methods.
230 | // Otherwise read/write events are scheduled on the incorrect runloop, and chaos may ensue.
231 |
232 | /**
233 | * Tells the socket to begin listening and accepting connections on the given port.
234 | * When a connection comes in, the AsyncSocket instance will call the various delegate methods (see above).
235 | * The socket will listen on all available interfaces (e.g. wifi, ethernet, etc)
236 | **/
237 | - (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr;
238 |
239 | /**
240 | * This method is the same as acceptOnPort:error: with the additional option
241 | * of specifying which interface to listen on. So, for example, if you were writing code for a server that
242 | * has multiple IP addresses, you could specify which address you wanted to listen on. Or you could use it
243 | * to specify that the socket should only accept connections over ethernet, and not other interfaces such as wifi.
244 | * You may also use the special strings "localhost" or "loopback" to specify that
245 | * the socket only accept connections from the local machine.
246 | *
247 | * To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method.
248 | **/
249 | - (BOOL)acceptOnInterface:(NSString *)interface port:(UInt16)port error:(NSError **)errPtr;
250 |
251 | /**
252 | * Connects to the given host and port.
253 | * The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2")
254 | **/
255 | - (BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr;
256 |
257 | /**
258 | * This method is the same as connectToHost:onPort:error: with an additional timeout option.
259 | * To not time out use a negative time interval, or simply use the connectToHost:onPort:error: method.
260 | **/
261 | - (BOOL)connectToHost:(NSString *)hostname
262 | onPort:(UInt16)port
263 | withTimeout:(NSTimeInterval)timeout
264 | error:(NSError **)errPtr;
265 |
266 | /**
267 | * Connects to the given address, specified as a sockaddr structure wrapped in a NSData object.
268 | * For example, a NSData object returned from NSNetService's addresses method.
269 | *
270 | * If you have an existing struct sockaddr you can convert it to a NSData object like so:
271 | * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
272 | * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];
273 | **/
274 | - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr;
275 |
276 | /**
277 | * This method is the same as connectToAddress:error: with an additional timeout option.
278 | * To not time out use a negative time interval, or simply use the connectToAddress:error: method.
279 | **/
280 | - (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr;
281 |
282 | - (BOOL)connectToAddress:(NSData *)remoteAddr
283 | viaInterfaceAddress:(NSData *)interfaceAddr
284 | withTimeout:(NSTimeInterval)timeout
285 | error:(NSError **)errPtr;
286 |
287 | /**
288 | * Disconnects immediately. Any pending reads or writes are dropped.
289 | * If the socket is not already disconnected, the onSocketDidDisconnect delegate method
290 | * will be called immediately, before this method returns.
291 | *
292 | * Please note the recommended way of releasing an AsyncSocket instance (e.g. in a dealloc method)
293 | * [asyncSocket setDelegate:nil];
294 | * [asyncSocket disconnect];
295 | * [asyncSocket release];
296 | **/
297 | - (void)disconnect;
298 |
299 | /**
300 | * Disconnects after all pending reads have completed.
301 | * After calling this, the read and write methods will do nothing.
302 | * The socket will disconnect even if there are still pending writes.
303 | **/
304 | - (void)disconnectAfterReading;
305 |
306 | /**
307 | * Disconnects after all pending writes have completed.
308 | * After calling this, the read and write methods will do nothing.
309 | * The socket will disconnect even if there are still pending reads.
310 | **/
311 | - (void)disconnectAfterWriting;
312 |
313 | /**
314 | * Disconnects after all pending reads and writes have completed.
315 | * After calling this, the read and write methods will do nothing.
316 | **/
317 | - (void)disconnectAfterReadingAndWriting;
318 |
319 | /* Returns YES if the socket and streams are open, connected, and ready for reading and writing. */
320 | - (BOOL)isConnected;
321 |
322 | /**
323 | * Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected.
324 | * The host will be an IP address.
325 | **/
326 | - (NSString *)connectedHost;
327 | - (UInt16)connectedPort;
328 |
329 | - (NSString *)localHost;
330 | - (UInt16)localPort;
331 |
332 | /**
333 | * Returns the local or remote address to which this socket is connected,
334 | * specified as a sockaddr structure wrapped in a NSData object.
335 | *
336 | * See also the connectedHost, connectedPort, localHost and localPort methods.
337 | **/
338 | - (NSData *)connectedAddress;
339 | - (NSData *)localAddress;
340 |
341 | /**
342 | * Returns whether the socket is IPv4 or IPv6.
343 | * An accepting socket may be both.
344 | **/
345 | - (BOOL)isIPv4;
346 | - (BOOL)isIPv6;
347 |
348 | // The readData and writeData methods won't block (they are asynchronous).
349 | //
350 | // When a read is complete the onSocket:didReadData:withTag: delegate method is called.
351 | // When a write is complete the onSocket:didWriteDataWithTag: delegate method is called.
352 | //
353 | // You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.)
354 | // If a read/write opertion times out, the corresponding "onSocket:shouldTimeout..." delegate method
355 | // is called to optionally allow you to extend the timeout.
356 | // Upon a timeout, the "onSocket:willDisconnectWithError:" method is called, followed by "onSocketDidDisconnect".
357 | //
358 | // The tag is for your convenience.
359 | // You can use it as an array index, step number, state id, pointer, etc.
360 |
361 | /**
362 | * Reads the first available bytes that become available on the socket.
363 | *
364 | * If the timeout value is negative, the read operation will not use a timeout.
365 | **/
366 | - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag;
367 |
368 | /**
369 | * Reads the first available bytes that become available on the socket.
370 | * The bytes will be appended to the given byte buffer starting at the given offset.
371 | * The given buffer will automatically be increased in size if needed.
372 | *
373 | * If the timeout value is negative, the read operation will not use a timeout.
374 | * If the buffer if nil, the socket will create a buffer for you.
375 | *
376 | * If the bufferOffset is greater than the length of the given buffer,
377 | * the method will do nothing, and the delegate will not be called.
378 | *
379 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it.
380 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer.
381 | * That is, it will reference the bytes that were appended to the given buffer.
382 | **/
383 | - (void)readDataWithTimeout:(NSTimeInterval)timeout
384 | buffer:(NSMutableData *)buffer
385 | bufferOffset:(NSUInteger)offset
386 | tag:(long)tag;
387 |
388 | /**
389 | * Reads the first available bytes that become available on the socket.
390 | * The bytes will be appended to the given byte buffer starting at the given offset.
391 | * The given buffer will automatically be increased in size if needed.
392 | * A maximum of length bytes will be read.
393 | *
394 | * If the timeout value is negative, the read operation will not use a timeout.
395 | * If the buffer if nil, a buffer will automatically be created for you.
396 | * If maxLength is zero, no length restriction is enforced.
397 | *
398 | * If the bufferOffset is greater than the length of the given buffer,
399 | * the method will do nothing, and the delegate will not be called.
400 | *
401 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it.
402 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer.
403 | * That is, it will reference the bytes that were appended to the given buffer.
404 | **/
405 | - (void)readDataWithTimeout:(NSTimeInterval)timeout
406 | buffer:(NSMutableData *)buffer
407 | bufferOffset:(NSUInteger)offset
408 | maxLength:(NSUInteger)length
409 | tag:(long)tag;
410 |
411 | /**
412 | * Reads the given number of bytes.
413 | *
414 | * If the timeout value is negative, the read operation will not use a timeout.
415 | *
416 | * If the length is 0, this method does nothing and the delegate is not called.
417 | **/
418 | - (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
419 |
420 | /**
421 | * Reads the given number of bytes.
422 | * The bytes will be appended to the given byte buffer starting at the given offset.
423 | * The given buffer will automatically be increased in size if needed.
424 | *
425 | * If the timeout value is negative, the read operation will not use a timeout.
426 | * If the buffer if nil, a buffer will automatically be created for you.
427 | *
428 | * If the length is 0, this method does nothing and the delegate is not called.
429 | * If the bufferOffset is greater than the length of the given buffer,
430 | * the method will do nothing, and the delegate will not be called.
431 | *
432 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it.
433 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer.
434 | * That is, it will reference the bytes that were appended to the given buffer.
435 | **/
436 | - (void)readDataToLength:(NSUInteger)length
437 | withTimeout:(NSTimeInterval)timeout
438 | buffer:(NSMutableData *)buffer
439 | bufferOffset:(NSUInteger)offset
440 | tag:(long)tag;
441 |
442 | /**
443 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator.
444 | *
445 | * If the timeout value is negative, the read operation will not use a timeout.
446 | *
447 | * If you pass nil or zero-length data as the "data" parameter,
448 | * the method will do nothing, and the delegate will not be called.
449 | *
450 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter.
451 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for
452 | * a character, the read will prematurely end.
453 | **/
454 | - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
455 |
456 | /**
457 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator.
458 | * The bytes will be appended to the given byte buffer starting at the given offset.
459 | * The given buffer will automatically be increased in size if needed.
460 | *
461 | * If the timeout value is negative, the read operation will not use a timeout.
462 | * If the buffer if nil, a buffer will automatically be created for you.
463 | *
464 | * If the bufferOffset is greater than the length of the given buffer,
465 | * the method will do nothing, and the delegate will not be called.
466 | *
467 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it.
468 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer.
469 | * That is, it will reference the bytes that were appended to the given buffer.
470 | *
471 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter.
472 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for
473 | * a character, the read will prematurely end.
474 | **/
475 | - (void)readDataToData:(NSData *)data
476 | withTimeout:(NSTimeInterval)timeout
477 | buffer:(NSMutableData *)buffer
478 | bufferOffset:(NSUInteger)offset
479 | tag:(long)tag;
480 |
481 | /**
482 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator.
483 | *
484 | * If the timeout value is negative, the read operation will not use a timeout.
485 | *
486 | * If maxLength is zero, no length restriction is enforced.
487 | * Otherwise if maxLength bytes are read without completing the read,
488 | * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError.
489 | * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end.
490 | *
491 | * If you pass nil or zero-length data as the "data" parameter,
492 | * the method will do nothing, and the delegate will not be called.
493 | * If you pass a maxLength parameter that is less than the length of the data parameter,
494 | * the method will do nothing, and the delegate will not be called.
495 | *
496 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter.
497 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for
498 | * a character, the read will prematurely end.
499 | **/
500 | - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag;
501 |
502 | /**
503 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator.
504 | * The bytes will be appended to the given byte buffer starting at the given offset.
505 | * The given buffer will automatically be increased in size if needed.
506 | * A maximum of length bytes will be read.
507 | *
508 | * If the timeout value is negative, the read operation will not use a timeout.
509 | * If the buffer if nil, a buffer will automatically be created for you.
510 | *
511 | * If maxLength is zero, no length restriction is enforced.
512 | * Otherwise if maxLength bytes are read without completing the read,
513 | * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError.
514 | * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end.
515 | *
516 | * If you pass a maxLength parameter that is less than the length of the data parameter,
517 | * the method will do nothing, and the delegate will not be called.
518 | * If the bufferOffset is greater than the length of the given buffer,
519 | * the method will do nothing, and the delegate will not be called.
520 | *
521 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it.
522 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer.
523 | * That is, it will reference the bytes that were appended to the given buffer.
524 | *
525 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter.
526 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for
527 | * a character, the read will prematurely end.
528 | **/
529 | - (void)readDataToData:(NSData *)data
530 | withTimeout:(NSTimeInterval)timeout
531 | buffer:(NSMutableData *)buffer
532 | bufferOffset:(NSUInteger)offset
533 | maxLength:(NSUInteger)length
534 | tag:(long)tag;
535 |
536 | /**
537 | * Writes data to the socket, and calls the delegate when finished.
538 | *
539 | * If you pass in nil or zero-length data, this method does nothing and the delegate will not be called.
540 | * If the timeout value is negative, the write operation will not use a timeout.
541 | **/
542 | - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
543 |
544 | /**
545 | * Returns progress of current read or write, from 0.0 to 1.0, or NaN if no read/write (use isnan() to check).
546 | * "tag", "done" and "total" will be filled in if they aren't NULL.
547 | **/
548 | - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
549 | - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
550 |
551 | /**
552 | * Secures the connection using SSL/TLS.
553 | *
554 | * This method may be called at any time, and the TLS handshake will occur after all pending reads and writes
555 | * are finished. This allows one the option of sending a protocol dependent StartTLS message, and queuing
556 | * the upgrade to TLS at the same time, without having to wait for the write to finish.
557 | * Any reads or writes scheduled after this method is called will occur over the secured connection.
558 | *
559 | * The possible keys and values for the TLS settings are well documented.
560 | * Some possible keys are:
561 | * - kCFStreamSSLLevel
562 | * - kCFStreamSSLAllowsExpiredCertificates
563 | * - kCFStreamSSLAllowsExpiredRoots
564 | * - kCFStreamSSLAllowsAnyRoot
565 | * - kCFStreamSSLValidatesCertificateChain
566 | * - kCFStreamSSLPeerName
567 | * - kCFStreamSSLCertificates
568 | * - kCFStreamSSLIsServer
569 | *
570 | * Please refer to Apple's documentation for associated values, as well as other possible keys.
571 | *
572 | * If you pass in nil or an empty dictionary, the default settings will be used.
573 | *
574 | * The default settings will check to make sure the remote party's certificate is signed by a
575 | * trusted 3rd party certificate agency (e.g. verisign) and that the certificate is not expired.
576 | * However it will not verify the name on the certificate unless you
577 | * give it a name to verify against via the kCFStreamSSLPeerName key.
578 | * The security implications of this are important to understand.
579 | * Imagine you are attempting to create a secure connection to MySecureServer.com,
580 | * but your socket gets directed to MaliciousServer.com because of a hacked DNS server.
581 | * If you simply use the default settings, and MaliciousServer.com has a valid certificate,
582 | * the default settings will not detect any problems since the certificate is valid.
583 | * To properly secure your connection in this particular scenario you
584 | * should set the kCFStreamSSLPeerName property to "MySecureServer.com".
585 | * If you do not know the peer name of the remote host in advance (for example, you're not sure
586 | * if it will be "domain.com" or "www.domain.com"), then you can use the default settings to validate the
587 | * certificate, and then use the X509Certificate class to verify the issuer after the socket has been secured.
588 | * The X509Certificate class is part of the CocoaAsyncSocket open source project.
589 | **/
590 | - (void)startTLS:(NSDictionary *)tlsSettings;
591 |
592 | /**
593 | * For handling readDataToData requests, data is necessarily read from the socket in small increments.
594 | * The performance can be much improved by allowing AsyncSocket to read larger chunks at a time and
595 | * store any overflow in a small internal buffer.
596 | * This is termed pre-buffering, as some data may be read for you before you ask for it.
597 | * If you use readDataToData a lot, enabling pre-buffering will result in better performance, especially on the iPhone.
598 | *
599 | * The default pre-buffering state is controlled by the DEFAULT_PREBUFFERING definition.
600 | * It is highly recommended one leave this set to YES.
601 | *
602 | * This method exists in case pre-buffering needs to be disabled by default for some unforeseen reason.
603 | * In that case, this method exists to allow one to easily enable pre-buffering when ready.
604 | **/
605 | - (void)enablePreBuffering;
606 |
607 | /**
608 | * When you create an AsyncSocket, it is added to the runloop of the current thread.
609 | * So for manually created sockets, it is easiest to simply create the socket on the thread you intend to use it.
610 | *
611 | * If a new socket is accepted, the delegate method onSocket:wantsRunLoopForNewSocket: is called to
612 | * allow you to place the socket on a separate thread. This works best in conjunction with a thread pool design.
613 | *
614 | * If, however, you need to move the socket to a separate thread at a later time, this
615 | * method may be used to accomplish the task.
616 | *
617 | * This method must be called from the thread/runloop the socket is currently running on.
618 | *
619 | * Note: After calling this method, all further method calls to this object should be done from the given runloop.
620 | * Also, all delegate calls will be sent on the given runloop.
621 | **/
622 | - (BOOL)moveToRunLoop:(NSRunLoop *)runLoop;
623 |
624 | /**
625 | * Allows you to configure which run loop modes the socket uses.
626 | * The default set of run loop modes is NSDefaultRunLoopMode.
627 | *
628 | * If you'd like your socket to continue operation during other modes, you may want to add modes such as
629 | * NSModalPanelRunLoopMode or NSEventTrackingRunLoopMode. Or you may simply want to use NSRunLoopCommonModes.
630 | *
631 | * Accepted sockets will automatically inherit the same run loop modes as the listening socket.
632 | *
633 | * Note: NSRunLoopCommonModes is defined in 10.5. For previous versions one can use kCFRunLoopCommonModes.
634 | **/
635 | - (BOOL)setRunLoopModes:(NSArray *)runLoopModes;
636 | - (BOOL)addRunLoopMode:(NSString *)runLoopMode;
637 | - (BOOL)removeRunLoopMode:(NSString *)runLoopMode;
638 |
639 | /**
640 | * Returns the current run loop modes the AsyncSocket instance is operating in.
641 | * The default set of run loop modes is NSDefaultRunLoopMode.
642 | **/
643 | - (NSArray *)runLoopModes;
644 |
645 | /**
646 | * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read
647 | * any data that's left on the socket.
648 | **/
649 | - (NSData *)unreadData;
650 |
651 | /* A few common line separators, for use with the readDataToData:... methods. */
652 | + (NSData *)CRLFData; // 0x0D0A
653 | + (NSData *)CRData; // 0x0D
654 | + (NSData *)LFData; // 0x0A
655 | + (NSData *)ZeroData; // 0x00
656 |
657 | @end
658 |
--------------------------------------------------------------------------------