【问题标题】:Swift: Reusable UIView in storyboard and sizing constraintsSwift:故事板中的可重用 UIView 和大小约束
【发布时间】:2015-11-10 18:02:43
【问题描述】:

我正在尝试在 Swift 中创建一个可重用的 UIView,我可以将它插入到我的 Storyboard 视图控制器中。我现在的关键问题是可重用的 UIView“小部件”不完全适合故事板中的 UIView 框。我跟着this tutorial 设置了可重用的 UIView 小部件

  1. 创建了一个 UIView 的子类和一个对应的 .xib -- 并将它们连接起来:

    import UIKit
    
    class MyWidgetView: UIView {
    
    @IBOutlet var view: UIView!;
    
    required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder);
    
    NSBundle.mainBundle().loadNibNamed("MyWidgetView", owner: self, options: nil);
    self.addSubview(self.view);
    }
    
    }
    
  2. 在上面代码对应的接口文件XIB中,我使用了Simulated Metrics下的UIView with Freeform size,View mode下使用Scale to Fill。

  3. 在主情节提要中,我添加了一个 UIView 块(相同的矩形形状)并将 Class 更改为 MyWidgetView

  4. 虽然我在 XIB 和主情节提要中都使用了布局约束,但我在 XIB 中创建的组件在实际应用程序中看起来被压扁了。

查看屏幕截图。粉红色的部分不应该出现,因为它只是主故事板上的 UIVIew 的颜色,我添加它以测试大小。该 UIView 实际上是 MyWidgetView (在我在步骤 3 中更改了类之后。所以理论上,由于 MyWidgetView == 主情节提要上的 UIView,并且 UIView 具有使其在超级视图中成为矩形的约束,那么为什么我的小部件会被压扁?下面的蓝色部分应该一直向右延伸。

【问题讨论】:

    标签: swift uiview autolayout


    【解决方案1】:

    从代码中的 nib 文件加载的实际视图层次结构是通过添加 self.addSubview(self.view)。所以,self.view 的框架实际上与其父级没有关系,即MyWidgetView

    您可以选择通过代码添加布局约束或在添加为子视图后仅设置其框架。就个人而言,我更喜欢后者。在我的实验中,以下对我有用。我使用的是 Xcode 6.4,我认为它和你的不一样。

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    
        if let nibsView = NSBundle.mainBundle().loadNibNamed("MyWidgetView", owner: self, options: nil) as? [UIView] {
            let nibRoot = nibsView[0]
            self.addSubview(nibRoot)
            nibRoot.frame = self.bounds
        }
    }
    

    【讨论】:

    • 好的,我试试这个。我有 XCode 7 beta 5 和 Swift 2.0,所以我可以在我的设备上加载应用程序,而无需通过 Apple 的 99 美元订阅。
    • 令人印象深刻...这行得通。你能解释一下它是如何工作的吗?尤其是在“nibRoot”周围——我不确定我是否完全理解这部分。
    • 很高兴它有效!如the official document 中所述,NSBundle.loadNibNamed() 的返回值是包含 nib 文件中顶级对象的数组。在我们的例子中,只有一个顶级对象:一个包含所有MyWidgetView 视图层次结构的视图。因此,在成功调用loadNibNamed 后,我们选择了第一个也是唯一一个视图为nibRoot,并将其添加为子视图。
    • 这是我写的一个明确的问题和答案,适用于自动布局。 stackoverflow.com/questions/30335089/…
    • 您可以在此处找到有关如何正确操作的详细说明:stackoverflow.com/a/34524346/971329。如果您需要关心所有内容的可重用超级视图的 Swift 实现,请参阅下面的评论。
    【解决方案2】:

    或者,可以覆盖可变框架。当 CardImgText 设置为视图的文件所有者时,此代码对我有用。

    class CardImgTxt: NSView {
    
        @IBOutlet var view: NSView!
        override var frame: NSRect{
            didSet{
                view.frame = bounds
            }
        }
    
        override func drawRect(dirtyRect: NSRect) {
            super.drawRect(dirtyRect)
    
    
            // Drawing code here.
        }
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            NSBundle.mainBundle().loadNibNamed("View", owner: self, topLevelObjects: nil)
            addSubview(view)
        }
    
    }
    

    如果您对效率比实时更新更感兴趣。然后替换:

        override var frame: NSRect{
            didSet{
                view.frame = bounds
            }
        }
    

    与:

    override func viewDidEndLiveResize() {
        view.frame = bounds
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-08
      • 2017-06-07
      • 1970-01-01
      • 1970-01-01
      • 2016-01-09
      • 2016-06-27
      相关资源
      最近更新 更多