0

我有一个带有多个视图控制器并启用了 ARC 的 iOS 应用程序。其中一个视图控制器有一个IBOutletforUIScrollViewUIPageControl. 加载该视图控制器时,控制台中会打印此错误:

*** -[NSRecursiveLock dealloc]: lock (<NSRecursiveLock: 0xcb88cb0> '(null)') 
deallocated while still in use

在尝试解决问题时,我为符号设置了一个符号断点,_NSLockError并将模块设置为 Foundation。"0x12d2b58: pushl %ebp"现在 Xcode在线程 1上以断点 1.1 中断。

Foundation`_NSLockError:
-----------------------------------------------------
|> 0x12d2b58: pushl %ebp   <|Thread 1: breakpoint 1.1|
-----------------------------------------------------
0x12d2b59:  movl   %esp, %ebp
0x12d2b5b:  subl   $8, %esp
0x12d2b5e:  calll  0x12d2b63                 ; _NSLockError + 11
0x12d2b63:  popl   %eax
0x12d2b64:  leal   2118709(%eax), %eax
0x12d2b6a:  movl   %eax, (%esp)
0x12d2b6d:  calll  0x125689d                 ; NSLog
0x12d2b72:  addl   $8, %esp
0x12d2b75:  popl   %ebp
0x12d2b76:  ret  

这是我的应用程序中有问题的 ViewController 的代码:

头文件(.h):

#import <UIKit/UIKit.h>

@class AboutViewController;

@protocol AboutViewControllerDelegate

- (void)aboutViewControllerDidFinish:(AboutViewController *)controller;
@end

@interface AboutViewController : UIViewController<UIScrollViewDelegate>


@property (strong, nonatomic,retain) id <AboutViewControllerDelegate> delegate;
@property (nonatomic,strong,) IBOutlet UIScrollView *scrollView;
@property (nonatomic, strong) IBOutlet UIPageControl *pageControl;
@property (nonatomic, strong) NSArray *imageArray;
@property(nonatomic, assign) IBOutlet UILabel *label;

- (IBAction)done:(id)sender; //returns back to main menu after a button is pressed

@end

实施文件(.m):

#import "AboutViewController.h"

@interface AboutViewController ()

@end

@implementation AboutViewController

@synthesize scrollView;
@synthesize pageControl;
@synthesize imageArray;

int page;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    //load the images for the scrollview in an array
    imageArray = [[NSArray alloc] initWithObjects:@"1.png", @"2.png", @"3.png", nil];

    for (int i = 0; i < [imageArray count]; i++ ) {
       int page = scrollView.contentOffset.x / scrollView.frame.size.width;

       CGRect frame;
       frame.origin.x = self.scrollView.frame.size.width * i;
       frame.origin.y = 0;
       frame.size = self.scrollView.frame.size;

        UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
        imageView.image = [UIImage imageNamed:[imageArray objectAtIndex:i]];
        [self.scrollView addSubview:imageView];

       NSLog (@"page %d",page);
        if (page==0) {
            self.label.text = [NSString stringWithFormat:@"%s","page1"];
        }


    }

    scrollView.contentSize = CGSizeMake(scrollView.frame.size.
                                    width *[imageArray count],     scrollView.frame.size.height);
}

#pragma mark - UIScrollView Delegate
- (void)scrollViewDidScroll:(UIScrollView *)sender
{

    CGFloat pageWidth = self.scrollView.frame.size.width;
    //calculate current page in scrollview 
    int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    self.pageControl.currentPage = page;
    NSLog (@"page %d",page);

    if (page==0) {
        //change the image caption
        self.label.text = [NSString stringWithFormat:@"%s","Hello"];
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:1.0];
        [_label setAlpha:1];
        [UIView commitAnimations];
    }

    if (page==1) {
        //change the image caption
         self.label.text = [NSString stringWithFormat:@"%s","World"];
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:1.0];
        [_label setAlpha:1];
        [UIView commitAnimations];

    }

    if (page==2) {
        //change the image caption
        self.label.text = [NSString stringWithFormat:@"%s","Foobar"];
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:1.0];
        [_label setAlpha:1];
        [UIView commitAnimations];

      }

}

- (IBAction)done:(id)sender
{
    [self.delegate aboutViewControllerDidFinish:self];

}

@end

在 (lldb)bt 之后:

 * thread #1: tid = 0x1c8f63, 0x012d2b58 Foundation`_NSLockError, queue = 'com.apple.main-thread, stop reason = breakpoint 1.1
        frame #0: 0x012d2b58 Foundation`_NSLockError
        frame #1: 0x01247153 Foundation`-[NSRecursiveLock dealloc] + 159
        frame #2: 0x01820692 libobjc.A.dylib`objc_object::sidetable_release(bool) + 268
        frame #3: 0x01821adf libobjc.A.dylib`-[NSObject release] + 25
        frame #4: 0x05a89385 UIFoundation`_freeExtraData + 48
        frame #5: 0x05a895d5 UIFoundation`-[NSLayoutManager dealloc] + 381
        frame #6: 0x01820692 libobjc.A.dylib`objc_object::sidetable_release(bool) + 268
        frame #7: 0x01821adf libobjc.A.dylib`-[NSObject release] + 25
        frame #8: 0x00a91065 UIKit`-[UITextView dealloc] + 168
        frame #9: 0x00453e6b UIKit`-[UIView release] + 89
        frame #10: 0x0045f2d4 UIKit`-[UIView(Hierarchy) removeFromSuperview] + 292
        frame #11: 0x0047b4fd UIKit`-[UIScrollView removeFromSuperview] + 84
        frame #12: 0x004565db UIKit`-[UIView dealloc] + 432
        frame #13: 0x00477eaf UIKit`-[UIScrollView dealloc] + 1156
        frame #14: 0x00453e6b UIKit`-[UIView release] + 89
        frame #15: 0x0045f2d4 UIKit`-[UIView(Hierarchy) removeFromSuperview] + 292
        frame #16: 0x0047b4fd UIKit`-[UIScrollView removeFromSuperview] + 84
        frame #17: 0x004565db UIKit`-[UIView dealloc] + 432
        frame #18: 0x00453e6b UIKit`-[UIView release] + 89
        frame #19: 0x01ba2380 CoreFoundation`CFRelease + 272
        frame #20: 0x01bc18b4 CoreFoundation`-[__NSArrayM dealloc] + 196
        frame #21: 0x01820692 libobjc.A.dylib`objc_object::sidetable_release(bool) + 268
        frame #22: 0x0181fe81 libobjc.A.dylib`objc_release + 49
        frame #23: 0x01820ce7 libobjc.A.dylib`(anonymous      namespace)::AutoreleasePoolPage::pop(void*) + 537
        frame #24: 0x01bc1fc8 CoreFoundation`_CFAutoreleasePoolPop + 24
        frame #25: 0x00402c6e UIKit`_wrapRunLoopWithAutoreleasePoolHandler + 59
        frame #26: 0x01be89ee     CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
        frame #27: 0x01be893f CoreFoundation`__CFRunLoopDoObservers + 399
        frame #28: 0x01bc6cb0 CoreFoundation`__CFRunLoopRun + 1936
        frame #29: 0x01bc610d CoreFoundation`CFRunLoopRunSpecific + 445
        frame #30: 0x01bc5f3b CoreFoundation`CFRunLoopRunInMode + 123
        frame #31: 0x032e2ff2 GraphicsServices`GSEventRunModal + 192
        frame #32: 0x032e2e19 GraphicsServices`GSEventRun + 104
        frame #33: 0x004054eb UIKit`UIApplicationMain + 1225
        frame #34: 0x0000789d Monarch`main(argc=1, argv=0xbfffee1c) + 141 at main.m:16

我的问题是为什么NSRecursiveLock首先被解除分配?

我从未在代码中提及NSRecursiveLock任何地方。关于这个有一个类似的问题,但不是很详细。

ARC在这里发挥作用吗?

4

2 回答 2

0

我不知道这是否与您的问题有关,但我认为您的属性配置不正确。建议对“IBOutlet”属性使用“weak”而不是“strong”或“assign”(通常outlet是视图控制器的“view”属性的子视图,所以这些子视图被这个“view”属性保留) .

此外,您有一个使用强和保留的代表,您不需要两者,因为您使用的是 ARC,只使用“强”关键字,不再使用“保留”。顺便说一句,因为它是一个委托,你应该使用“弱”属性以避免循环引用。

于 2013-08-09T10:05:21.100 回答
0

在这种 NSRecursiveLock 在仍在使用时被释放的情况下,问题出在 IDE Xcode 上。使用它的最新官方版本解决了这个问题。

于 2013-08-10T07:07:16.480 回答