1

Я попытался изменить простой CS193P iTunes U пример/домашнее задание, которое отображает только UIImage UIScrollView. Я новичок в блоках Obj-C.Блоки/dispatch_async: что не так с моим простым кодом?

Как только я пытаюсь обернуть строку кода, который загружает изображение внутри * dispatch_async * Block I прорвать масштабированием и получить

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 

ответ

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... 

    }; 
}; 

// ... 

UPDATE

попробовать это решение, а также, он работает так же, как версия 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); 
} 
+0

спасибо за вашу помощь! все еще сбой с тем же исключением, хотя .. – blub

+0

какая линия бросает вам исключение? – holex

+0

Я действительно не знаю, я думал, что это не одна из моих кодовых строк, но [CALayer (CALayerPrivate) setDoublePosition:] запускается scrollView, распознающим pinchGesture? XCode просто возвращается к основному. – blub

Смежные вопросы