我尝试修改简单 CS193P iTunes U示例/家庭作业,只在UIScrollView 中显示 UIImage。我是Obj-C区块的新手。
一旦我尝试将下载Image的代码行包装在* dispatch_async * Block中,我就会打破缩放并获得
Uncaught exception: CALayer position contains NaN: [nan nan]
(显示图像和“滚动”工作)
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.activityIndicatorView startAnimating];
[self resetImage];
}
- (void)resetImage
{
if (self.detailItem && self.scrollView) {
//reset
self.scrollView.contentSize = CGSizeZero;
self.imageView.image = nil;
NSURL *imageURL = [FlickrFetcher urlForPhoto:self.detailItem format:FlickrPhotoFormatLarge];
__block NSData *imageData;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
imageData = [[NSData alloc] initWithContentsOfURL:imageURL];
dispatch_async(dispatch_get_main_queue(), ^{ //because of UI Stuff
UIImage *image = [[UIImage alloc] initWithData:imageData];
if (image) {
[self.activityIndicatorView stopAnimating];
[self.activityIndicatorView removeFromSuperview];
self.scrollView.zoomScale = 1.0;
self.scrollView.contentSize = image.size;
self.imageView.image = image;
CGRect frame = { CGPointZero , image.size };
self.imageView.frame = frame;
[self addToRecentPhotosList:self.detailItem];
NSLog(@"\n self.imageView.frame:%@ \n self.imageView.bounds: %@ \n self.scrollView.contentSize: %@ \n self.scrollView.frame: %@ \n self.scrollView.bounds: %@ ", NSStringFromCGRect(self.imageView.frame), NSStringFromCGRect(self.imageView.bounds), NSStringFromCGSize(self.scrollView.contentSize), NSStringFromCGRect(self.scrollView.frame), NSStringFromCGRect(self.scrollView.bounds));
}
});
});
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.scrollView addSubview:self.imageView];
[self.scrollView addSubview:self.activityIndicatorView];
self.scrollView.minimumZoomScale = 0.2;
self.scrollView.maximumZoomScale = 5.0;
self.scrollView.delegate = self;
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if (self.imageView.image) [self.scrollView zoomToRect:self.imageView.bounds animated:YES];
else self.activityIndicatorView.center = self.view.center;
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
记录的帧/边界:
without dispatch_async blocks:
self.imageView.frame: {{0, 0}, {1024, 768}}
self.imageView.bounds: {{0, 0}, {1024, 768}}
with dispatch_async blocks:
self.imageView.frame: {{-7.62939e-06, -1.52588e-05}, {1024, 768}}
self.imageView.bounds: {{0, 0}, {204.8, 153.6}}
self.scrollView.contentSize: {1024, 768}
self.scrollView.frame: {{0, 0}, {320, 367}}
self.scrollView.bounds: {{0, 0}, {320, 367}}
堆栈追踪:
0 CoreFoundation 0x01ca002e __exceptionPreprocess + 206
1 libobjc.A.dylib 0x010dde7e objc_exception_throw + 44
2 CoreFoundation 0x01c9fdeb +[NSException raise:format:] + 139
3 QuartzCore 0x02293e0b _ZN2CA5Layer12set_positionERKNS_4Vec2IdEEb + 151
4 QuartzCore 0x0229eba1 -[CALayer(CALayerPrivate) setDoublePosition:] + 81
5 UIKit 0x000874a2 -[UIScrollView setZoomScale:withAnchorPoint:validatingScrollOffset:allowRubberbanding:animated:duration:notifyDelegate:force:] + 1476
6 UIKit 0x00083004 -[UIScrollView _updatePinchGestureForState:] + 3499
7 UIKit 0x00083960 -[UIScrollView handlePinch:] + 59
8 UIKit 0x002ec85a _UIGestureRecognizerSendActions + 139
9 UIKit 0x002eb99b -[UIGestureRecognizer _updateGestureWithEvent:] + 333
10 UIKit 0x002ed0df -[UIGestureRecognizer _delayedUpdateGesture] + 46
11 UIKit 0x002efd2d ___UIGestureRecognizerUpdate_block_invoke_0543 + 57
12 UIKit 0x002efcac _UIGestureRecognizerRemoveObjectsFromArrayAndApplyBlocks + 331
13 UIKit 0x002e7a28 _UIGestureRecognizerUpdate + 1348
14 UIKit 0x00054972 -[UIWindow _sendGesturesForEvent:] + 1283
15 UIKit 0x00054e53 -[UIWindow sendEvent:] + 98
16 UIKit 0x00032d4a -[UIApplication sendEvent:] + 436
17 UIKit 0x00024698 _UIApplicationHandleEvent + 9874
18 GraphicsServices 0x01bfbdf9 _PurpleEventCallback + 339
19 GraphicsServices 0x01bfbad0 PurpleEventCallback + 46
20 CoreFoundation 0x01c15bf5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
21 CoreFoundation 0x01c15962 __CFRunLoopDoSource1 + 146
22 CoreFoundation 0x01c46bb6 __CFRunLoopRun + 2118
23 CoreFoundation 0x01c45f44 CFRunLoopRunSpecific + 276
24 CoreFoundation 0x01c45e1b CFRunLoopRunInMode + 123
25 GraphicsServices 0x01bfa7e3 GSEventRunModal + 88
26 GraphicsServices 0x01bfa668 GSEventRun + 104
27 UIKit 0x00021ffc UIApplicationMain + 1211
28 CS193P.4.SPoT 0x00002b84 main + 164
29 CS193P.4.SPoT 0x00002a95 start + 53
答案 0 :(得分:2)
imageData
并不是一个屡获殊荣的想法。
// ...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_t _semaphore = dispatch_semaphore_create(0);
imageData = [[NSData alloc] initWithContentsOfURL:imageURL];
dispatch_semaphore_signal(_semaphore);
dispatch_async(dispatch_get_main_queue(), ^{ //because of UI Stuff
dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
dispatch_release(_semaphore);
UIImage *image = [[UIImage alloc] initWithData:imageData];
// etc...
};
};
// ...
<强>更新强>
尝试此解决方案,它的工作方式与GCD
版本应该有效。
<强> SPoTDetailViewController.h 强>
@interface SPoTImageViewController : UIViewController <UISplitViewControllerDelegate, UIScrollViewDelegate> {
dispatch_semaphore_t _semaphore;
__block NSData *imageData;
}
// ...
@end
<强> SPoTDetailViewController.m 强>
- (void)resetImage
{
// Update the user interface for the detail item.
[self.activityIndicatorView startAnimating];
if (self.detailItem && self.scrollView) {
self.scrollView.contentSize = CGSizeZero;
self.imageView.image = nil;
[self performSelectorInBackground:@selector(downloadImageDataOnBackgroundThread) withObject:nil];
dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
// dispatch_release(_semaphore);
UIImage *image = [[UIImage alloc] initWithData:imageData];
if (image) {
[_activityIndicatorView stopAnimating];
_scrollView.zoomScale = 1.0;
_scrollView.contentSize = image.size;
_imageView.image = image;
CGRect frame = { CGPointZero , image.size };
NSLog(@"\n new CGRect frame:%@ \n ", NSStringFromCGRect(frame));
_imageView.frame = frame;
NSLog(@"\n self.imageView.frame:%@ \n self.imageView.bounds: %@", NSStringFromCGRect(self.imageView.frame), NSStringFromCGRect(self.imageView.bounds));
}
}
}
- (void)downloadImageDataOnBackgroundThread {
_semaphore = dispatch_semaphore_create(0);
NSURL *imageURL = [FlickrFetcher urlForPhoto:self.detailItem format:FlickrPhotoFormatLarge];
imageData = [[NSData alloc] initWithContentsOfURL:imageURL];
dispatch_semaphore_signal(_semaphore);
}