iOS 使用 xib + 全局方法覆盖 UIView (Swift)

iOS using xib + global methods for overlay UIView (Swift)

我正在编写一个应在特定情况下显示叠加层的应用程序,例如该应用程序未启用定位服务。

Overlay 是一个 UIView,带有一个 UIImageView(背景)、一个 UILabel(标题)和一个调用特定操作的 UIButton。我想使用 Interface Builder 来设置叠加层 UI 但我想调用叠加层并将其显示在不同的 UIViewControllers 上,具体取决于何时缺少位置服务检测到。

我已经为 link 一个 xib 文件设置了自定义 class(UIView 的子class)。代码如下:

class LaunchCustomScreen: UIView
{

   @IBOutlet var title: UILabel!
   @IBOutlet var enableLocationButton: UIButton!
   @IBOutlet var waitingIndicator: UIActivityIndicatorView!
   @IBOutlet var bckgroundImage: UIImageView!

   func setupDefault()
   {
       title.text = "Location Services Required"
       enableLocationButton.setTitle("Enable Location Services", forState: UIControlState.Normal)
       enableLocationButton.addTarget(self,
        action: "promptUserForLocation",
        forControlEvents: UIControlEvents.TouchUpInside)

       hideLocButton()
   }

   func hideLocButton()
   {
       enableLocationButton.hidden = true
   }

   func showLocButton()
   {
       enableLocationButton.hidden = false
   }
}

然后我创建了 Class LaunchCustomScreen 的 xib 文件,我 link 将 IBOutlets 编辑到其中的所有 objects (UI 标签,UIBUtton, UIImageView)

然后我设置了一些全局函数,以便从任何其他 UIViewController 调用,以便 show/hide 在特定视图控制器上覆盖并使用 [=34 配置它=] 按钮隐藏或可见(当用户位置仍在加载时,它将被隐藏并带有等待指示器)。相关代码如下:

func setupLaunchDefault(vc: UIViewController) -> LaunchCustomScreen
{
    for aSubview in vc.view.subviews
    {
        if aSubview.isKindOfClass(LaunchCustomScreen)
        {
            NSLog("Found already a launch screen. Removing")
            aSubview.removeFromSuperview()
        }
    }

    var screen: LaunchCustomScreen = LaunchCustomScreen()
    screen.setupDefault()
    return screen
}

func showLaunchAskLocation(vc:UIViewController)
{
    var screen = setupLaunchDefault(vc)
    screen.bounds = vc.view.bounds
    screen.showLocButton()
    vc.view.addSubview(screen)
} 

现在我正在尝试该解决方案是否有效并且它在 setupLaunchDefault 函数上崩溃。原因是即使创建了 LaunchCustomSCreen 的实例,变量 (title, enableLocationButton) 仍然是 nil。我虽然他们应该 non-nil 感谢 xib 的 IBOutlet...我错过了什么?

提前感谢您的帮助!

I have set up a custom class (subclass of UIView) to link a xib file

不,你没有。没有这样的 "link" 是可能的。

what am I missing?

你没有遗漏任何东西,因为你已经想通了!

只是凭空创建一个 LaunchCustomScreen 实例(即像您一样说 LaunchCustomScreen())只是创建此 class 的一个实例。它与 .xib (nib) 文件没有任何关系! class 和笔尖之间没有任何魔法 "link"!因此,没有任何事情会导致这些属性获得任何值。正如您正确解释的那样,它们是 nil.

您已经在 nib 中设计并配置了 LaunchCustomScreen 的一个特殊实例那个是插座连接的实例,在同一个笔尖。因此,如果您想要一个带有连接插座的 LaunchCustomScreen 实例,您必须 加载 nib!加载 nib 完全等同于创建 nib 中的实例 - 它 一种实例化形式。而这里,就是你想要的实例化形式,因为这个实例就是你想要的实例。

所以,答案是:做 而不是 LaunchCustomScreen() 来获取您的 LaunchCustomScreen 实例 (screen)。相反,加载 nib 以获取您的 LaunchCustomScreen 实例 - 一切都会好起来的。

那么,假设您的 .xib 文件名为 LaunchCustomScreen.xib。你会说:

let arr = NSBundle.mainBundle().loadNibNamed("LaunchCustomScreen", owner: nil, options: nil)
let screen = arr[0] as UIView

第一个结果 arr 是从 nib 实例化的顶级对象数组。这些对象中的第一个(可能是数组的唯一成员)就是您所追求的视图!因此,您将其转换为 UIView 并准备好将其粘贴到您的界面中。由于视图来自笔尖,因此设置了它的出口,这就是您所追求的。您可以根据需要多次执行此操作,以获得任意多的此视图 "copies"。