我在计时器中调用一个函数会抛出以下错误:
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)
答案 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处于同一级别,并且选择器没有“:”。希望对你有用!