Categories
Recent Posts

Posts Tagged ‘Objective-C’

iPhone开发中的问题整理(一)

看到很刚开始开发iPhone软件的朋友问很多问题,其实同样的问题我也碰到过, 所以抽时间把能想到的或者碰到的问题汇总一下, 一来可以给自己做个备忘也可以和朋友们分享探讨。

1. iPhone SDK 开发能不能使用C / C++ 语言?

Answer: iPhone SDK的开发的基础框架是基于cocoa库的, Objective-C 是cocoa的开发语言, 但基于Objective-C的特性,在iPhone程序中可以使用C/C++进行功能开发以及使用第三方C/C++库。 Read the rest of this entry »

ZipArchive has been updated to version 1.1 (更新至1.1版)

ZipArchive is a wrapper class to compress and uncompress zip files for Objective-C and cocoa use. It’s developed based on minizip and zlib.  The latest version is 1.1, new feature includes :

✩ create password protected zip files

✩ unzip password protected zip files

To obtain the new version up to date, please visit the project website http://code.google.com/p/ziparchive/

ZipArchive 是基于minizip和zlib的Objective-C 类, 用于创建和解压zip格式的压缩文件, 最新版本为1.1, 新增功能如下:

✩ 创建有密码保护的zip文件

✩ 解压有密码保护的zip文件

为了保证获取最新的版本, 请访问该项目网页 http://code.google.com/p/ziparchive/

Create custom checkbox style button for iPhone

Recently, I got a task to develop an application for iPhone. In the application,  there are some optional choices for user to decide further processes. The first idea jumps out from my head is something like button with a checkbox just the same as other desktop platforms, but unfortunately, iPhone SDK doesn’t provide such view. The only official choice is the ON|OFF switch view,  but it really can’t represent the actually meaning of the options. So comes out the idea of writing  custom checkbox style button.

It’s really easy to implement. What we need is two images which are statuses for check and uncheck.  Here are the runtime screenshots:

checkbutton uncheckbutton

The class  for Checkbox button  is CheckButton,  it’s inherited from UIButton,  look at the declaration:

1
2
3
4
5
6
7
8
9
10
#import 
 
@interface CheckButton : UIButton {
	BOOL		_checked;
}
 
@property (nonatomic, setter=setChecked) BOOL checked;
 
-(void) setChecked:(BOOL) check;
@end

Implementation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#import "CheckButton.h"
 
@implementation CheckButton
@synthesize checked = _checked;
 
-(id) init
{
	if( self=[super init] )
	{
		self.checked = NO;
		[self addTarget:self action:@selector(OnCheck:) forControlEvents:UIControlEventTouchUpInside];
	}
	return self;
}
 
-(void) awakeFromNib
{
	self.checked = NO;
	[self addTarget:self action:@selector(OnCheck:) forControlEvents:UIControlEventTouchUpInside];
}
 
-(void) dealloc
{
	[super dealloc];
}
 
-(void) setChecked:(BOOL) check
{
	_checked = check;
	if( _checked )
	{
		UIImage* img = [UIImage imageNamed:@"check.png"];
		[self setImage:img forState:UIControlStateNormal];
	}
	else
	{
		UIImage* img = [UIImage imageNamed:@"uncheck.png"];
		[self setImage:img forState:UIControlStateNormal];
	}
}
 
-(void) OnCheck:(id) sender
{
	self.checked = !_checked;
}
 
@end

To use the class, import the header where contains the button, and declare a IBOutlet with type of “CheckButton”, and connect the IBOutlet in InterfaceBuilder to the member as shown below:
import

This is simple but exactly meet my requirement. Of course, someone wants to include title text of the button within the button class,  it’s sure to be easy to do :)

Here is the sample project zip file.

base64 encoder/decoder for objective-c 编码及解码

base64是广为使用的一种编码及解码方式, 通常用于网络传输和邮件传输中,使用base64可以将标点符号以及多字节文字等特殊字符编码以便传输,以下是base64 编码解码的objective-c代码, 可以用于desktop和iphone程序当中

头文件

?Download base64.h
1
2
3
4
5
6
7
#include <UIKit/UIKit.h>
 
extern size_t EstimateBas64EncodedDataSize(size_t inDataSize);
extern size_t EstimateBas64DecodedDataSize(size_t inDataSize);
 
extern bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize, BOOL wrapped);
extern bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize);

实现文件

?Download base64.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include "Base64Transcoder.h"
 
#include <math.h>
 
