我正在使用NSTimer在一段时间内发送消息。这是代码:
{
// ....
var params : [String] = []
params.append(conversion)
params.append(message)
let timer = NSTimer(fireDate: date, interval: 60, target: self, selector: Selector("importTextMessage.sendMessage:"), userInfo: params, repeats: true)
NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
// ...
}
func sendMessage(params: [String]){ ...}
我也尝试过更改为Swift 2.2语法:
let timer = NSTimer(fireDate: date, interval: 60, target: self, selector: #selector(importTextMessage.sendMessage(_:)), userInfo: params, repeats: true)
但这不会改变任何事情。
从发布的关于“无法识别的选择器发送到实例”的每个其他问题,响应是“在选择器中包含一个冒号,以便它知道从UserInfo中获取参数”,但我已经包含了这个,并且无法计算出了什么问题。
注意事项:
通过NSTimer userInfo DO传递的函数和参数的参数匹配。它们都是字符串数组。
如果它意味着什么,则在调用sendMessage时代码失败。它实际上并没有使它成为sendMessage。
我收到一个奇怪的警告,说“String literal不是一个有效的objective-c选择器”
我尝试更改sendMessage的代码,将Timer作为参数,如1用户建议的那样:func sendMessage(timer: NSTimer){
但仍然会出现相同的错误。
感谢您的帮助,我很感激。
编辑:这是运行计时器的函数://保存所有数据 @IBAction func saveText(sender:AnyObject){ var手机:双倍 var active:Int var频率:双倍 var message:String var date:NSDate
phone = Double(currentNumber)!
active = 1
message = myTextView.text
date = myDatePicker.date
switch self.frequency.selectedRowInComponent(0) {
case 0:
frequency = 1
case 1:
frequency = 3
case 2:
frequency = 6
case 3:
frequency = 24
case 4:
frequency = 168
case 5:
frequency = 744
default:
frequency = 8760
}
importTextMessage.seedMessage(phone, active: active, frequency: frequency, message: message, date: date)
print(date)
let conversion : String = "+1" + String(Int(phone))
//importTextMessage.sendMessage("Ryan", to: conversion, message: message)
var params : [String] = []
params.append(conversion)
params.append(message)
//importTextMessage.sendMessage(params)
let timer = NSTimer(fireDate: date, interval: 60, target: self, selector: #selector(importTextMessage.sendMessage(_:)), userInfo: params, repeats: true)
//
NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
}
编辑:确切错误mssg:
无法识别的选择器发送到实例0x7ffe6b915460 2016-07-25 13:26:09.092 Harass Your Kate [53524:9000621] ***由于未捕获的异常'NSInvalidArgumentException'终止应用程序,原因:' - [Harass_Your_Kate.AddMessageViewController sendMessage:]:无法识别的选择器发送到实例0x7ffe6b915460 < / p>
答案 0 :(得分:1)
来自doc:
计时器将自己作为参数传递
所以你的计时器期望其他参数类型NSTimer
。试试这段代码:
override func viewDidLoad() {
super.viewDidLoad()
var params : [String] = []
params.append(conversion)
params.append(message)
let timer = NSTimer(fireDate: date, interval: 60, target: self, selector: #selector(sendMessage(_:)), userInfo: params, repeats: true)
NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
}
func sendMessage(sender: NSTimer) {
print(sender.userInfo as? [String])
}
此代码在我的标准视图控制器
中正常工作答案 1 :(得分:0)
NSTimer的API是这样的,接收者(目标函数)必须只接受一个NSTImer类型的参数。
定时器触发时发送给目标的消息。
选择器应具有以下签名:timerFireMethod: (包括冒号以指示该方法接受参数)。该 timer将自身作为参数传递,因此该方法将采用 以下模式:
- (void)timerFireMethod:(NSTimer *)timer
在Swift中,签名必须
编辑:更新以完全匹配您的代码
注意:Swift 2.2语法
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="288dp">
<android.support.v7.widget.CardView
android:id="@+id/card_view1"
android:layout_width="match_parent"
android:layout_height="288dp"
android:elevation="3dp"
card_view:cardCornerRadius="0dp"
android:gravity="top">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/card"
android:focusable="true"
android:contextClickable="true"
android:gravity="top"
android:layout_alignParentBottom="true">
<ImageView
android:id="@+id/thumbnail1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:src="@drawable/ic_menu_send"
android:contextClickable="true"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:id="@+id/title1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="25dp"
android:paddingTop="10dp"
android:textColor="@color/cardview_dark_background"
android:textSize="15dp"
android:layout_above="@+id/count1"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:id="@+id/count1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingRight="25dp"
android:textSize="12dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
</LinearLayout>
就userInfo字典而言,它是计时器对象的属性,而不是目标函数本身的参数。
SECOND 错误是选择器语法未能将类的名称用作声明的,而不是某个引用该类的实例变量的名称类实例。在您的问题中包含更多上下文,以便更快地解决!
THIRD 错误是你使用了错误的类名。如果您使用class TextMessageViewController: UIViewController {
var importTextMessage: AddMessageViewController // init'd somehow
override func viewDidLoad() {
super.viewDidLoad()
// ...
// Note how selector matches *the name of the class*
// As I understand it now, the sendMessage method
// is declared in the AddMessageViewController class,
// and importTextMessage is the name of the instance of that class.
// And we're in a different class now, TextMessageViewController,
// so using `self` does not make sense here.
let timer = NSTimer(fireDate: date, interval: 60, target: importTextMessage,
selector: #selector(AddMessageViewController.sendMessage(_:)), userInfo: params, repeats: true)
NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
}
}
class AddMessageViewController: UIViewController {
// func must not be private
func sendMessage(timer: NSTimer) {
// And now for example
print("params: \(timer.userInfo)")
}
}
,则选择器中的类名必须与当前类的名称相匹配。由于您确实希望消息转到其他类,因此您必须使用该引用。查看更新的代码。
我认为你仍然没有完全掌握对象引用及其类型,以及它们必须如何匹配,以及self
如何仅仅是对上下文对象的引用。