如何在同一个ViewController中初始化两个NSObject实例 – Swift

请多多包涵。 我是新手编程和新的StackOverflow。 我希望我的问题能够给我一个进入编程界的热烈回应。 一个相信我的信任的人告诉我在StackOverflow上发布这封电子邮件给他。

我需要做什么才能让两个NSObject实例在同一个ViewController中工作? 我已经初始化了一个名为SideBar和RightSideBar的NSObject子类。 他们都从NSObject中提取。 菜单中的单元格由编程创build的TableViewController创build。 我跟随了一个以编程方式完成所有事情的教程,因为我不知道Storyboard更适合构build事物。

以下是代码库。

编辑:对不起长时间的啰嗦。 我不知道如何使这个更短,更完整

===========

****请注意,SideBar子类是左侧菜单。 RightSideBar类具有相同的初始化设置,并且是正确的菜单。 如果可能的话,我希望能够使它们在同一个ViewController的同一个实例中出现在相同的ViewController中。

这是左边的TableViewController:

import UIKit //this protocol of the sidebar delegate manages the selection of the item in the row. protocol SidebarTableViewControllerDelegate { func sidebarControlDidSelectRow(indexPath: NSIndexPath) } class SidebarTableViewController: UITableViewController { //setting up the delegate and array of menu items. var delegate:SidebarTableViewControllerDelegate? var tableData:Array <String> = [] var imageData:[UIImage] = [] // MARK: - Table view data source //Setting up the number of sections in the menu override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } //Setting up the number of items in the menu override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return tableData.count } //Setting up the menu look for the main screen after login. override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("Cell") as? UITableViewCell if cell == nil { cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell") //configure the cell... cell!.backgroundColor = UIColor.clearColor() cell!.textLabel?.textColor = UIColor.darkTextColor() let selectedView:UIView = UIView(frame: CGRect(x: 0, y: 0, width: cell!.frame.size.width, height: cell!.frame.size.height)) selectedView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.3) cell!.selectedBackgroundView = selectedView } cell!.textLabel!.text = tableData[indexPath.row] cell!.imageView!.image = imageData[indexPath.row] return cell! } //Setting up the height for each cell of the table override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return 45.0 } //Setting up the selection of the item in the cell. override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { delegate?.sidebarControlDidSelectRow(indexPath) } override func viewDidLoad() { } override func didReceiveMemoryWarning() { } } 

这是正确的表视图控制器:

 //setting up the RightSidebarControllerDelegate protocol RightSidebarTableViewControllerDelegate { func rightSidebarControlDidSelectRow(indexPath: NSIndexPath) } class RightSidebarTableViewController: UITableViewController { //setting up the delegate and array of menu items. var delegate:RightSidebarTableViewControllerDelegate? var rightTableData:Array <String> = [] var rightImageData:[UIImage] = [] // MARK: - Table view data source //Setting up the number of sections in the menu override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } //Setting up the number of items in the menu override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return rightTableData.count } //Setting up the menu look for the main screen after login. override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("Cell") as? UITableViewCell if cell == nil { cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell") //configure the cell... cell!.backgroundColor = UIColor.clearColor() cell!.textLabel?.textColor = UIColor.darkTextColor() let selectedView:UIView = UIView(frame: CGRect(x: 0, y: 0, width: cell!.frame.size.width, height: cell!.frame.size.height)) selectedView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.3) cell!.selectedBackgroundView = selectedView } cell!.textLabel!.text = rightTableData[indexPath.row] cell!.imageView!.image = rightImageData[indexPath.row] return cell! } //Setting up the height for each cell of the table override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return 45.0 } //Setting up the selection of the item in the cell. override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { delegate?.rightSidebarControlDidSelectRow(indexPath) } override func viewDidLoad() { } override func didReceiveMemoryWarning() { } } 

