2012-02-19 8 views
0

写真を選択した後に写真ライブラリにアクセスするとクラッシュするという問題があります。iOS4のiPadのUIImagePickerControllerDelegateがクラッシュする(iOS5で正常に動作する)

ログ出力は次のようになります。

[GEPhotoControllerPopOver respondsToSelector:]: message sent to deallocated instance 0x239fbf40 

クラッシュが無いコールスタックをメインに発生します。 GuardMallocを実行すると、上記のエラーがログに記録されます。

GEPhotoControllerPopOverはフォトライブラリのポップオーバーです。割り当て解除された後に何かがアクセスしようとしているようですが、私の人生にとって何が分かりませんか? GEPhotoControllerPopoverを呼び出すすべてのコードでブレークポイントを設定し、GEPhotoControllerPopoverが解放された後に呼び出されるコードはありません。

そうのように宣言されています

@interface GEPhotoControllerPopOver : UIViewController < UINavigationControllerDelegate, 
                 UIImagePickerControllerDelegate, 
                 UIPopoverControllerDelegate 
                > 
{ 
    char* m_pPixelData; 
    int m_photoWidth; 
    int m_photoHeight; 
    int m_bytesPerPixel; 

    GEClient *m_pClient;  
    int m_longEdge; 

    UIImage* m_pLevelFrame; 
    UIImageView* m_pLevelFrameView; 

    UIPopoverController *m_pPopoverController; 
} 

- (void)UseImage:(UIImage*)theImage:(UIImagePickerController *)picker; 
@end 

フォトライブラリから画像を取得するためのコードは次のとおりです。

extern UIView *g_glView; 

@implementation GEPhotoControllerPopOver 


- (id)init 
{ 
    return [super init]; 
} 

- (void)loadView 
{ 
    [super loadView]; 
} 

- (void)dealloc 
{ 
    [super dealloc]; 
} 

- (void)SelectPhoto 
{ 
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary ]) 
    { 
     self.view = g_glView; 

     UIImagePickerController *pImagePicker; 

     pImagePicker = [[UIImagePickerController alloc] init]; 

     pImagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 

     pImagePicker.delegate = self; 

     pImagePicker.mediaTypes = [NSArray arrayWithObjects:(NSString *) kUTTypeImage, nil]; 

     pImagePicker.allowsEditing = NO; 

     m_pPopoverController = [[UIPopoverController alloc] initWithContentViewController:pImagePicker]; 
     m_pPopoverController.delegate = self; 

     [m_pPopoverController setPopoverContentSize:CGSizeMake(160,160) animated:YES]; 
     CGRect selectedRect = CGRectMake(0,0,1,1); 
     [m_pPopoverController presentPopoverFromRect:selectedRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 

     [pImagePicker release]; 
    } 
} 

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 
    [m_pPopoverController dismissPopoverAnimated:true]; 

    [m_pPopoverController release]; 
    m_pPopoverController = nil; 

    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; 

    [self dismissModalViewControllerAnimated:YES]; 

    if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) { 
     UIImage *picture = [info objectForKey:UIImagePickerControllerOriginalImage]; 

     [self UseImage:picture:picker];  
    } 
} 

私はあまりにもクレイジー何かをやっているとは思いません。 UseImageのコードの残りの部分に画像データを渡しています.Imageのコピーを作成して、同じメモリを指していないようにします。

次に、GEPhotoControllerPopOverの割り当てを解除し、再度呼び出すことはありません。残念ながら、数フレーム後に上記のエラーが発生します。 iOS4.3のiPadのみ。それはiOS3.xとiOS5.xのiPhone(異なるインターフェースオブジェクト)とiPadでうまく動作します

誰でもアイデアはありますか?

ありがとうございます!

EDIT - [super dealloc]の呼び出しを削除すると、問題が消えてしまうようです。明らかに最善の解決策ではありませんが、おそらく何が起きているのか把握するのに役立ちますか? 私はすべてのコードを踏んで、無駄なクラッシュを見つけようとしました。ポップオーバーを解除し、完全なレンダリングサイクルを経て、描画サイクルを終了し、次にアセンブリが深くクラッシュします。

EDIT 2 - 次のコードはiOS4ではクラッシュせず、32kと128kの両方のメモリがリークします。

32Kリーク:

0 libsystem_c.dylib calloc 
1 MusicLibrary MemNewPtrClear 
2 MusicLibrary ReadITImageDB 
3 MusicLibrary -[MLPhotoLibrary _loadImageLibrary] 
4 MusicLibrary -[MLPhotoLibrary albums] 
5 PhotoLibrary -[PLPhotoLibrary albums] 
6 PhotoLibrary -[PLPhotoLibrary imagePickerAlbums] 
7 PhotoLibrary -[PLPhotoLibrary(Utilities) albumsForContentMode:] 
8 PhotoLibrary -[PLLibraryViewController _updateAlbumsIfNecessary] 
9 PhotoLibrary -[PLLibraryViewController viewWillAppear:] 
10 PhotoLibrary -[PLUILibraryViewController viewWillAppear:] 
11 UIKit -[UINavigationController _startTransition:fromViewController:toViewController:] 
12 UIKit -[UINavigationController _startDeferredTransitionIfNeeded] 
13 UIKit -[UILayoutContainerView layoutSubviews] 
14 QuartzCore -[CALayer layoutSublayers] 
15 QuartzCore CALayerLayoutIfNeeded 
16 QuartzCore CA::Context::commit_transaction(CA::Transaction*) 
17 QuartzCore CA::Transaction::commit() 
18 QuartzCore CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) 
19 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ 
20 CoreFoundation __CFRunLoopDoObservers 
21 CoreFoundation __CFRunLoopRun 
22 CoreFoundation CFRunLoopRunSpecific 
23 CoreFoundation CFRunLoopRunInMode 
24 GraphicsServices GSEventRunModal 
25 GraphicsServices GSEventRun 
26 UIKit UIApplicationMain 

128Kリーク:

0 libsystem_c.dylib malloc 
1 MusicLibrary ReadITImageDB 
2 MusicLibrary -[MLPhotoLibrary _loadImageLibrary] 
3 MusicLibrary -[MLPhotoLibrary albums] 
4 PhotoLibrary -[PLPhotoLibrary albums] 
5 PhotoLibrary -[PLPhotoLibrary imagePickerAlbums] 
6 PhotoLibrary -[PLPhotoLibrary(Utilities) albumsForContentMode:] 
7 PhotoLibrary -[PLLibraryViewController _updateAlbumsIfNecessary] 
8 PhotoLibrary -[PLLibraryViewController viewWillAppear:] 
9 PhotoLibrary -[PLUILibraryViewController viewWillAppear:] 
10 UIKit -[UINavigationController _startTransition:fromViewController:toViewController:] 
11 UIKit -[UINavigationController _startDeferredTransitionIfNeeded] 
12 UIKit -[UILayoutContainerView layoutSubviews] 
13 QuartzCore -[CALayer layoutSublayers] 
14 QuartzCore CALayerLayoutIfNeeded 
15 QuartzCore CA::Context::commit_transaction(CA::Transaction*) 
16 QuartzCore CA::Transaction::commit() 
17 QuartzCore CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) 
18 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ 
19 CoreFoundation __CFRunLoopDoObservers 
20 CoreFoundation __CFRunLoopRun 
21 CoreFoundation CFRunLoopRunSpecific 
22 CoreFoundation CFRunLoopRunInMode 
23 GraphicsServices GSEventRunModal 
24 GraphicsServices GSEventRun 
25 UIKit UIApplicationMain 

新コード:

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 
    [m_pPopoverController dismissPopoverAnimated:true]; 

    [m_pPopoverController release]; 
    m_pPopoverController = nil; 

    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; 

    [self dismissModalViewControllerAnimated:YES]; 

    if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) { 
     UIImage *picture = [info objectForKey:UIImagePickerControllerOriginalImage]; 

     [self UseImage:picture:picker];  
    } 

    [picker dismissModalViewControllerAnimated:YES]; 

// [picker release]; // <- CAUSES CRASH on BOTH iOS4 and iOS5. 
} 


- (void)SelectPhoto 
{ 
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary ]) 
    { 
     self.view = g_glView; 

     UIImagePickerController *pImagePicker; 

     pImagePicker = [[UIImagePickerController alloc] init]; 

     pImagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 

     pImagePicker.delegate = self; 

     pImagePicker.mediaTypes = [NSArray arrayWithObjects:(NSString *) kUTTypeImage, nil]; 

     pImagePicker.allowsEditing = NO; 

     m_pPopoverController = [[UIPopoverController alloc] initWithContentViewController:pImagePicker]; 
     m_pPopoverController.delegate = self; 

     [m_pPopoverController setPopoverContentSize:CGSizeMake(160,160) animated:YES]; 
     CGRect selectedRect = CGRectMake(0,0,1,1); 
     [m_pPopoverController presentPopoverFromRect:selectedRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 

     [pImagePicker release]; 
    } 
} 
ここ

は私UseImageコードです:

