0

我试图制作一个像这样的自我生产课程:

Test *test = [[Test alloc] init];
[test setFrame:frame];
[test setBackgroundColor:[UIColor redColor]];
[self addSubview:test];

这是一个UIView子类,此代码在initWithFrame:方法内部。类Test是它自己的名字,自产。

现在我遇到了问题,我在第一行添加了一个断点,你可以在上面看到,我看到它永远不会通过第一行,只是创建一个新实例,但从未将它添加到视图中。这是不可能的还是我应该“研究”更多如何正确地做到这一点?

想象一下它的样子:xCode 的图像

如您所见,它永远不会超过第一行。

4

3 回答 3

4

我现在明白了。initWithFrame:您的代码的问题是您忘记了UIView指定的初始化方法。因此,即使您调用[[Test alloc] init]init调用也会调用initWithFrame:自身,从而创建一个无限循环。

编辑

在 iOS 中有一个“指定”初始化程序的概念。每当您有多个“init”方法时,您都必须将其中一个设为“指定”init。例如,UIView的指定初始值设定项是initWithFrame。这意味着所有其他 init 方法都会在后台调用它,即使是 init。

这是UIView'sinit方法的样子:

-(id)init {
    return [self initWithFrame:CGRectMake(0,0,0,0)];
}

这意味着即使您将您的类实例化为 [[Test alloc] init],initWithFrame仍然会被UIView.

initWithFrame:现在,您在您的类中覆盖,Test并且您还在该方法中创建另一个Test实例,该方法再次调用initWithFrame:

// the init call you have inside this method is calling initWithFrame again beacause
// you're referring to the same Test class...
-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        // This line here is creating the infinite loop. Right now you're inside
        // Test's initWithFrame method. Here you're creating a new Test instance and
        // you're calling init... but remember that init calls initWithFrame, because
        // that's the designated initializer. Whenever the program hits this line it will 
        // call again initWithFrame which will call init which will call initWithFrame 
        // which will call init... ad infinitum, get it?
        Test *test = [[Test alloc] init];

        [test setFrame:frame];
        [test setBackgroundColor:[UIColor redColor]];
        [self addSubview:test];
    }
}

EDIT2:一种可能的解决方法

为了防止这种情况,您可以做的一件事是声明一个static bool变量(标志)来指示是否Test应该继续创建更多自身的实例:

static BOOL _keepCreating = YES;

@implementation Test

-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        // Remember to set _keepCreating to "NO" at some point to break
        // the loop
        if (_keepCreating) 
        {
            Test *test = [[Test alloc] init];
            [test setFrame:frame];
            [test setBackgroundColor:[UIColor redColor]];
            [self addSubview:test];
        }
    }
}

@end

希望这可以帮助!

于 2013-10-22T22:05:30.147 回答
1

你写了一个无限循环。这不是关于-init-initWithFrame:。对 init 的每次调用都会创建另一个 Test 实例,该实例创建另一个 Test 实例,该实例创建另一个 Test 实例......

相反,我会将子视图创建为 Test 的属性,如下所示:

@interface Test : UIView
@property ( nonatomic, readonly ) Test * testSubview ;
@end

然后创建一个惰性初始化访问器testSubview

@implementation Test

-(Test*)testSubview
{
    if ( !_testSubview )
    {
        Test * view = [ [ Test alloc ] initWithFrame:CGRectZero ] ;
        [ self addSubview:view ] ;
        _testSubview = view ;
    }
    return _testSubview ;
}

-(void)layoutSubviews
{
    [ super layoutSubviews ] ;
    [ self.testSubview setFrame:self.bounds ] ; // testSubview will be created if it doesn't exist...
}

@end
于 2013-10-22T23:04:49.783 回答
0

你想要完成什么?

你跟注initWithFrame的同时也是顺子init,这有点奇怪。

根据其余代码的外观,您可能会进入无限循环领域,创建无限的Test对象流并将它们添加为它们自己的子视图。

也许您正在寻找返回类的新实例的Test类方法?看起来像这样:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setBackgroundColor:[UIColor redColor]];
    }
    return self;
}

+ (id)testWithFrame:(CGRect)frame
{
    Test * test = [[Test alloc] initWithFrame:frame];
    return test;
}

如果您真的在寻找Test作为另一个对象的子视图添加的Test对象,您可以在testWithFrame:方法中执行此操作。

于 2013-10-22T22:09:16.630 回答