Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/43.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 以编程方式设置文本时,停止UITextView跳转_Iphone_Cocoa Touch_Uitextview - Fatal编程技术网

Iphone 以编程方式设置文本时,停止UITextView跳转

Iphone 以编程方式设置文本时,停止UITextView跳转,iphone,cocoa-touch,uitextview,Iphone,Cocoa Touch,Uitextview,我必须更新滚动UITextView中的少量文本。我将只在光标当前所在的位置插入一个字符,只需按下导航栏上的按钮即可 我的问题是,每当我调用文本视图的setText方法时,它都会跳到文本的底部。我尝试过使用contentOffset并重置selectedRange,但不起作用!下面是我的例子: // Remember offset and selection CGPoint contentOffset = [entryTextView contentOffset]; NSRange selecte

我必须更新滚动UITextView中的少量文本。我将只在光标当前所在的位置插入一个字符,只需按下导航栏上的按钮即可

我的问题是,每当我调用文本视图的setText方法时,它都会跳到文本的底部。我尝试过使用contentOffset并重置selectedRange,但不起作用!下面是我的例子:

// Remember offset and selection
CGPoint contentOffset = [entryTextView contentOffset];
NSRange selectedRange = [entryTextView selectedRange];
// Update text
entryTextView.text = entryTextView.text;
// Try and reset offset and selection
[entryTextView setContentOffset:contentOffset animated:NO];
[entryTextView setSelectedRange: selectedRange];
有没有什么方法可以在不移动任何滚动的情况下更新文本。。。好像他们只是在键盘上键入了什么

编辑:

我尝试过使用textViewDidChange:delegate方法,但它仍然无法向上滚动到原始位置

- (void)textViewDidChange:(UITextView *)textView {
    if (self.programChanged) {
        [textView setSelectedRange:self.selectedRange];
        [textView setContentOffset:self.contentOffset animated:NO];
        self.programChanged = NO;
    }
}

- (void)changeButtonPressed:(id)sender {
    // Remember position
    self.programChanged = YES;
    self.contentOffset = [entryTextView contentOffset];
    self.selectedRange = [entryTextView selectedRange];
    // Update text
    entryTextView.text = entryTextView.text;
}

看看UITextViewDelegate,我相信textViewDidChangeSelection方法可以让你做你需要的事情。

不是很优雅的解决方案-但它工作得很好,谁在乎呢:

- (IBAction)changeTextProgrammaticaly{
     myTextView.text = @"Some text";
     [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(rewindOffset) userInfo:nil repeats:NO];
}

- (void)rewindOffset{
    [myTextView setContentOffset:CGPointMake(0,0) animated: NO];
}

如果您使用iPhone 3.0或更高版本,则可以解决此问题:

textView.scrollEnabled = NO;

//You should know where the cursor will be(if you update your text by appending/inserting/deleting you can know the selected range) so keep it in a NSRange variable.

Then update text:
textView.text = yourText;

textView.scrollEnabled = YES;
textView.selectedRange = range;//you keep before
现在应该可以用了(不要再跳了)

问候
Meir分析公司

建议的解决方案中没有一种对我有效-setContentOffset:animated:由-setText:3次触发,动画为YES,结尾为contentOffset(减去UITextView的默认8pt边距)。我把-setText:包在一个警卫里:

textView.contentOffsetAnimatedCallsDisabled = YES;
textView.text = text;
textView.contentOffsetAnimatedCallsDisabled = NO;
在-setContentOffset:animated:put中的UITextView子类中

if (contentOffsetAnimatedCallsDisabled) return; // early return
在你的其他逻辑中。别忘了超级电话。这很有效


Raphael

基于Meir的建议,下面的代码以编程方式删除选择(是的,我知道有一个选择菜单按钮也可以这样做,但我正在做一些有点古怪的事情),而无需滚动文本视图

NSRange selectedRange = textView.selectedRange;
textView.scrollEnabled = NO;
// I'm deleting text. Replace this line with whatever insertions/changes you want
textView.text = [textView.text
                stringByReplacingCharactersInRange:selectedRange withString:@""];
selectedRange.length = 0;
// If you're inserting text, you might want to increment selectedRange.location to be
// after the text you inserted
textView.selectedRange = selectedRange;
textView.scrollEnabled = YES;

我找到了一个在iOS 6和iOS 7(可能还有更早版本)中运行可靠的解决方案。在UITextView的子类中,执行以下操作:

@interface MyTextView ()
@property (nonatomic) BOOL needToResetScrollPosition;
@end

@implementation MyTextView

- (void)setText:(NSString *)text
{
    [super setText:text];
    self.needToResetScrollPosition = YES;
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    if (self.needToResetScrollPosition) {
        self.contentOffset = CGPointMake(0, 0);
        self.needToResetScrollPosition = NO;
    }
}

