iOS自定义视图 - 非常奇怪的属性行为

时间:2016-06-19 15:42:01

标签: ios iphone swift null iboutlet

使用Swift 2.0

我正在尝试使用带有标签的自定义视图(不仅仅是那个)在屏幕上显示一些信息,所以我的想法是以编程方式将自定义视图添加到ViewController上的滚动视图,并设置标签的文本(开头)

问题:我只是无法得到标签和我希望设置标签文本的字符串不为空的时刻,并且由于某种原因字符串最后变为空

所以我进行了大量的调试,以显示每个时刻每个var的状态,这让我更加困惑: (这是Xcode的日志输出)

my init was called, fatura String value: Optional("random text")
init with coder was called

 - On awake from Nib
Label outlet is NOT null
fatura String is null
view loaded from Nib was added

 - On Setup
Label outlet is null
fatura String is NOT null
checking fatura String value from ViewController: Optional("random text")

 - On ViewController's viewDidLoad
Label outlet is null
fatura String is NOT null

 - On ViewController's viewWillAppear
Label outlet is null
fatura String is NOT null

 - On Button touched action
Label outlet is NOT null
fatura String is null

我是iOS的新手,来自Android开发的几年,我想真正理解发生了什么,所以任何好的文章和书籍也会受到欢迎。我在自定义视图中发现了很多东西,但它们都有些不同,所以我不知道使用哪一个,它们主要是实现,没有任何解释。

问题:

  • 为什么在加载Nib视图之前,vencimentoLb Label的出口是否为“not null”?

  • 为什么在调用*我的init后,fatura String为null,将其设置出来? *至少这是日志告诉我的内容

  • 为什么我的fatura在buttonClicked动作上的字符串null?

总结:如何让标签和字符串都不为空,那么要在标签上设置文字?

我知道这是很多问题,所以非常感谢他们对任何一个问题的回答

找到“解决方案”:

调用customview.view强制插座实现。不起作用(customview没有我创建的视图成员,并且调用那个没有区别)

自定义视图的代码:

class FaturaCard: UIView {

    var view:UIView!
    @IBOutlet var vencimentoLb: UILabel!
    @IBOutlet var cardView: UIView!

    var fatura:String?

    init(string:String , frame:CGRect){
        fatura = string
        print("my init was called, fatura String value:",self.fatura)
        super.init(frame: frame)
        setup()
    }

    override init(frame: CGRect){
        super.init(frame:frame)
        print("init with frame was called")
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        print("init with coder was called")
    }

    @IBAction func onBotaoClicked(sender: AnyObject) {
        print("\n - On Button touched action")
        checksWhatsNull()
    }

    func setup(){
        view = loadViewFromNib()
        view.frame = bounds
        view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
        addSubview(view)
        print("view loaded from Nib was added")
        print("\n - On Setup")
        checksWhatsNull()
    }

    func checksWhatsNull(){
        if vencimentoLb == nil{
            print("Label outlet is null")
        }else{
            print("Label outlet is NOT null")
        }

        if self.fatura == nil{
            print("fatura String is null")
        }else{
            print("fatura String is NOT null")
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        print("\n - On awake from Nib")
        checksWhatsNull()
    }

    func loadViewFromNib() -> UIView{
        let nib = UINib(nibName: "FaturaCard", bundle: nil)
        let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
        return view
    }

}

修改

自定义视图实例化代码:

var view2:FaturaCard!
override func viewDidLoad() {
        super.viewDidLoad()

        view2 = FaturaCard(string:"random text",frame: CGRect(x: 00, y:145, width: scrollView.bounds.size.width, height: 145))

        print("checking fatura String value from ViewController:",view2.fatura)

        self.scrollView.addSubview(view2)

        print("\n - On ViewController's viewDidLoad")
        view2.checksWhatsNull()

        self.scrollView.contentSize.height=145*2
    }

2 个答案:

答案 0 :(得分:1)

您的问题日志中有两个来自init语句的输出。

这意味着您要加载自定义视图的两个实例。

您看到的日志来自不同的实例,具体取决于操作 - 值不会更改,您将看到来自不同实例的值。

在您的日志记录中添加print(self)应该有助于明确这一点。

当您从笔尖或故事板创建视图时,

init(coder:)将会出现。您正在使用自定义init(在日志中看到)创建视图,然后在setUp方法中创建视图的第二个实例,并将其保存在原始视图中。这不对。

我认为您已经阅读了有关访问view以强制加载视图的信息,并尝试在此处执行此操作 - 这适用于查看控制器,而不是视图,以及根本不适用于您的情况。

你应该直接从笔尖创建视图,然后设置fatura属性 - 不可能从问题中的内容来判断,但我认为你的网点是指向主视图本身而不是文件的所有者,因此您可以使用nil的所有者创建。

查看更新的代码,您可能想要这样的东西。

而不是viewDidLoad中的这一行:

view2 = FaturaCard(string:"random text",frame: CGRect(x: 00, y:145, width: scrollView.bounds.size.width, height: 145))

使用此:

let nib = UINib(nibName: "FaturaCard", bundle: nil)
view2 = nib.instantiateWithOwner(nil, options: nil)[0] as! FaturaCard
view2.frame = CGRect(x: 00, y:145, width: scrollView.bounds.size.width, height: 145)
view2.fatura = "Random Text"

来自笔尖的笨拙加载视图,理想情况下,您可以将这些内容放在FaturaCard上的类方法中,您也可以传入一个框架和一个字符串。

答案 1 :(得分:0)

所以,最后问题出在Interface Builder中。

我已经在nib的主视图中的Identity Inspector上设置了Custom Class属性,而不是在File的所有者占位符中。 这创造了一个FaturaCard' FaturaCard视图中的自定义视图,一次创建两个实例(正如jrturton的答案所述),第二个由init(编码器:)初始化,创造了所有麻烦。

这是一个初学者的错误,非常令人困惑。