Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/113.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在视图控制器中访问UIView子类_Ios_Swift_Uiview_Uiviewcontroller - Fatal编程技术网

Ios 在视图控制器中访问UIView子类

Ios 在视图控制器中访问UIView子类,ios,swift,uiview,uiviewcontroller,Ios,Swift,Uiview,Uiviewcontroller,假设我有SomeViewController:UIViewController,我有一个自定义视图CustomView:UIView,定义为XIB,我想显示它。此自定义视图将在其他视图控制器中重复使用,甚至在同一视图控制器中重复使用多次 class CustomView: UIView { @IBOutlet public var label: UILabel! } 我一直以来添加此视图的方式是: class UIExamples: UIViewController { @IBOutl

假设我有
SomeViewController:UIViewController
,我有一个自定义视图
CustomView:UIView
,定义为XIB,我想显示它。此自定义视图将在其他视图控制器中重复使用,甚至在同一视图控制器中重复使用多次

class CustomView: UIView {
  @IBOutlet public var label: UILabel!
}
我一直以来添加此视图的方式是:

class UIExamples: UIViewController {
  @IBOutlet private var myView: UIView!

  override func viewDidLoad() {
    super.viewDidLoad()
    // Assume makeViewFromNib returns the view [0] in the Nib. 
    let customView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
    customView.frame = myView.bounds
    myView.addSubview(customView)
  }
}
假设稍后我想通过公共属性
标签
修改有关
CustomView
的内容

我可以在
viewDidLoad
中执行此操作,只是因为我可以访问
customView
,但是如果我想在其他功能中更改它呢?我所看到的是一个人必须要做的事

let customView = myView.subviews[0] as! CustomView
customView.label.text = "some text"
这看起来不对

因此,我认为正确的方法应该是:

class UIExamples: UIViewController {
  @IBOutlet public var customView: CustomView! // Now this is always a CustomView type

  override func viewDidLoad() {
    super.viewDidLoad()

    // Assume makeViewFromNib returns the view [0] in the Nib. 
    customView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
    customView.label.text = "some text" // DOES NOT WORK!
  }
}
最后一行customView.label.text无效。事实上,屏幕上甚至看不到标签。我做错了什么

好的,没有读到(或者可能在编辑之前读过)您使用的xib。如果ViewController是从xib中创建的,其中包含标签,则这将是正确的方式:

在xib中设置myView类,如下所示:

然后连接IB插座(此处从xib中移除当前插座:

然后从代码)

现在
myView.label.text=“some text”
应该可以正常工作,不会出现进一步的问题。 祝你好运


如果从代码创建视图,请按以下方式执行:

class UIExamples: UIViewController {
  @IBOutlet private var myView: CustomView!

  override func viewDidLoad() {
    super.viewDidLoad()
    // Assume makeViewFromNib returns the view [0] in the Nib. 
    myView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
    myView.frame = view.bounds
    view.addSubview(myView)
  }
}
因为已经有属性将此视图存储在视图控制器中,所以无需在子视图中挖掘,它将像这样工作

myView.label.text = "some text"

原因何在

customView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
    customView.label.text = "some text"
不起作用是因为它是一个全新的视图,没有添加到视图控制器子视图中(顺便说一句,框架也没有设置)。而且,因为您更改了customView属性的值,所以它现在不会指向视图的旧实例,即子视图中的旧实例(您仍然可以看到“旧实例”,但不会更改它)


但我确实建议使用一次创建的指针作为正确的类来避免强制转换。(或者直接在xib/故事板中创建视图,否则不需要
@IBOutlet

发布我自己的答案

  • 创建XIB文件
  • 创建UIView子类Swift文件
  • 在XIB文件所有者的标识检查器自定义类字段下,键入UIView子类名称(自定义视图)
  • 在XIB文件所有者的连接检查器下,确保Swift文件中的所有IBOutlet都已连接
  • 将视图添加到视图控制器,并在其“标识检查器自定义类类型”下指定自定义类名 重要: *在XIB swift文件中,必须正确加载XIB内容视图

    ...
    
      /// Initializer used by Interface Builder.
      required init?(coder: NSCoder) {
        super.init(coder: coder)
        configure()
      }
    
      /// Initializer used programmatically.
      override init(frame: CGRect) {
        super.init(frame: frame)
        configure()
      }
    
    ...
    
    func configure() {
      let contentView = // here use many of the functions available on the internet to 
                        // load a view from a nib. 
      // Then add this view to the view hierarchy. 
        addSubview(contentView)
    }
    

    您不需要显式地从nib调用
    makeViewFromNib(nib:\(CustomView.self)”,所有者:self)
    ,因为如果在这种情况下使用
    IBOutlet
    ,您已经从情节提要加载了
    CustomView
    。下一点你应该澄清——你使用的是故事板还是Xib。你想在不同的视图控制器中重用视图,还是专门针对那个视图?在第一句中添加了澄清。也许可以看看这里:你可以找到问题的答案我注意到了myView。子视图的类型是
    [UIView]
    。这就是为什么我认为您不能执行
    customView.label.text
    @anr是,但所有自定义视图(UIView子类)都是UIView类型。将CustomView添加为子视图甚至不需要强制转换到UIView。这是“向上投射”-投射到超类。在此上下文中,只有向下转换(转换为子类)需要显式。因此,您可以(也应该)以方便的方式使用属性,正如我在回答(
    @IBOutlet private var myView:CustomView!
    )中所建议的那样,再次阅读答案时,我认为有点不对:我希望能够执行
    myView.label.text
    (您使用的是CustomView.label.text)。事实上,我尝试了
    myView.label.text
    ,但它不起作用。请记住,我希望能够在
    myView.label.text
    之外执行
    viewDidLoad
    操作,这意味着我只能访问
    myView
    而不能访问
    customView
    。@anr稍微改变了我的答案。实际上没有必要将CustomView添加到另一个CustomView。如果myView是从storyboard/xib创建的,类设置为“CustomView”,则只需在代码中将myView设置为此类,并直接使用label(
    myView.label.text=“some text”
    ),而不必从nib创建视图all@anr为从xib创建的ViewController编辑了我的答案(对于故事板,它非常类似)