UITextView contentOffset на iOS 7

У меня есть UITextView в моем приложении. Мне нужно динамически изменять его смещение содержимого каждый раз при добавлении новой строки. Нижеприведенный код отлично работает на iOS 6 и более ранних версиях, но не на iOS 7.

CGPoint offset = CGPointMake(0, self.textView.contentSize.height - self.textView.frame.size.height);
[self.textView setContentOffset:bottomOffset animated:YES]; 

Есть ли у вас какие-либо идеи?

Чем ты.

UPDATE

UITextView не устанавливает его contentOffset так, как должен, или что-то еще испортит его. Результат не так, как ожидалось (как на iOS 6 или более ранних версиях).

Я также попытался установить новое свойство textContainerInset, но все равно никаких результатов...

self.textView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)    

UPDATE

Как я могу видеть в методе делегата didScroll, когда я передаю положительное значение для смещения содержимого, он прокручивается до (0,0). Например, я установил смещение содержимого (0,35), и он прокручивается до (0,0)...

Ответы

Ответ 1

Хорошо, на основании моих исследований и других ответов проблема заключалась в высоте содержимого UITextView, а не прокрутке к определенному смещению. Вот решение, которое работает так, как должно работать для iOS 7:

Сначала вам нужно воссоздать UITextView следующим образом:

    NSString *reqSysVer = @"7.0";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    BOOL osVersionSupported = ([currSysVer compare:reqSysVer  options:NSNumericSearch] != NSOrderedAscending);

    if (osVersionSupported) {

        NSLog(@"reset chatoutput");

        CGRect outputFrame = self.chatOutput.frame;

        [chatOutput removeFromSuperview];
        [chatOutput release];
        chatOutput = nil;

        NSTextStorage* textStorage = [[NSTextStorage alloc] init];
        NSLayoutManager* layoutManager = [NSLayoutManager new];
        [textStorage addLayoutManager:layoutManager];
        NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:self.view.bounds.size];
        [layoutManager addTextContainer:textContainer];
        chatOutput = [[UITextView alloc] initWithFrame: outputFrame
                                           textContainer: textContainer];
        // if using ARC, remove these 3 lines
        [textContainer release];
        [layoutManager release];
        [textStorage release];

        [self.view addSubview: chatOutput];
    }

Затем используйте этот метод, чтобы получить высоту содержимого UITextView:

- (CGFloat)textViewHeightForAttributedText:(NSAttributedString*)text andWidth:(CGFloat)width
{
     UITextView *calculationView = [[UITextView alloc] init];
     [calculationView setAttributedText:text];
     CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];

     NSLog(@"size: %f", size.height) ;

     return size.height;
}

Теперь вы можете установить смещение содержимого:

CGPoint bottomOffset;

bottomOffset = CGPointMake(0, [self textViewHeightForAttributedText: self.chatOutput.attributedText andWidth: self.chatOutput.frame.size.width] - self.chatOutput.frame.size.height);

[self.chatOutput setContentOffset:bottomOffset animated:YES];

UPDATE

Я прочитал это в Apple Documentation для NSAttributedString: "Шрифт по умолчанию для объектов NSAttributedString - это 12-точечная версия Helvetica, которая может отличаться от системного шрифта по умолчанию для платформы".

В заключение, если вы используете разные шрифты разных размеров, вы должны также установить их в экземпляр NSAttributeString. В противном случае возвращаемая высота не будет соответствовать вашим ожиданиям. Вы можете использовать что-то вроде этого:

    NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObject: [UIFont systemFontOfSize: 18.0] //or any other font or size
                                                                forKey: NSFontAttributeName];
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString: currentPost.postMessageText attributes: attrsDictionary];
    frame.size.height = [self textViewHeightForAttributedText: attributedString andWidth: 280.0];
    [attributedString release];

Ответ 2

Решение, которое я нашел, совсем не изящно, но оно работает:

Я установил для UITextView contentOffset значение (0,0), прежде чем устанавливать его на нужный сдвиг. Я не знаю, почему это работает, но на данный момент это лучшее решение, которое я нашел.

CGPoint bottomOffset = CGPointMake(0, self.textView.contentSize.height - self.textView.frame.size.height);
[self.textView setContentOffset: CGPointMake(0,0) animated:NO]; 
[self.textView setContentOffset:bottomOffset animated:YES]; 

Ответ 3

Я только что заметил это сегодня. В моем случае проблема, по-видимому, связана с тем, что Text View является первым элементом управления в представлении. Я переместил его на второе место в контуре документа (например, после UILabel), и смещение исчезло.

Скорее всего, это делается специально из-за нового поведения навигационной панели в iOS7.

Ответ 4

@vidonism answer работает, но это еще лучше.

// in -viewDidLoad of UIViewController
self.automaticallyAdjustsScrollViewInsets = NO;

См. также верхний комментарий принятого ответа на этот question. Вероятно, это объясняет поведение UIScrollView, являющегося первым подвидью основного вида ViewController.
Я не могу полностью игнорировать, если это ожидаемое поведение или ошибка.

Ответ 5

Мне приходилось прибегать к

[displayText scrollRangeToVisible:NSMakeRange([displayText.text length], 0)];

но проблема BIG заключается в том, что он начинается с верхней части текста и прокручивается до конца каждый раз, когда вы добавляете текст. Решение Mihai также делает это.

Ответ 6

Ни один из предыдущих ответов не работал у меня, потому что у меня был [textView setScrollEnabled:NO]. Итак, я закончил с этим:

[textView setScrollEnabled:YES]
[self.text setContentOffset:CGPointMake(0, page * self.text.frame.size.height) animated:NO];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [self.text setScrollEnabled:NO];
});