如何解决将代码移至单独的功能时遇到麻烦
在GameViewController的 viewDidLoad()函数中,我做两件事:
1-我创建了一个子UImyew myView,它已添加到主视图中,
2-我在GameViewController的代码中调用了我的函数addConstraints。
创建GameScene时, self.myView.frame.width 和 self.myView.frame.height 包含正确的值,并遵守safeAreaLayout指南。
我想使代码更清晰,因此将addConstraints函数移到了单独的文件中。但是当我以这种方式运行我的应用程序时, self.myView.frame.width 和 self.myView.frame.height 为零。
所以很好奇我是否以某种方式不正确地翻译了函数,或者这是我不能移出主代码的地方?
//located with GameViewControl
private func addConstraints(){
var constraints = [NSLayoutConstraint]()
constraints.append(myView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor))
constraints.append(myView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor))
constraints.append(myView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor))
constraints.append(myView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor))
NSLayoutConstraint.activate(constraints)
}
翻译成函数
//called from GameViewControl
createConstraints(view: myView)
....
//located outside of GameViewControl
func createConstraints(view: UIView) {
var constraints = [NSLayoutConstraint]()
constraints.append(view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor))
constraints.append(view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor))
constraints.append(view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor))
constraints.append(view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor))
NSLayoutConstraint.activate(constraints)
}
这是GameViewControl的完整文件
import UIKit
import SpriteKit
class GameViewController: UIViewController {
private let myView : UIView = {
let myView = UIView()
setViewAttributes(view: myView)
return myView
}()
private func addConstraints(){
var constraints = [NSLayoutConstraint]()
//add
constraints.append(myView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor))
constraints.append(myView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor))
constraints.append(myView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor))
constraints.append(myView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor))
//activate
NSLayoutConstraint.activate(constraints)
}
override func viewDidLoad() {
super.viewDidLoad()
#if DEBUG
print ("viewDidLoad")
#endif
if let view = self.view as! SKView? {
getScreenDimensions (screen: &screenDims)
view.addSubview(myView)
addConstraints()
var scene : GameScene!
dispatchQueue.main.async { scene = GameScene(size: CGSize(width: self.myView.frame.width,height: self.myView.frame.width))
scene.anchorPoint = CGPoint(x: 0.0,y: 0.0)
scene.backgroundColor = .clear
scene.scaleMode = .aspectFit
view.isHidden = false
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
view.showsPhysics = true
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
#if DEBUG
print ("GVC viewDidLayoutSubviews")
#endif
myGlobalVars.sceneRect = view.frame
if #available(iOS 11.0,*) {
myGlobalVars.topSafeArea = view.safeAreaInsets.top
myGlobalVars.bottomSafeArea = view.safeAreaInsets.bottom
} else {
myGlobalVars.topSafeArea = topLayoutGuide.length
myGlobalVars.bottomSafeArea = bottomLayoutGuide.length
}
}
override var shouldAutorotate: Bool {
#if DEBUG
print ("shouldAutorotate")
#endif
return false
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
#if DEBUG
print ("supportedInterfaceOrientations")
#endif
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
override var prefeRSStatusBarHidden: Bool {
#if DEBUG
print ("prefeRSStatusBarHidden")
#endif
return false
}
}
对函数 setViewAttributes 的调用确实将视图传递给了函数,并且我已经验证了该函数可以正常工作。
func setViewAttributes(view: UIView)
{
view.alpha = 0.0
view.frame.size.height = UIScreen.main.nativeBounds.height
view.frame.size.width = UIScreen.main.nativeBounds.width
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .clear
}
解决方法
您不能仅仅移动这种功能,因为其中的view
变量引用了GameViewController.view
。
如果您要进行这样的重构,则可以将此方法移至扩展名并在GameViewController
内调用它。
public extension UIView {
func createConstraints() {
guard let superview = superview else { return }
view.translatesAutoresizingMaskIntoConstraints = false
var constraints = [NSLayoutConstraint]()
constraints.append(leadingAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.leadingAnchor))
constraints.append(trailingAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.trailingAnchor))
constraints.append(bottomAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.bottomAnchor))
constraints.append(topAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.topAnchor))
NSLayoutConstraint.activate(constraints)
}
}
然后应该调用addConstraints()
,而不是在viewDidLoad()
中调用myView.createConstraints()
。它应该和以前一样工作。
您可以从Extensions — The Swift Programming Language阅读有关扩展的更多信息。
,而且您也应该阅读此书Programmatically Creating Constraints
遍历代码后,我一遍又一遍地意识到,我在之前 viewDidLayoutSubviews 调用了safeAreaLayout例程。现在,我可以将调用移至函数了,并且可以正常工作。现在,我很想知道为什么过早调用它时它为什么能工作。但是也许我应该感谢我发现了一个严重的错误。
因此,现在我的代码看起来与OP中的代码相同,除了有关屏幕尺寸和safeAreaLayout的每个调用都是在 viewDidLayoutSubviews 函数中完成的。
并且addConstraints现在是一个外部函数
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
getScreenDimensions (screen: &screenDims)
view.addSubview(myView)
addConstraints()
myGlobalVars.sceneRect = view.frame
createConstraints(view: myView)
if #available(iOS 11.0,*) {
myGlobalVars.topSafeArea = view.safeAreaInsets.top
myGlobalVars.bottomSafeArea = view.safeAreaInsets.bottom
} else {
myGlobalVars.topSafeArea = topLayoutGuide.length
myGlobalVars.bottomSafeArea = bottomLayoutGuide.length
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。