其他答案在iOS 7中都不起作用,因为它会在显示时调整滚动偏移。

旧问题,但iOS 7应用程序也有同样的问题。需要在运行循环后稍微更改contentOffset。这里有一个快速的想法

self.clueString = [self.level clueText];
CGPoint point = self.clueText.contentOffset;
self.clueText.attributedText = self.clueString;
double delayInSeconds = 0.001; // after the run loop update
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [self.clueText setContentOffset:point animated:NO]; 
});

在iOS 7中。在UITextView中可能有一个sizeThatFits和换行错误。我发现的解决方案是通过禁用滚动来包装它。像这样:

textView.scrollEnabled = NO;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
textView.scrollEnabled = YES;

奇怪的跳跃已经被修复。

以下两种解决方案在iOS 8.0上对我不起作用

textView.scrollEnabled = NO;
[textView.setText: text];
textView.scrollEnabled = YES;

我将一个委托设置到textview以监视滚动事件,并注意到在恢复偏移量的操作之后,偏移量再次重置为0。因此,我改为使用主操作队列,以确保在“重置为0”选项之后执行还原操作

这是我的适用于iOS 8.0的解决方案

CGPoint offset = self.textView.contentOffset;
self.textView.attributedText = replace;
[[NSOperationQueue mainQueue] addOperationWithBlock: ^{
    [self.textView setContentOffset: offset];
}];

此决定适用于iOS 8:

let offset = textView.contentOffset
textView.text = newText
textView.layoutIfNeeded()
textView.setContentOffset(offset, animated: false)

必须准确地调用
setContentOffset:animated:
,因为只有这样才能取消动画
textView.contentOffset=offset
不会取消动画,也不会有帮助。

要编辑UITextView的文本,需要更新其文本存储字段:

[_textView.textStorage beginEditing];

NSRange replace = NSMakeRange(10, 2); //enter your editing range
[_textView.textStorage replaceCharactersInRange:replace withString:@"ha ha$ "];

//if you want to edit the attributes
NSRange attributeRange = NSMakeRange(10, 5); //enter your editing attribute range
[_textView.textStorage addAttribute:NSBackgroundColorAttributeName value:[UIColor greenColor] range:attributeRange];

[_textView.textStorage endEditing];

祝你好运

我在IOS9中遇到了类似的问题,如果不是相同的话。将某些文本的特征更改为(例如)粗体会导致视图将所选内容滚动到看不见的位置。我通过在setSelectedRange之后添加对scrollRangeToVisible的调用对其进行排序:

    [self setSelectedRange:range];
    [self scrollRangeToVisible:range];

最后试试这个,在iOS 10上检查

let offset = textView.contentOffset
textView.attributedText = newValue
OperationQueue.main.addOperation {
    self.textView.setContentOffset(offset, animated: false)
}

谢谢你的意见。在这个委托方法中应该发生什么?此时是否应该进行contentOffset和selectedRange的最终重置?(此解决方案是在此处建议的所有其他解决方案都不适用于我之后提出的)这不值得投否决票。有时像这样的滚动问题必须在运行循环中解决。我知道可能有更优雅的解决方案,但这是有效的,是无害的。谢谢你的建议,我会试试看!它不是私有API,根据我的示例,您可以重写UITextView并自己实现该行为。Meir Assayag的答案在我的情况下不起作用,在iOS 3.2上也不起作用。在iOS 7上,这不起作用,因为contentOffset方法将在显示时再次调用。我正在寻找一个有效的解决方案。此解决方案(在设置所选范围后设置scrollEnabled,而不是之前)修复了我在设置UITextView的attributedText属性时遇到的“跳转文本”问题!Thanksself.contentOffset对我来说总是0,0(该子类在防止iOS 7下滚动方面没有任何效果)。因此,在模拟器中测试它时,它修复了我的问题,但在我的设备上运行它时没有修复该问题。这让我相信这仍然是一种比赛状态。我正在考虑将uitextview子类化,并覆盖layoutsubviews方法,使其在启用锁定属性时不运行。在iOS 8上,在
textdicchange:
中设置
textView.scrollEnabled=NO
,似乎会永远禁用滚动。然而,在这个操作系统上,只要在
viewDidLoad
期间切换
scrolldenabled
一次就足够了,即将其设置为
NO
,然后直接返回到
YES
即可完美工作,没有明显的跳转,而且非常简单!我不知道我怎么会错过这个!
let offset = textView.contentOffset
textView.attributedText = newValue
OperationQueue.main.addOperation {
    self.textView.setContentOffset(offset, animated: false)
}