这里是我的问题可能从SideBar:NSObject开始。 这是左边的SideBar被初始化:

 import UIKit @objc protocol SideBarDelegate { func sideBarDidSelectButtonAtIndex (index: Int) optional func sideBarWillClose() optional func sideBarWillOpen() optional func sideBarWillDeinitialize() } //this class sets up the actual sidebar. class SideBar: NSObject, SidebarTableViewControllerDelegate { //width of the bar, tableview setup, and views for the sidebar let barWidth:CGFloat = 175.0 let sideBarTableViewTopInset:CGFloat = 25.0 let sideBarContainerView:UIView = UIView() let sideBarTableViewController:SidebarTableViewController = SidebarTableViewController() var originView:UIView! //var for dynamic effect and controlling the sidebar var animator:UIDynamicAnimator! var delegate:SideBarDelegate? var isSideBarOpen:Bool = false //initializer for the "SideBar" class. override init() { super.init() } //initializer for the tableView of menu items. init(sourceView: UIView, menuItems: Array<String>, menuImages: [UIImage]){ super.init() //initializing the views and animation for the menu. originView = sourceView sideBarTableViewController.tableData = menuItems sideBarTableViewController.imageData = menuImages setupSideBar() animator = UIDynamicAnimator(referenceView: originView) } //function for setting up the sidebar. func setupSideBar () { //setting up the frame/outline of the side bar. sideBarContainerView.frame = CGRectMake(-barWidth, originView.frame.origin.y + 45, barWidth, originView.frame.size.height) //setting up the color of the sidebar. sideBarContainerView.backgroundColor = UIColor.clearColor() //disables subviews from being confined to the sidebar. sideBarContainerView.clipsToBounds = false //placing the sidebar in the UIView originView.addSubview(sideBarContainerView) //adding blur to the menu. let blurView:UIVisualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.Light)) blurView.frame = sideBarContainerView.bounds sideBarContainerView.addSubview(blurView) //setting up controls for the sidebar sideBarTableViewController.delegate = self sideBarTableViewController.tableView.frame = sideBarContainerView.bounds sideBarTableViewController.tableView.clipsToBounds = false //disabling the scroll feature. Delete to keep the scroll feature. sideBarTableViewController.tableView.scrollsToTop = false //This will remove separators in the UITableCell. Delete to keep separators. sideBarTableViewController.tableView.separatorStyle = UITableViewCellSeparatorStyle.None //This sets the background color of the sidebar and creates the inset. sideBarTableViewController.tableView.backgroundColor = UIColor.clearColor() sideBarTableViewController.tableView.contentInset = UIEdgeInsets(top: sideBarTableViewTopInset, left: 0, bottom: 0, right: 0) //reloads the sidebar and adds the container view to the sideBarTableViewController. sideBarTableViewController.tableView.reloadData() sideBarContainerView.addSubview(sideBarTableViewController.tableView) } func showSideBar(shouldOpen: Bool){ animator.removeAllBehaviors() isSideBarOpen = shouldOpen //simple if and else statements to define the direction of animation and intensity of animation let gravityX:CGFloat = (shouldOpen) ? 0.5 : -0.5 let magnitude:CGFloat = (shouldOpen) ? 20 : -20 let boundaryX:CGFloat = (shouldOpen) ? barWidth : -barWidth //controls the behavior of the animation. let gravityBehavior: UIGravityBehavior = UIGravityBehavior(items: [sideBarContainerView]) gravityBehavior.gravityDirection = CGVectorMake(gravityX, 0) animator.addBehavior(gravityBehavior) let collisionBehavior: UICollisionBehavior = UICollisionBehavior(items: [sideBarContainerView]) collisionBehavior.addBoundaryWithIdentifier("sideBarBoundary", fromPoint: CGPointMake(boundaryX, 20), toPoint: CGPointMake(boundaryX, originView.frame.size.height)) animator.addBehavior(collisionBehavior) let pushBehavior:UIPushBehavior = UIPushBehavior(items: [sideBarContainerView], mode: UIPushBehaviorMode.Instantaneous) pushBehavior.magnitude = magnitude animator.addBehavior(pushBehavior) let sideBarBehavior:UIDynamicItemBehavior = UIDynamicItemBehavior(items: [sideBarContainerView]) sideBarBehavior.elasticity = 0.3 animator.addBehavior(sideBarBehavior) } func sidebarControlDidSelectRow(indexPath: NSIndexPath) { delegate?.sideBarDidSelectButtonAtIndex(indexPath.row) } } 

