为什么 ui 元素以 swift 编程方式在视图控制器之间共享?
Why the ui elements are shared between view controllers in swift programmatic way?
我试图在 swift 中以编程方式导航视图控制器。所以,我这次测试的目的是
- 创建两个视图控制器。
- 按下按钮时在视图控制器之间导航
所以这是我的 AppDelegate.swift
。我创建了导航控制器并嵌入了 ViewController
.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let navigationController = UINavigationController();
let mainViewController = ViewController();
let loginViewController = LoginViewController();
navigationController.viewControllers = [ mainViewController, loginViewController ];
self.window?.rootViewController = navigationController;
self.window?.makeKeyAndVisible()
return true
}
然后在视图控制器中
let button: UIButton = {
let button = UIButton(frame: CGRect(x: 120, y: 120, width: 50, height: 50));
button.setTitle("Login", for: .normal);
button.layer.borderColor = UIColor.lightGray.cgColor;
button.translatesAutoresizingMaskIntoConstraints = false;
button.backgroundColor = UIColor.red;
button.layer.cornerRadius = 5;
return button;
}();
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white;
view.addSubview(button);
button.addTarget(self, action: #selector(loginPressed(_sender:)), for: .touchUpInside);
// Do any additional setup after loading the view.
}
@IBAction func loginPressed(_sender: UIButton) {
print("clicked");
let loginViewController = LoginViewController();
self.navigationController?.pushViewController(loginViewController, animated: true);
}
并且在LoginViewController
let emailLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 150, y: 150, width: 150, height: 150));
label.text = "Email address";
return label;
}();
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(emailLabel);
print("this is loginViewController");
}
这是我的结果。在 ViewController
并在登录中ViewController。
所以这是我的问题:为什么按钮会出现在登录ViewController中?为什么 uielement 在视图控制器之间共享?
注意:我尝试在 google 中搜索。也许因为我是一名网络开发人员,我可能没有用正确的词进行搜索。
首先尝试使用 backgroundColor 进行调试并检查视图是否透明。
其次,从 navigationController.viewControllers = [ mainViewController, loginViewController ];
中删除 loginViewController
,因为这样做是将 UIViewController 推入堆栈。
无论如何,当您使用 let loginViewController = LoginViewController();
推送时,您正在创建一个新的 LoginViewController 实例
当您在推送后打印 navigationController.viewControllers
时,您会得到类似 [mainViewController, loginViewController, loginViewController]
的内容,我认为这不是您想要的。
第三,@IBAction 用于Storyboard。为什么你不在 generell 中使用故事板?只需点击几下,无需一行代码,即可实现您想要实现的目标。
运行使用您发布的确切代码,初始视图将是您的LoginViewController
(不是您的"Main"视图控制器) 并且屏幕将变黑。
所以,要修复那里的东西...
在 AppDelegate
中不要尝试创建 LoginViewController
- 仅创建和设置您的 "main" VC:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let navigationController = UINavigationController();
let mainViewController = ViewController();
// don't try to create login view here...
//let loginViewController = LoginViewController();
//navigationController.viewControllers = [ mainViewController, loginViewController ];
// set only your first controller
navigationController.viewControllers = [ mainViewController ];
self.window?.rootViewController = navigationController;
self.window?.makeKeyAndVisible()
return true
}
现在,当您 运行 应用程序将显示带有 Login
按钮的 "main" VC 时的初始视图...但是,点击该按钮将推送黑屏,因为你没有给 LoginViewController
背景颜色:
class LoginViewController: UIViewController {
let emailLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 150, y: 150, width: 150, height: 150));
label.text = "Email address";
return label;
}();
override func viewDidLoad() {
super.viewDidLoad()
// set background to green, to make it really obvious
view.backgroundColor = .green
view.addSubview(emailLabel);
print("this is loginViewController");
}
}
如果您仍然看到 Login
按钮和电子邮件标签,和/或背景不是绿色,我怀疑您开始是在 Storyboard 中布置视图控制器但没有清除 Main Interface
在项目设置(常规选项卡)中:
如果 Main Interface
框不为空,请删除其中的内容并再次 运行 您的应用(进行上述更改)。
编辑
这是一个完整的示例,使用您的代码和我描述的编辑。
- 创建一个新项目
- 删除
Main.storyboard
- 将下面的
AppDelegate
代码复制并粘贴到 AppDelegate.swift
- 将下面的
ViewController
代码复制并粘贴到 ViewController.swift
- 从项目设置/常规
Main Interface
中删除单词Main
- 运行 应用
看看你是否得到了你想要的。
AppDelegate
//
// AppDelegate.swift
// NewProject
//
// Created by Don Mag on 8/6/19.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let navigationController = UINavigationController();
let mainViewController = ViewController();
// don't try to create login view here...
//let loginViewController = LoginViewController();
//navigationController.viewControllers = [ mainViewController, loginViewController ];
// set only your first controller
navigationController.viewControllers = [ mainViewController ];
self.window?.rootViewController = navigationController;
self.window?.makeKeyAndVisible()
return true
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationDidBecomeActive(_ application: UIApplication) {
}
func applicationWillTerminate(_ application: UIApplication) {
}
}
ViewController
//
// ViewController.swift
// NewProject
//
// Created by Don Mag on 8/7/19.
//
import UIKit
class ViewController: UIViewController {
let button: UIButton = {
let button = UIButton(frame: CGRect(x: 120, y: 120, width: 50, height: 50));
button.setTitle("Login", for: .normal);
button.layer.borderColor = UIColor.lightGray.cgColor;
button.translatesAutoresizingMaskIntoConstraints = false;
button.backgroundColor = UIColor.red;
button.layer.cornerRadius = 5;
return button;
}();
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white;
view.addSubview(button);
button.addTarget(self, action: #selector(loginPressed(_sender:)), for: .touchUpInside);
// Do any additional setup after loading the view.
}
@IBAction func loginPressed(_sender: UIButton) {
print("clicked");
let loginViewController = LoginViewController();
self.navigationController?.pushViewController(loginViewController, animated: true);
}
}
class LoginViewController: UIViewController {
let emailLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 150, y: 150, width: 150, height: 150));
label.text = "Email address";
return label;
}();
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
view.addSubview(emailLabel);
print("this is loginViewController");
}
}
在花了更多时间并从@DonMag 的回答中寻找我做错了什么之后,我试图推送的视图控制器继承了 ViewController
class 而不是实际的 UIViewController
.
我试图在 swift 中以编程方式导航视图控制器。所以,我这次测试的目的是
- 创建两个视图控制器。
- 按下按钮时在视图控制器之间导航
所以这是我的 AppDelegate.swift
。我创建了导航控制器并嵌入了 ViewController
.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let navigationController = UINavigationController();
let mainViewController = ViewController();
let loginViewController = LoginViewController();
navigationController.viewControllers = [ mainViewController, loginViewController ];
self.window?.rootViewController = navigationController;
self.window?.makeKeyAndVisible()
return true
}
然后在视图控制器中
let button: UIButton = {
let button = UIButton(frame: CGRect(x: 120, y: 120, width: 50, height: 50));
button.setTitle("Login", for: .normal);
button.layer.borderColor = UIColor.lightGray.cgColor;
button.translatesAutoresizingMaskIntoConstraints = false;
button.backgroundColor = UIColor.red;
button.layer.cornerRadius = 5;
return button;
}();
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white;
view.addSubview(button);
button.addTarget(self, action: #selector(loginPressed(_sender:)), for: .touchUpInside);
// Do any additional setup after loading the view.
}
@IBAction func loginPressed(_sender: UIButton) {
print("clicked");
let loginViewController = LoginViewController();
self.navigationController?.pushViewController(loginViewController, animated: true);
}
并且在LoginViewController
let emailLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 150, y: 150, width: 150, height: 150));
label.text = "Email address";
return label;
}();
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(emailLabel);
print("this is loginViewController");
}
这是我的结果。在 ViewController
并在登录中ViewController。
所以这是我的问题:为什么按钮会出现在登录ViewController中?为什么 uielement 在视图控制器之间共享?
注意:我尝试在 google 中搜索。也许因为我是一名网络开发人员,我可能没有用正确的词进行搜索。
首先尝试使用 backgroundColor 进行调试并检查视图是否透明。
其次,从 navigationController.viewControllers = [ mainViewController, loginViewController ];
中删除 loginViewController
,因为这样做是将 UIViewController 推入堆栈。
无论如何,当您使用 let loginViewController = LoginViewController();
当您在推送后打印 navigationController.viewControllers
时,您会得到类似 [mainViewController, loginViewController, loginViewController]
的内容,我认为这不是您想要的。
第三,@IBAction 用于Storyboard。为什么你不在 generell 中使用故事板?只需点击几下,无需一行代码,即可实现您想要实现的目标。
运行使用您发布的确切代码,初始视图将是您的LoginViewController
(不是您的"Main"视图控制器) 并且屏幕将变黑。
所以,要修复那里的东西...
在 AppDelegate
中不要尝试创建 LoginViewController
- 仅创建和设置您的 "main" VC:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let navigationController = UINavigationController();
let mainViewController = ViewController();
// don't try to create login view here...
//let loginViewController = LoginViewController();
//navigationController.viewControllers = [ mainViewController, loginViewController ];
// set only your first controller
navigationController.viewControllers = [ mainViewController ];
self.window?.rootViewController = navigationController;
self.window?.makeKeyAndVisible()
return true
}
现在,当您 运行 应用程序将显示带有 Login
按钮的 "main" VC 时的初始视图...但是,点击该按钮将推送黑屏,因为你没有给 LoginViewController
背景颜色:
class LoginViewController: UIViewController {
let emailLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 150, y: 150, width: 150, height: 150));
label.text = "Email address";
return label;
}();
override func viewDidLoad() {
super.viewDidLoad()
// set background to green, to make it really obvious
view.backgroundColor = .green
view.addSubview(emailLabel);
print("this is loginViewController");
}
}
如果您仍然看到 Login
按钮和电子邮件标签,和/或背景不是绿色,我怀疑您开始是在 Storyboard 中布置视图控制器但没有清除 Main Interface
在项目设置(常规选项卡)中:
如果 Main Interface
框不为空,请删除其中的内容并再次 运行 您的应用(进行上述更改)。
编辑
这是一个完整的示例,使用您的代码和我描述的编辑。
- 创建一个新项目
- 删除
Main.storyboard
- 将下面的
AppDelegate
代码复制并粘贴到AppDelegate.swift
- 将下面的
ViewController
代码复制并粘贴到ViewController.swift
- 从项目设置/常规
Main Interface
中删除单词Main
- 运行 应用
看看你是否得到了你想要的。
AppDelegate
//
// AppDelegate.swift
// NewProject
//
// Created by Don Mag on 8/6/19.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let navigationController = UINavigationController();
let mainViewController = ViewController();
// don't try to create login view here...
//let loginViewController = LoginViewController();
//navigationController.viewControllers = [ mainViewController, loginViewController ];
// set only your first controller
navigationController.viewControllers = [ mainViewController ];
self.window?.rootViewController = navigationController;
self.window?.makeKeyAndVisible()
return true
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationDidBecomeActive(_ application: UIApplication) {
}
func applicationWillTerminate(_ application: UIApplication) {
}
}
ViewController
//
// ViewController.swift
// NewProject
//
// Created by Don Mag on 8/7/19.
//
import UIKit
class ViewController: UIViewController {
let button: UIButton = {
let button = UIButton(frame: CGRect(x: 120, y: 120, width: 50, height: 50));
button.setTitle("Login", for: .normal);
button.layer.borderColor = UIColor.lightGray.cgColor;
button.translatesAutoresizingMaskIntoConstraints = false;
button.backgroundColor = UIColor.red;
button.layer.cornerRadius = 5;
return button;
}();
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white;
view.addSubview(button);
button.addTarget(self, action: #selector(loginPressed(_sender:)), for: .touchUpInside);
// Do any additional setup after loading the view.
}
@IBAction func loginPressed(_sender: UIButton) {
print("clicked");
let loginViewController = LoginViewController();
self.navigationController?.pushViewController(loginViewController, animated: true);
}
}
class LoginViewController: UIViewController {
let emailLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 150, y: 150, width: 150, height: 150));
label.text = "Email address";
return label;
}();
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
view.addSubview(emailLabel);
print("this is loginViewController");
}
}
在花了更多时间并从@DonMag 的回答中寻找我做错了什么之后,我试图推送的视图控制器继承了 ViewController
class 而不是实际的 UIViewController
.