-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathErrata.txt
308 lines (252 loc) · 11.2 KB
/
Errata.txt
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
■IIページ
各レシピ内で紹介しているソースコード(すべてではありません)は、次のURLより取得できます。
http://github.com/ktakayama/iPhoneSDK-RecipeBook
ご使用にあたっては、上記から辿れるファイル「README.md」をご覧ください。
■39ページ
レシピ16「ユニークなファイル名を生成する」
一つ目のプログラム
○修正前
NSString *fileName = [NSString stringWithFormat:@"%@.%@",uuidStr,ext];
return fileName;
○修正後
NSString *fileName = [NSString stringWithFormat:@"%@.%@",uuidStr,ext];
CFRelease(uuidStr);
return fileName;
■53ページ
レシピ25「文字列からMD5を取得する」
一つ目のプログラム
○修正前
return [NSString stringWithCString:md5string length:CC_MD5_DIGEST_LENGTH*2];
○修正後
return [NSString stringWithCString:md5string encoding:NSASCIIStringEncoding];
■178ページ
レシピ74「カメラロールから読み込んだ写真の縦横位置を調べる」
一つ目のプログラム
○修正前
- (void) imagePickerController:(UIImagePickerController*)picker
didFinishPickingImage:(UIImage *)image
editingInfo:(NSDictionary*)editingInfo {
○修正後
- (void) imagePickerController
didFinishPickingMediaWithInfo:(NSDictionary*)info {
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
■103ページ〜109ページ
レシピ番号とレシピタイトルを除き
全体を差し替え
FirefoxなどのマウスジェスチャーのようにUIWebViewをフィンガージェスチャーで操作する方法です。UIWebViewではシングルタッチは画面スクロールや拡大などの役割があるため、マルチタッチの左右のスワイプでブラウザの「戻る」「進む」動作が出来るようにしてみました。マルチタッチはピンチ動作も含まれるのでその辺りの考慮も必要です。またマルチタッチ時のタッチの軌跡をマウスジェスチャーのように赤いラインで表示しました。以下の例は、View-based Applicationで新規プロジェクトを作成しています。
まず、赤いラインを描画するビューを作ります。CGPointをNSMutableArrayに入れてdrawGestureLine:を呼ぶと赤いラインを描画します。
▽ファイル
@interface GestureView : UIView {
NSMutableArray* touchPoints;
}
- (void) drawGestureLine:(NSMutableArray*)points;
@end
@implementation GestureView
- (void) drawGestureLine:(NSMutableArray*) points {
touchPoints = points;
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect {
// ジェスチャーの軌跡を描画する
if (touchPoints.count > 0 ) {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 5.0f);
CGContextSetRGBStrokeColor(context, 255, 0, 0, 50);
CGPoint points[touchPoints.count];
int i=0;
for (NSValue* value in touchPoints) {
points[i++] = [value CGPointValue];
}
CGContextAddLines(context, points, touchPoints.count);
CGContextStrokePath(context);
}
}
@end
△ファイル
次にフィンガージェスチャーを認識するためにタッチ動作をフックするUIWindowのサブクラスを作ります。UIWindowのsendEvent:ですべてのタッチ動作をフックしてUIWebViewへの2本指でのマルチタッチのときのみ、delegateを通じてタッチイベントを通知します。また、フックしたタッチイベントは全てスーパークラスへそのまま渡すことにより、通常のタッチイベントを邪魔しないようにします。
▽ファイル
@protocol GestureWindowDelegate
- (void) touchesBeganWeb:(NSSet *)touches withEvent:(UIEvent *)event;
- (void) touchesMovedWeb:(NSSet *)touches withEvent:(UIEvent *)event;
- (void) touchesEndedWeb:(NSSet *)touches withEvent:(UIEvent *)event;
@end
@interface GestureWindow : UIWindow {
UIWebView* wView;
id delegate;
}
@property (nonatomic, retain) UIWebView* wView;
@property (nonatomic, assign) id delegate;
@end
@implementation GestureWindow
@synthesize wView, delegate;
-(void) dealloc {
[wView release];
[super dealloc];
}
- (void)sendEvent:(UIEvent *)event {
[super sendEvent:event];
if (wView == nil || delegate == nil) {
return;
}
// 2本指でのマルチタッチか
NSSet *touches = [event allTouches];
if (touches.count != 2) {
return;
}
UITouch *touch = touches.anyObject;
// 指定のUIWebViewへのタッチか
if ([touch.view isDescendantOfView:wView] == NO) {
return;
}
switch (touch.phase) {
case UITouchPhaseBegan:
if ([self.delegate
respondsToSelector:@selector(touchesBeganWeb:withEvent:)]) {
[self.delegate
performSelector:@selector(touchesBeganWeb:withEvent:)
withObject:touches withObject:event];
}
break;
case UITouchPhaseMoved:
if ([self.delegate
respondsToSelector:@selector(touchesMovedWeb:withEvent:)]) {
[self.delegate
performSelector:@selector(touchesMovedWeb:withEvent:)
withObject:touches withObject:event];
}
break;
case UITouchPhaseEnded:
if ([self.delegate
respondsToSelector:@selector(touchesEndedWeb:withEvent:)]) {
[self.delegate
performSelector:@selector(touchesEndedWeb:withEvent:)
withObject:touches withObject:event];
}
default:
return;
break;
}
}
@end
△ファイル
このGestureWindowクラスをアプリケーションのUIWindowとして使います。AppDelegateクラスのUIWindowを次のようにGesutreWindowsに変更します。またMainWindow.xibをInterfaceBuilderで開き、UIWindowを選択肢、InspectorでClass IdentityをGestureWindowに変更します。
▽ファイル
@interface WebAppDelegate : NSObject <UIApplicationDelegate> {
GestureWindow *window;
WebViewController *viewController;
}
@property (nonatomic, retain) IBOutlet GestureWindow *window;
@property (nonatomic, retain) IBOutlet WebViewController *viewController;
@end
△ファイル
最後にGestureView、UIWebViewを持ち、ジェスチャーを解析するUIViewControllerを作ります。タッチイベントがあると、マルチタッチでかつ、ピンチ動作ではなく、水平方向にGESTURE_LENGTH以上スワイプされれば、ジェスチャーとして認識して左右方向により「戻る」「進む」の動作をUIWebViewに対して行います。
▽ファイル
#define GESTURE_LENGTH 50
#define BLUR_LENGTH 50
#define PINCH_DELTA 100
#import "GestureWindow.h"
#import "GestureView.h"
@interface WebViewController : UIViewController <GestureWindowDelegate> {
UIWebView* webView;
GestureView* gestureView;
NSMutableArray* touchPoints;
CGFloat initDistance;
}
@end
@implementation WebViewController
// 2点間の距離を計算
CGFloat distanceBetweenPoints (CGPoint first, CGPoint second) {
CGFloat deltaX = second.x - first.x;
CGFloat deltaY = second.y - first.y;
return sqrt(deltaX*deltaX + deltaY*deltaY );
};
- (void) touchesBeganWeb:(NSSet *)touches withEvent:(UIEvent *)event {
initDistance = 0;
NSArray *twoTouches = [touches allObjects];
UITouch *first = [twoTouches objectAtIndex:0];
UITouch *second = [twoTouches objectAtIndex:1];
initDistance = distanceBetweenPoints([first locationInView:self.view],
[second locationInView:self.view]);
}
- (void) touchesMovedWeb:(NSSet *)touches withEvent:(UIEvent *)event {
NSArray *twoTouches = [touches allObjects];
UITouch *first = [twoTouches objectAtIndex:0];
UITouch *second = [twoTouches objectAtIndex:1];
CGFloat currentDistance =
distanceBetweenPoints([first locationInView:self.view],
[second locationInView:self.view]);
if (initDistance == 0) {
initDistance = currentDistance;
}
// ピンチ動作かチェック
if (fabs(currentDistance - initDistance) > PINCH_DELTA) {
[touchPoints removeAllObjects];
[gestureView drawGestureLine:touchPoints];
return;
}
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
[touchPoints addObject:[NSValue valueWithCGPoint:point]];
[gestureView drawGestureLine:touchPoints];
}
- (void) touchesEndedWeb:(NSSet *)touches withEvent:(UIEvent *)event {
if (touchPoints.count<=0) {
return;
}
CGPoint point1 = [[touchPoints objectAtIndex:0] CGPointValue];
CGPoint point2 =
[[touchPoints objectAtIndex:[touchPoints count]-1] CGPointValue];
CGFloat deltaX = point2.x - point1.x;
CGFloat deltaY = point2.y - point1.y;
if (fabsf(deltaX) >= GESTURE_LENGTH && fabsf(deltaY) <= BLUR_LENGTH) {
if (deltaX < 0) {
// 戻る
[webView goBack];
} else {
// 進む
[webView goForward];
}
} else if (fabsf(deltaY) >= GESTURE_LENGTH &&
fabsf(deltaX) <= BLUR_LENGTH) {
// 上下方向にマルチタッチスワイプ
}
[touchPoints removeAllObjects];
[gestureView setNeedsDisplay];
}
- (void)viewDidLoad {
[super viewDidLoad];
initDistance = 0;
touchPoints = [[NSMutableArray alloc] init];
// UIWebView
webView = [[UIWebView alloc] initWithFrame:CGRectMake(0 ,0 , 320, 450)];
webView.userInteractionEnabled = YES;
webView.scalesPageToFit = YES;
[self.view addSubview:webView];
[webView release];
// ジェスチャーの軌跡を描画するビュー
gestureView =
[[GestureView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
gestureView.userInteractionEnabled = NO;
gestureView.opaque = NO;
[self.view addSubview:gestureView];
[gestureView release];
// タッチイベントをフックするUIWindow
GestureWindow* tapWindow;
tapWindow = (GestureWindow*)[[UIApplication sharedApplication].windows
objectAtIndex:0];
tapWindow.wView = webView;
tapWindow.delegate = self;
// URL をロードする
[webView loadRequest:[NSURLRequest
requestWithURL:[NSURL URLWithString:@"http://example.com/"]]];
}
- (void)dealloc {
[touchPoints release];
[super dealloc];
}
@end
△ファイル
シミュレータでの動作チェックには、110ページのコラム「iPhoneシミュレータでマルチタッチを平行に動かす方法」で書かれた方法がマルチタッチを平行に動かせて便利です。
■320ページ
「発行日」の次の行に以下を追加
2010年7月10日 第1版第2刷