簡體   English   中英

如何在同一ViewController中初始化兩個NSObject實例-Swift

[英]How Do I Initialize Two Instances of NSObject in the same ViewController - Swift

請多多包涵。 我是編程新手,還是StackOverflow的新手。 我希望我的問題能使我對進入編程社區產生熱情的響應。 我信任他的一個熟人,讓我將此郵件發送到StackOverflow上給他。

如何使兩個NSObject實例在同一ViewController中工作? 我已經初始化了一個名為SideBar和RightSideBar的NSObject子類。 它們都從NSObject繪制。 菜單中的單元格由我以編程方式創建的TableViewController創建。 我遵循了一個以編程方式完成所有操作的教程,因為我不知道Storyboard可以更好地構建東西。

下面是代碼庫。

編輯:很抱歉長期困擾。 我不知道如何使它簡短而完整

===========

****請注意,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的地方。 這是要初始化的左側邊欄:

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類注釋掉初始化部分,因為我正在研究解決方案。 我知道此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. 由於SubViews似乎來自左側,因此我嘗試過更改CGFloat的位置。

  2. 我已將所有RightSideBar變量和類名都重命名,以克服實例變量和類名在運行時的混亂。 這包括重命名您在NSObject SubClass和目標視圖控制器中看到的初始化程序。

  3. 我嘗試在帶有按鈕標簽的viewDidLoad方法中使用控制流。 我取消了滑動功能以顯示菜單並添加了按鈕,因為我認為系統正在努力應對滑動。

  4. 我嘗試在NSObject的SideBar子類文件中取消初始化。 使我感到困惑的是無限循環,登錄后崩潰了該應用程序。

  5. 然后我嘗試在targetViewController中按需進行初始化..... DoubleMenuViewController和SingleMenuViewController。 我返回了帶有SingleMenuViewController中的按鈕的工作菜單,但是在DoubleMenuViewController中它仍然不會顯示左右菜單。

  6. 最后,我嘗試在DoubleMenuViewController中取消初始化SideBar(左側SideBar)和RightSideBar。 但是,當我將println()函數添加到我的所有部分時,調試器不會為我運行print函數來獲取對象的值,甚至不會顯示諸如“ This”之類的類型化狀態。 我添加了打印功能,因為我不確定是否知道何時進行初始化和重新初始化。

看來我的菜單是從SideBar:NSObject文件和RightSideBar:NSObject文件初始化的。 我的意思是,在我擊中目標視圖控制器之前就已經創建了菜單。 只要我可以讓編譯器在同一個View Controller中初始化SideBar和RightSideBar,這對我來說就不是問題,但是它不會那樣做。

我只需要能夠通過滑動或點擊按鈕來控制兩個菜單。

我認為我的初始化程序相互覆蓋時遇到問題。

但是,我不知道如何解決該問題。 我已經閱讀了Swift手冊並在互聯網上閱讀了文章。 我還搜索了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 je sais quoi。 我推斷您想要一個延遲實例化的屬性。 如果是這種情況,我傾向於使用一個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.
}

這樣,直到您在代碼中的某處引用sideBarsideBar才會被實例化,但是當您這樣做時, sideBar將會在該閉包中的代碼實例化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM