【问题标题】:Unrecognized Selector for SideBar InstanceSideBar 实例无法识别的选择器
【发布时间】:2015-08-12 23:31:36
【问题描述】:

我问这个问题是因为我在这个问题中收到的答案是:How Do I Initialize Two Instances of NSObject in the same ViewController - Swift

把我带到了这个方向。无论我是 NSObject 还是 UIViewController 的子类,当我将代码更改为以下内容时,我仍然会收到无法识别的选择器。

我仍在尝试能够创建左右侧边栏。但是,我现在什至无法加载一个 SideBar。我收到一个错误 [UIViewController Center]: unrecognized selector sent to instance xxxxx。

这个问题与我见过的其他无法识别的选择器实例问题不同,因为我没有处理按钮并且没有出口,因为一切都是以编程方式完成的。因此,我无法在情节提要中指定链接到 UIViewController 的子类。

我觉得一旦我解决了选择器问题,代码就会起作用。由于现在的代码,应用程序编译得很好。问题是我收到的运行时错误。如有必要,我可以提供来自调试器的信息。

Fwiw,运行时似乎从错误消息中识别出我有一个中心、左和右视图控制器。

我没有包含 RightSideBar 代码,因为我认为如果 left SideBar 运行,RightSideBar 将在我添加解决方案时运行。我想让你必须阅读的代码尽可能简短。

最后要注意的是,我正在处理我的所有打印声明。我实际上打印到它说“我应该显示侧边栏”。

这是 SideBar 的代码:

//optional delegate methods that select when the sidebar opens and closes.
@objc protocol SideBarDelegate : class {

func sideBarDidSelectButtonAtIndex (itemIndex: Int)
optional func sideBarWillClose()
optional func sideBarWillOpen()

}

//this class sets up the actual sidebar.
class SideBar: UIViewController, SidebarTableViewControllerDelegate {


//width of the bar, tableview setup, and views for the sidebar
let barWidth:CGFloat = 175.0
let sideBarTableViewTopInset:CGFloat = 25.0
let sideBarContainerView:UIViewController = UIViewController()
let sideBarTableViewController:SidebarTableViewController = SidebarTableViewController()
var originView:UIViewController?

//var for dynamic effect and controlling the sidebar
var animator:UIDynamicAnimator!
weak var delegate:SideBarDelegate?
var isSideBarOpen:Bool = false

//initializer for the "SideBar" class.
required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override init(nibName NibNameOrNil:String!, bundle nibBundleOrNil:NSBundle!) {
    super.init(nibName: nil, bundle: nil)

}

convenience init(){
    self.init(nibName: nil, bundle: nil)
}

//initializer for the tableView of menu items.
init(sourceView: UIViewController, menuItems: Array<String>, menuImages: [UIImage]){

    self.originView = sourceView
    self.sideBarTableViewController.tableData = menuItems
    self.sideBarTableViewController.imageData = menuImages

    println("set initialization values")
    super.init(nibName: nil, bundle: nil)

    //initializing the views and animation for the menu.
    setupSideBar()
    animator = UIDynamicAnimator(referenceView: originView!.view)

    println("finished initialization")

    //swipe gesture recognition for opening the menu.
    let showGestureRecognizer:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "handleSwipe:")
    showGestureRecognizer.direction = UISwipeGestureRecognizerDirection.Right
    originView!.view.addGestureRecognizer(showGestureRecognizer)

    let hideGestureRecognizer:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "handleSwipe:")
    hideGestureRecognizer.direction = UISwipeGestureRecognizerDirection.Left
    originView!.view.addGestureRecognizer(hideGestureRecognizer)
}

override func viewDidLoad() {

    println("view loaded")


}

//this function handles the direction of swipes
func handleSwipe(recognizer: UISwipeGestureRecognizer){
    if recognizer.direction == UISwipeGestureRecognizerDirection.Left {
        showSideBar(false)
        delegate?.sideBarWillClose?()
        println("closed the sideBar")
    } else {
        println("opened the sideBar")
        showSideBar(true)
        delegate?.sideBarWillOpen?()
    }
}

