对象在初始化后立即释放

时间:2013-11-27 10:30:39

标签: ios objective-c uiwebview youtube

我正在尝试制作一个播放YouTube视频的课程,但我遇到了一些问题。

以下是我处理YouTube视频的课程:

// this is the only property declared in the .h file:
@property (strong, nonatomic) UIView * view

// the rest of this is the .m file:
#import "MyYouTube.h"
@interface MyYouTube()
@property (strong, nonatomic) NSDictionary * contentData;
@property (strong, nonatomic) UIWebView * webView;
@property (nonatomic) int videoOffset;
@end

@implementation MyYouTube
@synthesize view,contentData,webView,videoOffset;

- (MyYouTube*) initIntoView: (UIView*) passedView withContent: (NSDictionary*) contentDict {
    NSLog(@"YOUTUBE: begin init");
    self=[super init];
    videoOffset=0;
    view=[[UIView alloc] initWithFrame:passedView.bounds];
    [view setBackgroundColor:[UIColor blackColor]];
    [view setAutoresizesSubviews:YES];
    [view setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
    contentData=contentDict;

    NSString * compiledUrl=[[NSString alloc] initWithFormat:@"http://_xxx_.com/app/youtube.php?yt=%@",[contentData objectForKey:@"cnloc"]];
    NSURL * url=[[NSURL alloc] initWithString:compiledUrl];
    NSURLRequest * request=[[NSURLRequest alloc] initWithURL:url];

    webView=[[UIWebView alloc] initWithFrame:passedView.bounds];
    [webView loadRequest:request];
    [webView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
    [[webView scrollView] setScrollEnabled:NO];
    [[webView scrollView] setBounces:NO];
    [webView setMediaPlaybackRequiresUserAction:NO];
    [webView setDelegate:self];

    NSLog(@"YOUTUBE: self: %@",self);
    NSLog(@"YOUTUBE: delegate: %@",webView.delegate);

    [view addSubview:webView];
    NSLog(@"YOUTUBE: end init");
    return self;
}

-(void)webViewDidFinishLoad:(UIWebView*)myWebView {
    NSLog(@"YOUTUBE: send play command");
    [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"playVideo(%d)", videoOffset]];
}

- (void) dealloc {
    NSLog(@"YOUTUBE: dealloc");
}
@end

以下是调用此类的代码(此代码位于appDelegate中):

NSLog(@"about to load youtube");
ytObj=[[MyYouTube alloc] initIntoView:mainView withContent:cn];
NSLog(@"loaded youtube");
[mainView addSubview:[ytObj view]];

FYI mainView和ytObj声明为:

@property (nonatomic,strong) UIView * mainView;
@property (nonatomic,strong) MyYouTube * ytObj;

运行此代码时,应用程序崩溃,我在控制台中收到此信息:

about to load youtube
YOUTUBE: begin init
YOUTUBE: self: <MyYouTube: 0x16503d40>
YOUTUBE: delegate: <MyYouTube: 0x16503d40>
YOUTUBE: end init
YOUTUBE: dealloc
loaded youtube
*** -[MyYouTube respondsToSelector:]: message sent to deallocated instance 0x166f19f0

如果我将UIWebView委托设置为nil,那么该应用不会崩溃,但正如预期的那样,YouTube视频无法自动播放。

任何人都可以向我解释:

  • 为什么对象在发生之后立即解除分配 初始化

  • 为什么将respondsToSelector:消息发送给 除了MyYouTube之外的其他实例?

  • 如何在不崩溃的情况下让YouTube视频自动播放?

非常感谢。


修改

完全是我的坏 - ytObj是一个强大的财产 - 我忘了提到这一点。我添加了代码以反映这一点。


编辑2

我在dealloc方法上添加了一个断点,这是调用堆栈:

0 -[MyYouTube dealloc]
1 objc-object::sidetable_release(bool)
2 -[MyAppDelegate playYouTube:]

此处的最后一个条目(playYouTube:)是包含我的应用委托中代码的方法,该代码位于上面的原始帖子中。那么,还有一个问题:

  • 什么是objc-object::sidetable_release(bool),它做了什么,为什么要发布我的YouTube对象?

3 个答案:

答案 0 :(得分:2)

  

为什么对象在初始化后会立即解除分配?

因为没有东西拥有它。

您将其设置为视图的委托,但UIWebView的委托属性是assign属性。该视图不接受其委托的所有权。这意味着当ytObj超出范围时(可能之前,取决于优化)没有任何拥有它,所以它消失了。

修改

您还需要确保在取消分配ytObj时,将其仍为委托的任何视图的委托属性设置为nil。否则视图将继续尝试将消息发送到解除分配的对象。

  

如果没有应用程序崩溃,如何让YouTube视频自动播放?

您需要确保ytObj只要作为委托的视图持续,并且在取消分配时,它的视图的委托设置为nil。


另一个小问题。您的-init函数应在调用self = [super init]后测试self不为nil。如果self为nil,它不应运行任何其余的初始化代码。

答案 1 :(得分:1)

1)(我的第一个问题的第一个答案,在你编辑之前)

这种情况正在发生,因为您正在使用ARC(自动引用计数)并且您没有保留本地&#34; ytObj&#34;在您创建它的对象中的变量((不是&#34; self.ytObj&#34;属性)。一旦创建了本地&#34; ytObj的函数&#34;变量完成并返回,对象自动解除分类。

改变这个:

ytObj=[[MyYouTube alloc] initIntoView:mainView withContent:cn];

到此:

self.ytObj=[[MyYouTube alloc] initIntoView:mainView withContent:cn];

对于&#34;最佳做法&#34;,我还建议您不要在应用程序委托中执行太多工作和/或代码。应用程序代表意味着接收特定于应用程序的消息(例如&#34;应用程序正在暂停&#34;,&#34;应用程序再次变为活动状态&#34;等等),您应该在子类视图中执行此类操作控制器。

2)

&#34; respondsToSelector:&#34;您看到的错误是因为您的YouTube对象已自动解除分类错误。如果它仍然存在,你就不会看到这个消息。

3)

如果您在此处搜索Stackoverflow,您将找到解释如何进行自动播放的其他问题和解答... like how about this one?

答案 2 :(得分:0)

对象ytObj因为在任何地方都没有强引用,它只存在于定义的范围内。代表大部分时间都被宣布为弱房产。没有人坚持引用这个对象,因此ARC发布它 为ytObj创建一个强大的属性,您将看到一切正常。