弱属性无法在swift 3.0中初始化

时间:2017-01-11 04:43:11

标签: ios objective-c swift

所以这是swift中的一个定义:

@objc(ChartAxisBase)
open class AxisBase: ComponentBase
{
    public override init()
    {
        super.init()
    }

    /// Custom formatter that is used instead of the auto-formatter if set
    weak fileprivate var _axisValueFormatter: IAxisValueFormatter?
}

这里是valueFormatter的getter和setter:

open var valueFormatter: IAxisValueFormatter?
{
    get
    {
        if _axisValueFormatter == nil ||
            (_axisValueFormatter is DefaultAxisValueFormatter &&
                (_axisValueFormatter as! DefaultAxisValueFormatter).hasAutoDecimals &&
                (_axisValueFormatter as! DefaultAxisValueFormatter).decimals != decimals)
        {
            let df = DefaultAxisValueFormatter(decimals: decimals)
            _axisValueFormatter = df
            NSLog("found nil vf, assigning to \(_axisValueFormatter)")
        }
        NSLog("returning _axisValueFormatter: \(_axisValueFormatter)")
        return _axisValueFormatter
    }
    set
    {
        _axisValueFormatter = newValue ?? DefaultAxisValueFormatter(decimals: decimals)
    }
}

setter将检测_axisValueFormatter是否为nil,它将为它创建一个默认值并返回。

但是,稍后在Objective-C文件中,我尝试将其初始化为:

-(void)viewDidLoad {
    ChartXAxis *xAxis = _chartView.xAxis;
    ChartDefaultAxisValueFormatter *f = [[ChartDefaultAxisValueFormatter alloc] initWithFormatter:leftAxisFormatter];
    xAxis.valueFormatter = [[ChartDefaultAxisValueFormatter alloc] initWithFormatter:leftAxisFormatter];
    NSLog(@"x axis vf:%@", xAxis.valueFormatter);

    ChartYAxis *leftAxis = _chartView.leftAxis;
    leftAxis.valueFormatter = [[ChartDefaultAxisValueFormatter alloc] initWithFormatter:leftAxisFormatter];
    NSLog(@"left axis vf:%@", leftAxis.valueFormatter);
}
根据log:

xAxis.valueFormatterleftAxis.valueFormatter现在为零

2017-01-11 12:38:25.819 ChartsDemo[49440:3296871] found nil vf, assigning to Optional(<ChartDefaultAxisValueFormatter: 0x608000268480>)
2017-01-11 12:38:25.820 ChartsDemo[49440:3296871] returning nil
2017-01-11 12:38:25.820 ChartsDemo[49440:3296871] x axis vf:(null)
2017-01-11 12:38:25.821 ChartsDemo[49440:3296871] found nil vf, assigning to Optional(<ChartDefaultAxisValueFormatter: 0x608000269e80>)
2017-01-11 12:38:25.821 ChartsDemo[49440:3296871] returning nil
2017-01-11 12:38:25.821 ChartsDemo[49440:3296871] left axis vf:(null)

然而,

如果我为leftAxis更改了这样的内容:

ChartDefaultAxisValueFormatter *lf = [[ChartDefaultAxisValueFormatter alloc] initWithFormatter:leftAxisFormatter];
leftAxis.valueFormatter = lf;
NSLog(@"left axis vf:%@", leftAxis.valueFormatter);

leftAxis现在将有一个格式化程序:

2017-01-11 12:40:26.147 ChartsDemo[49582:3311643] returning Optional(<ChartDefaultAxisValueFormatter: 0x608000265cc0>)
2017-01-11 12:40:26.147 ChartsDemo[49582:3311643] left axis vf:<ChartDefaultAxisValueFormatter: 0x608000265cc0>

我知道这不是一个好的用户案例,因为它很弱,在viewDidLoad()完成后,它应该全部消失,但只是坚持日志,我现在很困惑,我不认为创建一个新的指针会很重要。我想我应该犯一个愚蠢的错误,但目前看得太瞎了。

对于任何可以提供帮助的人,请从以下位置下载整个项目: https://github.com/liuxuan30/Charts/archive/Weak.zip

您可以使用BarChartViewController.m中的代码替换viewDidLoad对应项。

可能需要您通过Realm安装carthage bootstrap才能运行ChartsDemo。

1 个答案:

答案 0 :(得分:0)

在这一行上,您看起来正在构建一个新对象并将其分配给弱引用:

 _axisValueFormatter = newValue ?? DefaultAxisValueFormatter(decimals: decimals)

你不能这样做,因为它的保留计数为零(弱引用不会调用retain)。因此它将立即释放,因为当您的保留计数变为0并且您新创建的对象被取消初始化时会发生什么。有人需要对该对象保持强烈的引用。

这有什么理由需要弱吗?弱通常用于打破保留周期,但我不认为您的DefaultAxisValueFormatter保留了AxisBase实例,因为您没有将它传递给构造函数。

您的目标C代码存在同样的问题。初始化一个强引用并将其分配给堆栈中的变量f(保留计数为1)。您将f指定给弱引用(保留计数仍为1),然后f超出范围,保留计数降为0并且对象被取消分配;你的弱参考现在指向零。提升f为一个属于该类生命的属性,而不仅仅是viewDidLoad,它应该解决问题,但我认为除非你有一个令人信服的用途,否则最好完全摆脱弱点。