Swift / cornerRadius和masksToBounds使UIImageView消失

4

我有一个带有UIImageViewUITableViewController。以下是加载内容的简单代码。

@IBOutlet weak var avatarImageView: UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()

    updateUI()
}

func updateUI() {

    backendless.userService.currentUser.retrieveProperties()

    avatarImageView.layer.cornerRadius = avatarImageView.frame.size.width/2
    avatarImageView.layer.masksToBounds = true

    let imgURL = NSURL(string: (backendless.userService.currentUser.getProperty("Avatar") as? String)!)
    avatarImageView.sd_setImageWithURL(imgURL)

    tableView.reloadData()

}

ImageView没有显示。

但是,如果我删除以下代码,UIImageView将被设置并正确显示。

avatarImageView.layer.cornerRadius = avatarImageView.frame.size.width/2
avatarImageView.layer.masksToBounds = true

我错过了什么?非常感谢你的帮助。
注:使用Xcode 8.0和Swift 2.3;ImageView的限制设置为120 * 120;使用sd_setImageWithURL需要安装pod 'SDWebImage'插件。
参考图:enter image description here

这只是一个猜测,你可以尝试将 width/2 更改为 width/2.0 并运行一次吗?这可能也是自动布局约束的问题。 - Mahesh Agrawal
@M.K. width/2.0 没有区别 - UIImageView 仍然不显示。 - David Seek
在这行代码之前放置一个调试器并检查宽度是否有值,因为这段代码在任何地方都可以工作。我认为代码本身没有问题,问题可能出现在代码的顺序和正确的调用位置上。 - Mahesh Agrawal
print("width = (avatarImageView.frame.size.width)") 这里打印出的是1.000...,但是我确实设置了约束为150... 嗯嗯,你可能对你的猜测是对的... - David Seek
我猜这是因为它位于UITableViewController内部。你能否尝试将同样的代码放在一个普通的UIViewController中,附带一张图片来测试? - Mahesh Agrawal
显示剩余5条评论
4个回答

5
试试这个:

override func viewDidLoad() {
    super.viewDidLoad()

    self.view.layoutIfNeeded() // <- This will update your initial view frames
    updateUI()
}

在Xcode 8.0中,当你进入viewDidLoad时,控制器所有子视图的框架仍然是x: 0.0,y: 0.0,w: 1000.0,h: 1000.0,因此实际上你正在使头像图片视图的圆角半径为500.0pt。当你调用布局(layout)时,将会计算出正确的框架,并给你所期望的值。

4

一个明显的问题是你调用了 updateUI 太早了。在 viewDidLoad 中,没有 UI。视图已经加载进来了,但那只是一部分;它还没有在界面中,也没有进行布局。你的代码依赖于 avatarImageView.frame,但我们还不知道那是什么。你对图片视图设置了约束,但它们还没有生效!因此,你应该推迟这个调用,直到界面出现后再调用,例如在 viewDidAppear 或至少是 viewDidLayoutSubviews 中。但当然,那时你可能只想调用它一次(在浏览器中输入,未经测试,但将类似于以下内容):

var didConfigureUI = false
func viewDidLayoutSubviews() {
    if !didConfigureUI {
        didConfigureUI = true
        updateUI()
    }
}

在viewDidLayoutSubviews中调用它会导致应用程序在无限循环中冻结。我的print("width = \(avatarImageView.frame.size.width)")在updateUI中将被无限调用。但除此之外,你是正确的。在viewDidAppear中调用所有内容。 - David Seek
你的工作是加入一个“标志”,以防止递归循环。毕竟,你只想让这段代码运行一次,对吧? - matt
谢谢 @matt。我会记住的,并尝试了解更多关于如何放置标志的信息。非常感谢您的帮助和努力。 - David Seek

1
我认为你的问题出在控制器上。你已经将图像视图添加到UITableViewController中。这意味着如果你在viewDidLoad中使用frame,那么设置给图像视图的约束将不起作用。你需要在使用它之前改变UIImageView的frame或者使用UIViewController。在使用图像视图的frame之前,请使用以下代码。
avatarImageView.frame.size.width = 120.0
avatarImageView.frame.size.height = 120.0

我认为这会解决问题。但是如果没有特殊目的,您应该使用UIViewController而不是UITableViewController。

0
“xy.view.layoutIfNeeded()” 

每次在视图完成加载之前调用属性时都需要调用它,例如imageView.view.layoutIfNeeded()以获取高度和宽度值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接