目标c只能从主线程调用

Posted

技术标签:

【中文标题】目标c只能从主线程调用【英文标题】:objective c can only be called from main thread 【发布时间】:2015-12-23 19:48:53 【问题描述】:

我正在尝试从 javascript 使用的回调方法调用委托。但是当我从回调执行委托而不是事件触发时,我收到了错误"Can only be called from main thread"

注意:错误在代码的最后一行。

这是代码的样子

RCT_EXPORT_METHOD(setBold) 

  if(_bold == NO)
  
    _bold = YES;
  
  else if (_bold == YES)
  
    _bold = NO;
  
  else
    _bold = NO;
  

  if(_textV!=nil)
  
    _delCalled = YES;
    [self textViewDidChangeSelection:_textV];
  





-(void)textViewDidChangeSelection:(UITextView *)textView

  _textV = textView;

  _selectedText = [textView.text substringWithRange:textView.selectedRange];
  _rangeStart = textView.selectedRange.location;
  _rangeEnd = textView.selectedRange.length;

  if(_delCalled == YES)
  
    [self applyBold:textView];
    _delCalled = NO;
  



  NSDictionary *event = @
                          @"target": textView.reactTag,
                          @"highlights": @
                              @"text": textView.text,
                              @"range": @(textView.selectedRange.length),
                              @"cursorPosition": @(textView.selectedRange.location),
                              @"eventType": @"textViewDidChangeSelection",
                              
                          ;
  [self.bridge.eventDispatcher sendInputEventWithName:@"topChange" body:event];


-(void)applyBold:(UITextView *)textView

  NSMutableAttributedString *formatString;
  UIFont* boldFont;
  NSString *selectedText = _selectedText;


  _rangeStart -=1;


  if(_rangeEnd == 0)
  
    _rangeEnd = 1;
  
  else
  
    _rangeStart +=1;
  

NSRange range = NSMakeRange(_rangeStart, _rangeEnd);


  if (_bold==YES) 
   boldFont= [UIFont boldSystemFontOfSize:[UIFont systemFontSize]];
  
  else
    boldFont= [UIFont systemFontOfSize:textView.font.pointSize];
  

  NSAttributedString *lem = textView.attributedText;

    NSMutableAttributedString *textViewText = [[NSMutableAttributedString alloc]initWithAttributedString:textView.attributedText];


  NSDictionary *boldAttr = [NSDictionary dictionaryWithObject:boldFont forKey:NSFontAttributeName];

  formatString = [[NSMutableAttributedString alloc]initWithString:selectedText attributes:boldAttr];

  if(![selectedText isEqual:@""] || ![selectedText isEqual:@" "])
  
    [textViewText replaceCharactersInRange:range withAttributedString:formatString];

//this is where the error happens
      textView.attributedText = textViewText;



  

【问题讨论】:

【参考方案1】:

ios 中,任何更新 UI 的方法都必须在主线程上调用。 iOS UIKit 不是线程安全的。因此,解决方案是将代码放在主线程上,像这样

dispatch_async( dispatch_get_main_queue(), ^
   textView.attributedText = textViewText;
);

【讨论】:

【参考方案2】:

将产生错误的行包含在主队列的 dispatch_async 中

dispatch_async(dispatch_get_main_queue(), ^
    ...
);

【讨论】:

谢谢你修复它。

以上是关于目标c只能从主线程调用的主要内容,如果未能解决你的问题,请参考以下文章

在C ++中是否可以从主线程中执行辅助线程中运行的函数?

- 必须仅从主线程调用[UIApplication委托]

GMSThreadException' 原因:'API 方法必须从主线程调用'

即使从主线程调用更新,UI 也不会更新

在 Apple 的 Cocoa API 中,为啥从主线程调用 NSApplicationMain 很重要?

为啥从主线程调用时,`std::promise::set_value` 会抛出错误?