const UInt8 kBase64EncodeTable[64] = {
	/*  0 */ 'A',	/*  1 */ 'B',	/*  2 */ 'C',	/*  3 */ 'D', 
	/*  4 */ 'E',	/*  5 */ 'F',	/*  6 */ 'G',	/*  7 */ 'H', 
	/*  8 */ 'I',	/*  9 */ 'J',	/* 10 */ 'K',	/* 11 */ 'L', 
	/* 12 */ 'M',	/* 13 */ 'N',	/* 14 */ 'O',	/* 15 */ 'P', 
	/* 16 */ 'Q',	/* 17 */ 'R',	/* 18 */ 'S',	/* 19 */ 'T', 
	/* 20 */ 'U',	/* 21 */ 'V',	/* 22 */ 'W',	/* 23 */ 'X', 
	/* 24 */ 'Y',	/* 25 */ 'Z',	/* 26 */ 'a',	/* 27 */ 'b', 
	/* 28 */ 'c',	/* 29 */ 'd',	/* 30 */ 'e',	/* 31 */ 'f', 
	/* 32 */ 'g',	/* 33 */ 'h',	/* 34 */ 'i',	/* 35 */ 'j', 
	/* 36 */ 'k',	/* 37 */ 'l',	/* 38 */ 'm',	/* 39 */ 'n', 
	/* 40 */ 'o',	/* 41 */ 'p',	/* 42 */ 'q',	/* 43 */ 'r', 
	/* 44 */ 's',	/* 45 */ 't',	/* 46 */ 'u',	/* 47 */ 'v', 
	/* 48 */ 'w',	/* 49 */ 'x',	/* 50 */ 'y',	/* 51 */ 'z', 
	/* 52 */ '0',	/* 53 */ '1',	/* 54 */ '2',	/* 55 */ '3', 
	/* 56 */ '4',	/* 57 */ '5',	/* 58 */ '6',	/* 59 */ '7', 
	/* 60 */ '8',	/* 61 */ '9',	/* 62 */ '+',	/* 63 */ '/'
};
 
/*
-1 = Base64 end of data marker.
-2 = White space (tabs, cr, lf, space)
-3 = Noise (all non whitespace, non-base64 characters) 
-4 = Dangerous noise
-5 = Illegal noise (null byte)
*/
 
const SInt8 kBase64DecodeTable[128] = {
	/* 0x00 */ -5, 	/* 0x01 */ -3, 	/* 0x02 */ -3, 	/* 0x03 */ -3,
	/* 0x04 */ -3, 	/* 0x05 */ -3, 	/* 0x06 */ -3, 	/* 0x07 */ -3,
	/* 0x08 */ -3, 	/* 0x09 */ -2, 	/* 0x0a */ -2, 	/* 0x0b */ -2,
	/* 0x0c */ -2, 	/* 0x0d */ -2, 	/* 0x0e */ -3, 	/* 0x0f */ -3,
	/* 0x10 */ -3, 	/* 0x11 */ -3, 	/* 0x12 */ -3, 	/* 0x13 */ -3,
	/* 0x14 */ -3, 	/* 0x15 */ -3, 	/* 0x16 */ -3, 	/* 0x17 */ -3,
	/* 0x18 */ -3, 	/* 0x19 */ -3, 	/* 0x1a */ -3, 	/* 0x1b */ -3,
	/* 0x1c */ -3, 	/* 0x1d */ -3, 	/* 0x1e */ -3, 	/* 0x1f */ -3,
	/* ' ' */ -2,	/* '!' */ -3,	/* '"' */ -3,	/* '#' */ -3,
	/* '$' */ -3,	/* '%' */ -3,	/* '&' */ -3,	/* ''' */ -3,
	/* '(' */ -3,	/* ')' */ -3,	/* '*' */ -3,	/* '+' */ 62,
	/* ',' */ -3,	/* '-' */ -3,	/* '.' */ -3,	/* '/' */ 63,
	/* '0' */ 52,	/* '1' */ 53,	/* '2' */ 54,	/* '3' */ 55,
	/* '4' */ 56,	/* '5' */ 57,	/* '6' */ 58,	/* '7' */ 59,
	/* '8' */ 60,	/* '9' */ 61,	/* ':' */ -3,	/* ';' */ -3,
	/* '<' */ -3,	/* '=' */ -1,	/* '>' */ -3,	/* '?' */ -3,
	/* '@' */ -3,	/* 'A' */ 0,	/* 'B' */  1,	/* 'C' */  2,
	/* 'D' */  3,	/* 'E' */  4,	/* 'F' */  5,	/* 'G' */  6,
	/* 'H' */  7,	/* 'I' */  8,	/* 'J' */  9,	/* 'K' */ 10,
	/* 'L' */ 11,	/* 'M' */ 12,	/* 'N' */ 13,	/* 'O' */ 14,
	/* 'P' */ 15,	/* 'Q' */ 16,	/* 'R' */ 17,	/* 'S' */ 18,
	/* 'T' */ 19,	/* 'U' */ 20,	/* 'V' */ 21,	/* 'W' */ 22,
	/* 'X' */ 23,	/* 'Y' */ 24,	/* 'Z' */ 25,	/* '[' */ -3,
	/* '\' */ -3,	/* ']' */ -3,	/* '^' */ -3,	/* '_' */ -3,
	/* '`' */ -3,	/* 'a' */ 26,	/* 'b' */ 27,	/* 'c' */ 28,
	/* 'd' */ 29,	/* 'e' */ 30,	/* 'f' */ 31,	/* 'g' */ 32,
	/* 'h' */ 33,	/* 'i' */ 34,	/* 'j' */ 35,	/* 'k' */ 36,
	/* 'l' */ 37,	/* 'm' */ 38,	/* 'n' */ 39,	/* 'o' */ 40,
	/* 'p' */ 41,	/* 'q' */ 42,	/* 'r' */ 43,	/* 's' */ 44,
	/* 't' */ 45,	/* 'u' */ 46,	/* 'v' */ 47,	/* 'w' */ 48,
	/* 'x' */ 49,	/* 'y' */ 50,	/* 'z' */ 51,	/* '{' */ -3,
	/* '|' */ -3,	/* '}' */ -3,	/* '~' */ -3,	/* 0x7f */ -3
};
 