//function for setting up the sidebar.
func setupSideBar () {

    println("setup sideBar")

    //setting up the frame/outline of the side bar.

    sideBarContainerView.view.frame = CGRectMake(-barWidth - 1, originView!.view.frame.origin.y, barWidth, originView!.view.frame.size.height)

    //setting up the color of the sidebar.
    sideBarContainerView.view.backgroundColor = UIColor.clearColor()

    //disables subviews from being confined to the sidebar.
    sideBarContainerView.view.clipsToBounds = false

    //placing the sidebar in the UIView
    originView!.view.addSubview(sideBarContainerView.view)

    //adding blur to the menu.
    let blurView:UIVisualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.Light))
    blurView.frame = sideBarContainerView.view.bounds
    sideBarContainerView.view.addSubview(blurView)


    //setting up controls for the sidebar
    sideBarTableViewController.delegate = self
    sideBarTableViewController.tableView.frame = sideBarContainerView.view.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.view.addSubview(sideBarTableViewController.tableView)
    originView?.addChildViewController(sideBarContainerView)
    sideBarContainerView.didMoveToParentViewController(originView)

}


func showSideBar(shouldOpen: Bool){
    animator.removeAllBehaviors()
    isSideBarOpen = shouldOpen

    println("I should be showing the sideBar")

    //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 - 1

    //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!.view.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)
}

}

这里是 Home ViewController:

class Home: UIViewController, SideBarDelegate {

//*** Must put logout code into the logout button it should log the user out if they press it ***

var sideBar:SideBar = SideBar()

var homeImage = UIImage(named: "Shine Home")
var profileImage = UIImage(named: "Shine Profile")
var shareImage = UIImage(named: "Shine Share")
var aboutImage = UIImage(named: "Shine About")
var helpImage = UIImage(named: "Shine Help")

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    //setting up the menu items for the sidebar.
    sideBar = SideBar(sourceView: self, menuItems: ["Home", "Profile", "Share", "About", "Help"], menuImages: [homeImage!, profileImage!, shareImage!, aboutImage!, helpImage!])

    sideBar.delegate = self


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


func sideBarDidSelectButtonAtIndex(itemIndex: Int) {

    switch itemIndex {

    case 0:
        let vc = storyboard?.instantiateViewControllerWithIdentifier("Home") as! Home
        self.navigationController?.pushViewController(vc, animated: true)
    case 1:
        performSegueWithIdentifier("profile", sender: self)
    case 2:
        performSegueWithIdentifier("share", sender: self)
    case 3:
        performSegueWithIdentifier("about", sender: self)
    case 4:
        performSegueWithIdentifier("help", sender: self)

    default:
        break
    }
}

/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}

【问题讨论】:

  • 尝试 let sideBarContainerView:UIViewController = UIViewController() as! SideBar 会产生运行时错误:无法将 UIViewController 类型的值转换为 SideBar。这是我能想到的向代码添加某种信号的唯一方法,即 SideBar 是唯一的。

标签: ios swift uiviewcontroller menu sidebar


【解决方案1】:

无法识别选择器的这种情况源于运行时不知道要激活的具体对象。

运行时看到sideBarContainerView 对象,这是编译器可以接受的。

问题在于您的动画行为是针对视图的。您的 UIViewController 对象尚未下降到 UIViews。您需要将.view 添加到您的showSideBar 函数中的所有sideBarContainerView

如果你分解你的函数,只使用isSideBarOpen 作为常量中的 if 语句的布尔值并将它放在菜单的初始化中,那么你会立即得到 Selector 错误。

这只是表明错误已超出您最后一个打印语句"I should be showing SideBar 的第二种方式。

如果您这样做,那么您的菜单将会加载。到目前为止,我还没有解决方案让两个菜单都初始化为左右菜单。

【讨论】:

    猜你喜欢
    • 2019-08-28
    • 2012-07-24
    • 1970-01-01
    相关资源
    最近更新 更多