0
  • (void)fetchLastMessageInChannel

{ __weak id weakSelf = self;

    for (ANKChannel *channel in self.channelArray)
    {
            NSLog(@"channels %@",channel);

             NSLog(@"channel last message %@",channel.latestMessageID);

        [[ClientManager currentClient] fetchMessageWithID:channel.latestMessageID inChannel:channel
                                               completion:^(id responseObject, ANKAPIResponseMeta *meta, NSError *error)
         {
             NSLog(@"message object %@",responseObject);
             ANKMessage *message = responseObject;

             dispatch_async(dispatch_get_main_queue(), ^{
                 [weakSelf populateTextViews:message.text];
             });

             NSLog(@"message text %@",message.text);

         }];

    }

}

-(void)populateTextViews:(NSString *)message {

NSMutableArray *textViews = [@[] mutableCopy];

NSMutableAttributedString *postText = [[NSMutableAttributedString alloc] initWithString:message];
[postText addAttributes:@{
                          NSFontAttributeName : [UIFont preferredFontForTextStyle:UIFontTextStyleBody],
                          NSForegroundColorAttributeName : [UIColor darkTextColor]
                          }
                  range:NSMakeRange(0, postText.length)];

UITextView *postTextView = [[UITextView alloc] initWithFrame:CGRectMake(80, 30, kPostLabelMaxWidth, 44)];
postTextView.attributedText = postText;
postTextView.dataDetectorTypes = UIDataDetectorTypeAll;
postTextView.backgroundColor = [UIColor whiteColor];
postTextView.editable = NO;
postTextView.scrollEnabled = NO;
postTextView.clipsToBounds = NO; // So it doesn't clip the text selector

CGRect textViewBounds = postTextView.bounds;
textViewBounds.origin = CGPointMake(80, 30);
textViewBounds.size.width = MAX(textViewBounds.size.width, kPostLabelMaxWidth);
textViewBounds.size.height = postTextView.contentSize.height;


postTextView.bounds = textViewBounds;

[postTextView sizeToFit]; // Reload the content size

[textViews addObject:postTextView];



self.channelTextViewArray = [textViews copy];

}

在我得到的帮助下,就我的方法而言,这就是我现在的立场。self.channelTextViewArray 返回 nil 并导致崩溃,因为 populateTextViews(NSString*) 消息永远不会被调用。

有任何想法吗?

4

1 回答 1

1

如果ClientManager调用是异步的,则该populateTextViews方法将在异步调用返回之前完成,这就是您不能使用在其完成块中设置的值的原因。

要么放...

NSMutableAttributedString *postText = [[NSMutableAttributedString alloc] initWithString:messageText];

...在完成块内,或者在拥有 messageText 后调用完成块内的方法。在这样做时,您也不必声明 __block 变量。

如果会有 UI 更新,请确保发生在主线程上。

编辑

这是基本想法,但我猜您正在更新多个文本视图,因此您可能需要更改签名。如果你明白了基本的想法——调用异步方法不会中断你的代码流(基本上它说“当你有机会时这样做,可能在另一个线程上”)。这就是你有一个完成块的原因——它是你代码中的一个地方,你知道你调用的异步方法已经完成。

如果块内的内容根本没有被调用,请确保它self.channelArray具有值,并查看fetchMessageWithID如果出现问题会发生什么。

- (void)populateTextViews 
{
    __weak id weakSelf = self;
    for (ANKChannel *channel in self.channelArray)
    {    
        [[ClientManager currentClient] fetchMessageWithID:channel.latestMessageID inChannel:channel
                                               completion:^(id responseObject, ANKAPIResponseMeta *meta, NSError *error)
         {
             NSLog(@"message object %@",responseObject);
             ANKMessage *message = responseObject;
             dispatch_async(dispatch_get_main_queue(), ^{
                 [weakSelf updateTextView:message.text];
             });        
         }];
    }
}

- (void)updateTextView:(NSString *)message
{
    // Make an attributed string from the post text content
    NSMutableAttributedString *postText = [[NSMutableAttributedString alloc] initWithString:messageText];
    self.textView.attributedText = postText;
}
于 2013-08-24T22:21:17.320 回答