我想知道是否有人可以解释为什么要派遣回主队列并创建重复NSTimer
我必须将它添加到RUN LOOP因为太火了?即使使用performselectorOnMainThread
,我仍然需要将它添加到RUN循环才能触发它。
以下是我的问题示例:
#define queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define mainqueue dispatch_get_main_queue()
- (void)someMethodBeginCalled
{
dispatch_async(queue, ^{
int x = 0;
dispatch_async(mainqueue, ^(void){
if([_delegate respondsToSelector:@selector(complete:)])
[_delegate complete:nil];
});
});
}
- (void)compelete:(id)object
{
[self startTimer];
//[self performSelectorOnMainThread:@selector(startTimer) withObject:nil waitUntilDone:NO];
}
- (void)startTimer
{
NSTimer timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(callsomethingelse) userInfo:nil repeats:YES];
//NSDefaultRunLoopMode
[[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes];
}
修改
我相信我措辞很差。如果我致电[[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes];
,我想知道为什么 startTimer
需要someMethodBeginCalled
。如果我不包括该行,则计时器不会触发。
例如,如果我从startTimer
拨打viewDidLoad
,我可以删除NSRunLoop
行,计时器将每隔60秒触发一次。
答案 0 :(得分:20)
以下是如何将NSTimer
添加到runloop:
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
答案 1 :(得分:14)
您可以随时使用此方法:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(getBusLocation) userInfo:nil repeats:YES];
这会为你节省一条线,因为它会自动将它添加到运行循环中。
答案 2 :(得分:4)
因为,docs说:
计时器与运行循环一起使用。要有效地使用计时器, 你应该知道运行循环的运行方式 - 参见NSRunLoop和 线程编程指南。特别注意运行循环保留 他们的计时器,所以您可以在将计时器添加到计时器后释放计时器 运行循环。
这是Apple在为NSTimer编写代码时所做的设计决定(我确信他们有充分的理由这样做)并且我们无法绕过它。真的那么累吗?
答案 3 :(得分:3)
就像@sosborn说的那样,NSTimer
取决于NSRunLoop
,并且由于GCD队列创建的线程没有运行循环,NSTimer
与{GCD
不匹配1}}。
查看有关此问题的其他StackOverflow问题:Is it safe to schedule and invalidate NSTimers on a GCD serial queue?
为了解决这个问题,我实施了MSWeakTimer
:https://github.com/mindsnacks/MSWeakTimer(并在最后一个WWDC上由libdispatch工程师检查了实现!)
答案 4 :(得分:0)
在我的情况下,将计时器添加到runloop并不起作用。我不得不在主线程上创建计时器。我在MultipeerConnectivity委托中创建了这个线程。
dispatch_async(dispatch_get_main_queue(), ^{
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.interval invocation: self.invocation repeats:YES];
});
答案 5 :(得分:0)
由于GCD队列创建了没有运行循环的线程,因此无法调用计时器方法
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Product_model extends CI_Model{
public function __construct()
{
$this->load->database();
parent::__construct();
//Codeigniter : Write Less Do More
}
public function get_product()
{
#code
$query=$this->db->get('products');
return $query->result_array();
}
public function set_product($id=0)
{
#code
// if($this->input->post('userSubmit')){
$picture=array();
$count=count($_FILES['picture']['name']);
//Check whether user upload picture
if(!empty($_FILES['picture']['name'])){
foreach($_FILES as $value)
{
for($s=0; $s<=$count-1; $s++)
{
$_FILES['picture']['name']=$value['name'][$s];
$_FILES['picture']['type'] = $value['type'][$s];
$_FILES['picture']['tmp_name'] = $value['tmp_name'][$s];
$_FILES['picture']['error'] = $value['error'][$s];
$_FILES['picture']['size'] = $value['size'][$s];
$config['upload_path'] = 'uploads/images/';
$config['allowed_types'] = 'jpg|jpeg|png|gif';
$config['file_name'] = $_FILES['picture']['name'];
//Load upload library and initialize configuration
$this->load->library('upload',$config);
$this->upload->initialize($config);
// print_r($value['name'][$s]);exit;
if($this->upload->do_upload('picture')){
$uploadData = $this->upload->data();
$picture[] = $uploadData['file_name'];
}
else{
$picture = '';
}
}
}
}//end of first if
else{
$picture = '';
}
$data=array(
'product_name'=>$this->input->post('product_name')
);
$picture=array(
'product_id'=>$this->db->get('products',$id),
'picture_image'=>$picture
);
if ($id==0)
{
return $this->db->insert('products',$data);
return $this->db->insert('images',$picture);
}
else {
$this->db->where('id',$id);
return $this->db->update('products',$data);
return $this->db->update('images',$picture);
}
}
}
然而,当在主队列上调度时,将调用timer方法,因为它将被添加到主线程运行循环中。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
NSLog(@"Timer method from GCD main queue");
}];
});