- (void)UseImage:(UIImage*)theImage:(UIImagePickerController *)picker 
{ 
    CGFloat width, height; 

    // if image came from camera, save it to photo library 
    if(picker.sourceType == UIImagePickerControllerSourceTypeCamera) 
    { 
     UIImageWriteToSavedPhotosAlbum(theImage, nil, nil, nil);  
    } 

    CGImageRef imageRef = [theImage CGImage]; 
    width = CGImageGetWidth(imageRef); 
    height = CGImageGetHeight(imageRef);  

    size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef); 

    m_photoWidth = width; 
    m_photoHeight = height; 
    m_bytesPerPixel = bitsPerPixel/8; 


    CGContextRef cgctx = CreateARGBBitmapContextPopOver(theImage.CGImage, picker.sourceType, m_pClient); 
    if (cgctx == NULL) 
    { 
     // error creating context 
     return; 
    } 

    // Get image width, height. We'll use the entire image. 
    size_t w = CGImageGetWidth(theImage.CGImage); 
    size_t h = CGImageGetHeight(theImage.CGImage); 
    CGRect rect = {{0,0},{w,h}}; 

    // set the blend mode so we don't blend into the previous pixels, instead we copy over them. 
    CGContextSetBlendMode(cgctx, kCGBlendModeCopy); 

    // Draw the image to the bitmap context. Once we draw, the memory 
    // allocated for the context for rendering will then contain the 
    // raw image data in the specified color space. 
    CGContextDrawImage(cgctx, rect, theImage.CGImage); 

    // Now we can get a pointer to the image data associated with the bitmap 
    // context. 
    m_pPixelData = reinterpret_cast<char*>(CGBitmapContextGetData (cgctx)); 

    m_bytesPerPixel = 4; 

    // any client using the photo processing package is required to implement SELECT_PHOTO to its CLIENT_STATE 
    m_pClient->SetState(GEClient::LOADING_PHOTO); 

    m_pClient->PassPixelDataFromCamera(m_pPixelData, m_photoWidth, m_photoHeight, m_bytesPerPixel); 

    // When finished, release the context 
    CGContextRelease(cgctx); 
} 


CGContextRef CreateARGBBitmapContextPopOver (CGImageRef inImage, UIImagePickerControllerSourceType sourceType, GEClient* pClient) 
{ 
    CGContextRef context = NULL; 
    CGColorSpaceRef colorSpace; 
    void *   bitmapData; 
    int    bitmapByteCount; 
    int    bitmapBytesPerRow; 

// Get image width, height. We'll use the entire image. 
    size_t pixelsWide = CGImageGetWidth(inImage); 
    size_t pixelsHigh = CGImageGetHeight(inImage); 
    NSLog(@"Camera resolution:%lu x %lu", pixelsWide, pixelsHigh); 


    // Declare the number of bytes per row. Each pixel in the bitmap in this 
    // example is represented by 4 bytes; 8 bits each of red, green, blue, and 
    // alpha. 
    bitmapBytesPerRow = (pixelsWide * 4); 
    bitmapByteCount  = (bitmapBytesPerRow * pixelsHigh); 

    // Use the generic RGB color space. 
    colorSpace = CGColorSpaceCreateDeviceRGB(); 
    if (colorSpace == NULL) 
    { 
     fprintf(stderr, "Error allocating color space\n"); 
     return NULL; 
    } 

    // Allocate memory for image data. This is the destination in memory 
    // where any drawing to the bitmap context will be rendered. 
    bitmapData = malloc(bitmapByteCount); 
    if (bitmapData == NULL) 
    { 
     fprintf (stderr, "Memory not allocated!"); 
     CGColorSpaceRelease(colorSpace); 
     return NULL; 
    } 

    // Create the bitmap context. We want pre-multiplied ARGB, 8-bits 
    // per component. Regardless of what the source image format is 
    // (CMYK, Grayscale, and so on) it will be converted over to the format 
    // specified here by CGBitmapContextCreate. 
    context = CGBitmapContextCreate (bitmapData, 
           pixelsWide, 
           pixelsHigh, 
           8,  // bits per component 
           bitmapBytesPerRow, 
           colorSpace, 
           kCGImageAlphaPremultipliedFirst); 
    if (context == NULL) 
    { 
     free (bitmapData); 
     fprintf (stderr, "Context not created!"); 
    } 

// Make sure and release colorspace before returning 
    CGColorSpaceRelease(colorSpace); 

    return context; 
} 

答えて

0

私はここで野生の刺すようです。あなたのコードはかなり良く見えますが、疲れていて何かが欠けているかもしれませんが、テストのために "[pImagePicker release];という行を削除してください。何が起こるか見る。これは最終的な推奨ではありませんが、試してみる価値があります。

私はイメージピッカーと同様のものに遭遇し、リリースを行った場所を変更して問題を解決しました。

+0

これは動作しますが、2つのメモリリーク、つまり32Kリークと128kリークが発生します。私はそれらを主な質問に加えました。 –

0

ポップオーバーを解除するときに、ポップオーバーコントローラのデリゲートをnilに設定します。私はあなたのviewControllerのデリゲートメソッドにアクセスしようとしているフレームワークコードに何かがあると思います。 Popoverからデリゲートを削除すると、この問題が解決され、Popoverを適切に解放することができました。それがなぜ4でしか起こらないのか分からないが、そこに行く。うまくいけばそれはあなたの問題を解決します。

関連する問題