这是正确的SideBar:最终将初始化右侧菜单的NSObject。

 import UIKit @objc protocol RightSideBarDelegate { func rightSideBarDidSelectButtonAtIndex (index: Int) optional func sideBarWillClose() optional func sideBarWillOpen() } class RightSideBar: NSObject, RightSidebarTableViewControllerDelegate { //width of the bar, tableview setup, and views for the sidebar let barWidth:CGFloat = 175.0 let rightSideBarTableViewTopInset:CGFloat = 25.0 let rightSideBarContainerView:UIView = UIView() let rightSideBarTableViewController:RightSidebarTableViewController = RightSidebarTableViewController() var rightOriginView:UIView! //var for dynamic effect and controlling the sidebar var animator:UIDynamicAnimator! var delegate:RightSideBarDelegate? var isSideBarOpen:Bool = false //initializer for the "SideBar" class. override init() { super.init() } //initializer for the tableView of menu items. init(rightSourceView: UIView, rightMenuItems: Array<String>, rightMenuImages: [UIImage]){ super.init() //initializing the views and animation for the menu. rightOriginView = rightSourceView rightSideBarTableViewController.rightTableData = rightMenuItems rightSideBarTableViewController.rightImageData = rightMenuImages setupSideBar() animator = UIDynamicAnimator(referenceView: rightOriginView) } //function for setting up the sidebar. func setupSideBar () { //setting up the frame/outline of the side bar. rightSideBarContainerView.frame = CGRectMake(rightOriginView.frame.size.width + barWidth , rightOriginView.frame.origin.y + 45, barWidth, rightOriginView.frame.size.height) //setting up the color of the sidebar. rightSideBarContainerView.backgroundColor = UIColor.clearColor() //disables subviews from being confined to the sidebar. rightSideBarContainerView.clipsToBounds = false //placing the sidebar in the UIView rightOriginView.addSubview(rightSideBarContainerView) //adding blur to the menu. let blurView:UIVisualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.Light)) blurView.frame = rightSideBarContainerView.bounds rightSideBarContainerView.addSubview(blurView) //setting up controls for the sidebar rightSideBarTableViewController.delegate = self rightSideBarTableViewController.tableView.frame = rightSideBarContainerView.bounds rightSideBarTableViewController.tableView.clipsToBounds = false //disabling the scroll feature. Delete to keep the scroll feature. rightSideBarTableViewController.tableView.scrollsToTop = false //This will remove separators in the UITableCell. Delete to keep separators. rightSideBarTableViewController.tableView.separatorStyle = UITableViewCellSeparatorStyle.None //This sets the background color of the sidebar and creates the inset. rightSideBarTableViewController.tableView.backgroundColor = UIColor.clearColor() rightSideBarTableViewController.tableView.contentInset = UIEdgeInsets(top: rightSideBarTableViewTopInset, left: 0, bottom: 0, right: 0) //reloads the sidebar and adds the container view to the rightSideBarTableViewController. rightSideBarTableViewController.tableView.reloadData() rightSideBarContainerView.addSubview(rightSideBarTableViewController.tableView) } func showSideBar(shouldOpen: Bool){ animator.removeAllBehaviors() isSideBarOpen = shouldOpen //simple if and else statements to define the direction of animation and intensity of animation let gravityX:CGFloat = (shouldOpen) ? -0.5 : 0.5 let magnitude:CGFloat = (shouldOpen) ? -20 : 20 let boundaryX:CGFloat = (shouldOpen) ? -barWidth : barWidth //controls the behavior of the animation. let gravityBehavior: UIGravityBehavior = UIGravityBehavior(items: [rightSideBarContainerView]) gravityBehavior.gravityDirection = CGVectorMake(gravityX, 0) animator.addBehavior(gravityBehavior) let collisionBehavior: UICollisionBehavior = UICollisionBehavior(items: [rightSideBarContainerView]) collisionBehavior.addBoundaryWithIdentifier("sideBarBoundary", fromPoint: CGPointMake(boundaryX, 20), toPoint: CGPointMake(boundaryX, rightOriginView.frame.size.height)) animator.addBehavior(collisionBehavior) let pushBehavior:UIPushBehavior = UIPushBehavior(items: [rightSideBarContainerView], mode: UIPushBehaviorMode.Instantaneous) pushBehavior.magnitude = magnitude animator.addBehavior(pushBehavior) let sideBarBehavior:UIDynamicItemBehavior = UIDynamicItemBehavior(items: [rightSideBarContainerView]) sideBarBehavior.elasticity = 0.3 animator.addBehavior(sideBarBehavior) } func rightSidebarControlDidSelectRow(indexPath: NSIndexPath) { delegate?.rightSideBarDidSelectButtonAtIndex(indexPath.row) } } 

最后这是我当前的DoubleMenuViewController的代码。 当我继续DoubleMenuViewController来中断菜单时,会发生什么情况。 菜单将不会加载。 但是,如果我在一个只调用SideBar:NSObject的SingleMenuViewController中,那么只要调用一个菜单,代码就可以工作。 在这个DoubleMenuViewController中,我有初始化部分注释了RightSideBar类,因为我正在处理一个解决scheme。 我知道这个ViewController的代码是乱码。 我正在尝试我能想到的一切。 看看我的代码后,看看我已经试过了:

 import UIKit class DoubleMenuViewController: UIViewController, SideBarDelegate, RightSideBarDelegate { var sideBar:SideBar? var ondemandSideBar:SideBar { get { if sideBar == nil { //setting up the menu items for the sidebar. sideBar = SideBar(sourceView: self.view, menuItems: ["Home", "Share", "About", "Help"], menuImages: [homeImage!, shareImage!, aboutImage!, helpImage!]) sideBar!.delegate = self SideBar.new() } return sideBar! } } //initializes the "RightSideBar" var rightSideBar:RightSideBar? var ondemandRightSideBar:RightSideBar { get { if rightSideBar == nil { rightSideBar = RightSideBar(rightSourceView: self.view, rightMenuItems: [//Other items], rightMenuImages: [//Other Items]) rightSideBar!.delegate = self RightSideBar.new() } return rightSideBar! } } var homeImage = UIImage(named: "Home") var shareImage = UIImage(named: "Share") var aboutImage = UIImage(named: "About") var helpImage = UIImage(named: "Help") @IBOutlet weak var currentMenuControl: UIBarButtonItem! @IBAction func currentMenuDisplay(sender: AnyObject) { if currentMenuControl.tag == 1 { ondemandSideBar.showSideBar(true) currentMenuControl.tag = 0 } else { ondemandSideBar.showSideBar(false) currentMenuControl.tag = 1 } } @IBOutlet weak var progressionMenuControl: UIBarButtonItem! @IBAction func progressionMenuDisplay(sender: AnyObject) { if progressionMenuControl.tag == 1 { ondemandRightSideBar.showSideBar(true) progressionMenuControl.tag = 0 } else { ondemandRightSideBar.showSideBar(false) progressionMenuControl.tag = 1 } } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func sideBarDidSelectButtonAtIndex(index: Int) { switch index { //segues } } func rightSideBarDidSelectButtonAtIndex(index: Int) { switch index { //segues } } } 

以下是我所尝试的:

  1. 我尝试改变CGFloats的位置,因为SubViews似乎来自左侧。

  2. 我已经重命名所有的RightSideBarvariables和类名称,以克服实例variables和类名称中的运行时混淆。 这包括重命名您在NSObject子类和目标视图控制器中看到的初始值设定项。

  3. 我已经尝试在button标记的viewDidLoad方法中使用控制stream。 我拿走了滑动function来显示菜单和添加button,因为我认为系统正在努力处理Swipe。

  4. 我已经尝试在NSObject的SideBar子类文件中去初始化。 所有得到我的是一个无限循环,login后崩溃的应用程序。

  5. 然后我尝试了在targetViewController ….. DoubleMenuViewController和SingleMenuViewController的初始化。 我使用SingleMenuViewController中的button返回了一个工作菜单,但它仍然不会在DoubleMenuViewController中显示左右菜单。

  6. 最后,我试着在DoubleMenuViewController中去除初始化SideBar(Left SideBar)和RightSideBar。 但是,当我将println()函数添加到我的所有部分时,debugging器不会运行打印函数来获取对象的值,甚至不显示“This”之类的键入状态。 我添加了打印function,因为我不确定是否知道什么时候进行了初始化和重新初始化。

看来我的菜单是从SideBar:NSObject文件和RightSideBar:NSObject文件初始化的。 我的意思是我的菜单正在创build之前,我击中目标视图控制器。 这对我来说不是一个问题,只要我能让编译器在同一个View Controller中初始化SideBar和RightSideBar,但是不会这样做。

我只需要能够通过滑动或button水龙头来控制两个菜单。

我认为我的初始化程序有一个问题,相互覆盖。

但是,我不知道如何解决这个问题。 我已经阅读了Swift手册并阅读了互联网上的文章。 我也search过StackOverflow。

你问:

我如何初始化在同一个视图控制器的NSObject两个实例?

抛开为什么你要处理NSObject (在Objective-C中,所有类都必须从NSObject ,在Swift中不再是这种情况),如果你想实例化两个对象,你只需要一个属性每。

如果这些被懒惰地实例化,就像你的代码片断所暗示的那样,那么你必须确定那个被懒惰地实例化的属性被引用的地方(例如,你可能从“从边缘滑过”手势触发它)或者你有什么。 在引用那个懒洋洋的实例化属性的代码中设置一个断点,并确保你到达那里。

我在你的一个代码片段上有一些观察。 你说你正在实例化你的侧栏:

 var sideBar : SideBar? var ondemandSideBar : SideBar { get { if sideBar == nil { sideBar = SideBar(sourceView, menuItems, menuImage etc.) sideBar!.delegate SideBar.new() } } } 

我不认为这就是你真的在做什么,因为你没有设置委托,你既是实例化SideBar也是调用new (你不应该从Swift做),你没有返回价值等

此外,具有由某些计算属性实例化的存储属性的模式具有某种Objective-C 首选的function。 我推断你想要一个懒惰的实例化属性。 如果是这样的话,我会倾向于使用一个lazy存储属性。 然后,我会使用闭包懒惰地设置这个属性:

我期望像这样的模式

 protocol SideBarDelegate : class { // specify class so we can use `weak` reference func didChooseMenuItem(sender: SideBar, item: Int) } class SideBar { weak var delegate: SideBarDelegate? // make sure this is weak to avoid strong reference cycle } class ViewController: UIViewController, SideBarDelegate { lazy var sideBar: SideBar = { let _sideBar = SideBar(sourceView, menuItems, menuImage, etc.) _sideBar.delegate = self return _sideBar }() func didChooseMenuItem(sender: SideBar, item: Int) { // handle it here } // etc. } 

这样, sideBar将不会被实例化,直到你在你的代码中的某个地方引用sideBar ,但是当你这样做的时候,它将会用那个闭包内的代码实例化。