const UInt8 kBits_00000011 = 0x03;
const UInt8 kBits_00001111 = 0x0F;
const UInt8 kBits_00110000 = 0x30;
const UInt8 kBits_00111100 = 0x3C;
const UInt8 kBits_00111111 = 0x3F;
const UInt8 kBits_11000000 = 0xC0;
const UInt8 kBits_11110000 = 0xF0;
const UInt8 kBits_11111100 = 0xFC;
 
size_t EstimateBas64EncodedDataSize(size_t inDataSize)
{
size_t theEncodedDataSize = (int)ceil(inDataSize / 3.0) * 4;
theEncodedDataSize = theEncodedDataSize / 72 * 74 + theEncodedDataSize % 72;
return(theEncodedDataSize);
}
 
size_t EstimateBas64DecodedDataSize(size_t inDataSize)
{
size_t theDecodedDataSize = (int)ceil(inDataSize / 4.0) * 3;
//theDecodedDataSize = theDecodedDataSize / 72 * 74 + theDecodedDataSize % 72;
return(theDecodedDataSize);
}
 
bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize, BOOL wrapped)
{
size_t theEncodedDataSize = EstimateBas64EncodedDataSize(inInputDataSize);
if (*ioOutputDataSize < theEncodedDataSize)
	return(false);
*ioOutputDataSize = theEncodedDataSize;
const UInt8 *theInPtr = (const UInt8 *)inInputData;
UInt32 theInIndex = 0, theOutIndex = 0;
for (; theInIndex < (inInputDataSize / 3) * 3; theInIndex += 3)
	{
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (theInPtr[theInIndex + 2] & kBits_11000000) >> 6];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 2] & kBits_00111111) >> 0];
	if (wrapped && (theOutIndex % 74 == 72))
		{
		outOutputData[theOutIndex++] = '\r';
		outOutputData[theOutIndex++] = '\n';
		}
	}
const size_t theRemainingBytes = inInputDataSize - theInIndex;
if (theRemainingBytes == 1)
	{
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (0 & kBits_11110000) >> 4];
	outOutputData[theOutIndex++] = '=';
	outOutputData[theOutIndex++] = '=';
	if (wrapped && (theOutIndex % 74 == 72))
		{
		outOutputData[theOutIndex++] = '\r';
		outOutputData[theOutIndex++] = '\n';
		}
	}
else if (theRemainingBytes == 2)
	{
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (0 & kBits_11000000) >> 6];
	outOutputData[theOutIndex++] = '=';
	if (wrapped && (theOutIndex % 74 == 72))
		{
		outOutputData[theOutIndex++] = '\r';
		outOutputData[theOutIndex++] = '\n';
		}
	}
return(true);
}
 
bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize)
{
memset(ioOutputData, '.', *ioOutputDataSize);
 
size_t theDecodedDataSize = EstimateBas64DecodedDataSize(inInputDataSize);
if (*ioOutputDataSize < theDecodedDataSize)
	return(false);
*ioOutputDataSize = 0;
const UInt8 *theInPtr = (const UInt8 *)inInputData;
UInt8 *theOutPtr = (UInt8 *)ioOutputData;
size_t theInIndex = 0, theOutIndex = 0;
UInt8 theOutputOctet;
size_t theSequence = 0;
for (; theInIndex < inInputDataSize; )
	{
	SInt8 theSextet = 0;
 
	SInt8 theCurrentInputOctet = theInPtr[theInIndex];
	theSextet = kBase64DecodeTable[theCurrentInputOctet];
	if (theSextet == -1)
		break;
	while (theSextet == -2)
		{
		theCurrentInputOctet = theInPtr[++theInIndex];
		theSextet = kBase64DecodeTable[theCurrentInputOctet];
		}
	while (theSextet == -3)
		{
		theCurrentInputOctet = theInPtr[++theInIndex];
		theSextet = kBase64DecodeTable[theCurrentInputOctet];
		}
	if (theSequence == 0)
		{
		theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 2 & kBits_11111100;
		}
	else if (theSequence == 1)
		{
		theOutputOctet |= (theSextet >- 0 ? theSextet : 0) >> 4 & kBits_00000011;
		theOutPtr[theOutIndex++] = theOutputOctet;
		}
	else if (theSequence == 2)
		{
		theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 4 & kBits_11110000;
		}
	else if (theSequence == 3)
		{
		theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 2 & kBits_00001111;
		theOutPtr[theOutIndex++] = theOutputOctet;
		}
	else if (theSequence == 4)
		{
		theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 6 & kBits_11000000;
		}
	else if (theSequence == 5)
		{
		theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 0 & kBits_00111111;
		theOutPtr[theOutIndex++] = theOutputOctet;
		}
	theSequence = (theSequence + 1) % 6;
	if (theSequence != 2 && theSequence != 4)
		theInIndex++;
	}
*ioOutputDataSize = theOutIndex;
return(true);
}

在自己的程序中实现Email功能

在iPhone上如果想在应用程序里发送邮件只能通过调用系统默认email客户端程序,使用mailto协议,具体方法为

1
[[UIApplication sharedApplication] OpenURL:@&quot;mailto:someone@web.com?subject=test email...&quot;&gt;mailto:someone@web.com?subject=test email...&quot;];

这种方式建档方便, 如果只是简单的发送文本完全可以胜任, 不过如果需要发送附件或者html格式化的信件,这种方法将无法实现,此时需要在自己的程序中实现email发送代码。 如果你不想自己去实现发送的代码,请看SKPSMTPMessage , 该项目是google上的开源项目,实现了iPhone平台通过SMTP发送email的功能, 你可以通过http://code.google.com/p/skpsmtpmessage 获得代码,加入自己的项目即可。

SKPSMTPMessage 的使用方法也很简单,只需要分配一个新的SKPSMTPMessage 对象,设置相应的字段即可,比如

1
2
3
4
5
6
7
8
9
10
SKPSMTPMessage	mailMsg = [[SKPSMTPMessage  alloc] init];
mailMsg.fromEmail = @&quot;mylogin@gmail.com&quot;; 
mailMsg.toEmail = @&quot;mylogin@gmail.com&quot;; 
mailMsg.relayHost = @&quot;smtp.gmail.com&quot;; 
mailMsg.requiresAuth = YES; 
mailMsg.login = @&quot;mylogin&quot;; 
mailMsg.pass = @&quot;mypassword&quot;; 
mailMsg.subject = @&quot;test message&quot;;  
mailMsg.validateSSLChain = NO; // 只用于自验证
mailMsg.delegate = self;

 

详细文档请访问http://code.google.com/p/skpsmtpmessage

iPhone开发之打包zip文件

程序需要往服务器上上传文件, 因为iPhone用户往往是用gprs或者edge网络,为了节约流量以及加快上传速度,所以只好将要上传的文件打包成zip文件,这样体积小了, 也为用户节约了时间和金钱。 开始的时候抱有意思希望去挖掘SDK文档, 未果, sdk不提供zip相关接口,在apple论坛打听了一下,很多dx给的建议是用apple script在后台打包, 对此领域不熟悉,放弃。 好在iPhone的官方SDK支持zLib库,这就好了, 找来minizip,一个封装的挺好的C/C++ zip库, 动手创建Objective-C对象封装之, 只需要几行代码即可完成, 简单实用。

使用方法如下

1
2
3
4
5
6
7
		BOOL ret = [zip CreateZipFile2:l_zipfile];
		ret = [zip addFileToZip:l_photo newname:@"photo.jpg"];
		if( ![zip CloseZipFile2] )
		{
			l_zipfile = @"";
		}
		[zip release];

其中 l_photo是之源文件路径,  @”photo.jpg” 是在新的文件名(不带路径)

之前没有实现 解压缩的代码, 今天补上了, 使用起来也和压缩差不多,下面时用法演示

1
2
3
4
5
6
7
8
9
10
11
	ZipArchive* za = [[ZipArchive alloc] init];
	if( [za UnzipOpenFile:@"/Volumes/data/testfolder/Archive.zip"] )
	{
		BOOL ret = [za UnzipFileTo:@"/Volumes/data/testfolder/extract" overWrite:YES];
		if( NO==ret )
		{
		}
		[za UnzipCloseFile];
	}
 
	[za release];

代码在附件中

Zip格式解压缩Objective C封装类