无法识别的选择器在函数调用中发送到实例

时间:2014-08-13 23:07:44

标签: ios timer swift unrecognized-selector

我在计时器中调用一个函数会抛出以下错误:

AppName.CollectionViewController lastActive]: unrecognized selector sent to instance

当计划启动计时器时,应用程序崩溃并抛出异常。这是计时器及其调用的函数:

       var timer = NSTimer.scheduledTimerWithTimeInterval(180, target: self, selector: Selector("lastActive:"), userInfo: nil, repeats: true)
        }

        func lastActive(){
            if PFUser.currentUser(){
                PFCloud.callFunctionInBackground("registerActivity", withParameters: [:], target: nil, selector: Selector("lastActive:"))
            }
        }

还有另一种方法可以在定时器中调用该功能吗?我需要在"选择器中放入什么:"参数?

谢谢!

编辑:全班同学:

import UIKit

let reuseIdentifier = "Cell"

class LobbyCollectionViewController: UICollectionViewController, UICollectionViewDataSource {

    var lobbyData:NSMutableArray = NSMutableArray()


    override func viewDidAppear(animated: Bool) {

        if (!PFUser.currentUser()){
            var loginAlert:UIAlertController = UIAlertController(title: "Sign Up / Login", message: "Enter your login information and press the Log In button to log into the app. If you are new, enter in the desired login information and press the Sign Up button.", preferredStyle:UIAlertControllerStyle.Alert)

            loginAlert.addTextFieldWithConfigurationHandler({
                textfield in
                textfield.placeholder = "Username"
            })

            loginAlert.addTextFieldWithConfigurationHandler({
                textfield in
                textfield.placeholder = "Password"
                textfield.secureTextEntry = true
            })


            loginAlert.addAction(UIAlertAction(title: "Login", style: UIAlertActionStyle.Default, handler: {
                alertAction in
                let textFields:NSArray = loginAlert.textFields as NSArray
                let usernameTextField:UITextField = textFields.objectAtIndex(0) as UITextField
                let passwordTextField:UITextField = textFields.objectAtIndex(1) as UITextField

                PFUser.logInWithUsernameInBackground(usernameTextField.text, password: passwordTextField.text){
                    (user:PFUser!, error:NSError!)->Void in
                    if (user){
                        println("Login successful")
                    } else {
                        println("Login failed")
                    }
                }
                }))


            loginAlert.addAction(UIAlertAction(title: "Sign Up", style: UIAlertActionStyle.Default, handler: {
                alertAction in
                let textFields:NSArray = loginAlert.textFields as NSArray
                let usernameTextField:UITextField = textFields.objectAtIndex(0) as UITextField
                let passwordTextField:UITextField = textFields.objectAtIndex(1) as UITextField

                var user:PFUser = PFUser()
                user.username = usernameTextField.text
                user.password = passwordTextField.text

                user.signUpInBackgroundWithBlock{
                    (success:Bool!, error:NSError!)->Void in
                    if !error{
                        println("Sign Up successful")
                    }else{
                        let errorString = error.userInfo["error"] as NSString
                        println(errorString)
                    }

                }

            }))

            self.presentViewController(loginAlert, animated: true, completion: nil)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        if PFUser.currentUser(){

            self.loadData()

            PFCloud.callFunctionInBackground("registerActivity", withParameters: [:], target: nil, selector: "block:")

            var timer = NSTimer.scheduledTimerWithTimeInterval(180, target: self, selector: Selector("lastActive:"), userInfo: nil, repeats: true)
            //(timeInterval: 180, target: self, selector: "registerActivity", userInfo: nil, repeats: true)
        }

        func lastActive(){
            if PFUser.currentUser(){
                PFCloud.callFunctionInBackground("registerActivity", withParameters: [:], target: nil, selector: "block:")
            }
        }


        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Register cell classes
        self.collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

        // Do any additional setup after loading the view.
    }

    func loadData(){
        lobbyData.removeAllObjects()

        if PFUser.currentUser(){

            PFCloud.callFunctionInBackground("getOnlineUsers", withParameters: [:], target: nil, selector: "block:")

            func block(users: NSArray, error:NSError){
                if(error != nil){

                    self.lobbyData = users as NSMutableArray
                }
            }

            //var timer = NSTimer.scheduledTimerWithTimeInterval(180, target: self, selector: "block:", userInfo: nil, repeats: true)

        }

    }

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

    /*
    // 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.
    }
    */

    // MARK: UICollectionViewDataSource

    override func numberOfSectionsInCollectionView(collectionView: UICollectionView!) -> Int {
        //#warning Incomplete method implementation -- Return the number of sections
        return 1
    }


    override func collectionView(collectionView: UICollectionView!, numberOfItemsInSection section: Int) -> Int {
        //#warning Incomplete method implementation -- Return the number of items in the section
        return lobbyData.count
    }

    override func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell! {
        //let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as UICollectionViewCell

        // Configure the cell

        var cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as FightCollectionViewCell
        let battle:PFUser = self.lobbyData.objectAtIndex(indexPath!.row) as PFUser



        return cell
    }

更详细的错误:

[AppName.LobbyCollectionViewController lastActive:]: unrecognized selector sent to instance 0x7ffc60c34100
AppName[435:6742] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AppName.LobbyCollectionViewController lastActive:]: unrecognized selector sent to instance 0x7ffc60c34100'
*** First throw call stack:
(
    0   CoreFoundation                      0x00000001117343e5 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x0000000113247967 objc_exception_throw + 45
    2   CoreFoundation                      0x000000011173b4fd -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x00000001116937ec ___forwarding___ + 988
    4   CoreFoundation                      0x0000000111693388 _CF_forwarding_prep_0 + 120
    5   Foundation                          0x0000000111b67e94 __NSFireTimer + 83
    6   CoreFoundation                      0x000000011169c4d4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
    7   CoreFoundation                      0x000000011169c095 __CFRunLoopDoTimer + 1045
    8   CoreFoundation                      0x000000011165f3cd __CFRunLoopRun + 1901
    9   CoreFoundation                      0x000000011165e9f6 CFRunLoopRunSpecific + 470
    10  GraphicsServices                    0x00000001153a69f0 GSEventRunModal + 161
    11  UIKit                               0x0000000111fbd990 UIApplicationMain + 1282
    12  AppName                           0x000000010fff808e top_level_code + 78
    13  AppName                           0x000000010fff80ca main + 42
    14  libdyld.dylib                       0x00000001137cf145 start + 1
    15  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

1 个答案:

答案 0 :(得分:1)

如果你在末尾使用带有':'的选择器,它将寻找一个带参数的选择器。尝试使用“lastActive”或为发送上下文的“self”添加参数。

为选择器指定的名称标记的函数必须是目标的成员。即。在上面的代码中,您将目标指定为'self',它指的是类LobbyCollectionViewController的一个实例。但是,您的函数func lastActive()嵌入在override func viewDidLoad()函数中 - 这意味着它不是LobbyViewController的成员(并且是一种非常典型的编码方式,在函数内部具有函数,而不是闭包)。要解决这个问题,重构如下:

override func viewDidLoad() {
    super.viewDidLoad()

    if PFUser.currentUser(){

        self.loadData()

        PFCloud.callFunctionInBackground("registerActivity", withParameters: [:], target: nil, selector: "block:")

        var timer = NSTimer.scheduledTimerWithTimeInterval(180, target: self, selector: Selector("lastActive"), userInfo: nil, repeats: true)
        //(timeInterval: 180, target: self, selector: "registerActivity", userInfo: nil, repeats: true)
    }

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = false

    // Register cell classes
    self.collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

    // Do any additional setup after loading the view.
}


func lastActive(){
    if PFUser.currentUser(){
        PFCloud.callFunctionInBackground("registerActivity", withParameters: [:], target: nil, selector: "block:")
        }
}

请注意,该函数现在与viewDidLoad处于同一级别,并且选择器没有“:”。希望对你有用!