NSTextView — Xcode Mac OS

Как очистить NSTextView или целиком заменить его содержимое

NSTextView наследует всю работу с текстом от класса NSText, который имеет методы string/setString, работающие с его текстом.

// Заменить все содержимое в NSTextView
textView.string = @"New String";
// Или
[textView setString:@"New String"];

Прим. Чтобы очистить все содержимое NSTextView, достаточно передать пустую строку.

Как выключить Smart Quotes, Smart Dashes, Smart Links и т.д.

/*
 Отключаем ссылки, телефоны, смарт кавычки,
 орфографию и т.д
 */
textView.automaticQuoteSubstitutionEnabled = NO;
textView.automaticDashSubstitutionEnabled = NO;
textView.automaticSpellingCorrectionEnabled = NO;
textView.automaticLinkDetectionEnabled = NO;
textView.grammarCheckingEnabled = NO;
textView.automaticDataDetectionEnabled = NO;
textView.automaticTextReplacementEnabled = NO;
textView.smartInsertDeleteEnabled = NO;

 

 

Как выключить word-wrap и включить горизонтальную прокрутку

/*
Правильное включение горизонтальной прокрутки и disable word-wrap
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextUILayer/Tasks/TextInScrollView.html
*/
[[textView enclosingScrollView] setHasHorizontalScroller:YES];
[textView setHorizontallyResizable:YES];
[textView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
// Но вот этого пункта там нет и получается бяка, текст обрезается.
[textView setMaxSize:CGSizeMake(FLT_MAX, FLT_MAX)]; // Добавить!
[[textView textContainer] setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[[textView textContainer] setWidthTracksTextView:NO];

 

Как получить NSScroll текущего NSTextView

// Назначить scrollView явно заранее.
IBOutlet NSScrollView *scrollView;

// Получить ближайшее представление прокрутки предка, содержащее текущее представление.
NSScrollView *scrollView = [textView enclosingScrollView];
// Тоже самое, но иначе.
NSScrollView *scrollView = (NSScrollView *)textView.superview.superview;

 

 

Как получить текущую позицию курсора

Objective-C

// Получаем текущее состояние позиции курсора и длины выделенного текста.
NSRange rangeCursorBackup = textView.selectedRange;

// NSInteger (location) V1.
NSInteger locationCursorBackup = textView.selectedRange.location;

// Получаем текущую позицию курсора (location) V2.
// NSText может иметь более одного выбора.
NSInteger insertionPoint = [[[myTextView selectedRanges] objectAtIndex:0] rangeValue].location;

Swift 4

let insertionPointIndex = textView.selectedRanges.first?.rangeValue.location

AppleScriptObjC

set txtRange to obj's selectedRanges's objectAtIndex:0
set txtRangeLocation to txtRange's rangeValue()'s location()
set txtRangeLength to txtRange's rangeValue()'s |length|()

Как прокрутить документ

// Прокрутить документ в начало. (Курсор при этом не изменяется)
[textView scrollRangeToVisible:NSMakeRange(0, 0)];

// Прокрутить textView в конец документа. (Курсор при этом не изменяется)
[textView scrollToEndOfDocument:nil];

// Запоминаем текущее положение курсора (или вносим новое значение).
NSInteger insertionPointCursor = textView.selectedRange.location;

// Прокрутить документ до курсора (обычно середина view по вертикали).
[textView scrollRangeToVisible:NSMakeRange(insertionPointCursor, 0)];

// Прокрутка на самый верх view до курсора.
// Удобнее в категорию NSTextView добавить метод. (self = NSTextView)
// Это только прокрутка, позиция курсора тут не меняется.
- (void)scrollContentToTopCursor:(NSInteger)posCursor
{
    NSRange caretRange = NSMakeRange(posCursor, 0);
    NSLayoutManager* laym = [self layoutManager];
    NSRange glyphRange = [laym glyphRangeForCharacterRange:caretRange actualCharacterRange:nil];
    NSRect glyphRect = [laym boundingRectForGlyphRange:glyphRange inTextContainer:[self textContainer]];
    [self scrollRectToVisible:glyphRect];
}

 

Как установить курсор в определенную позицию

// Первый параметр, это позиция символа для установки курсора.
// Второй параметр, это длина, т.е. сколько символов нужно выделить.
// Точка вставки - это выделение пустой длины. Соответственно, чтобы просто 
// установить курсор в нужную позицию, второй параметр устанавливаем в ноль.

// В начало
[textView setSelectedRange:NSMakeRange(0, 0)];

// В конец
[textView setSelectedRange:NSMakeRange(textView.string.length, 0)];

// На пятый символ
[textView setSelectedRange:NSMakeRange(4, 0)];

Как программно заменить или вписать (вставить) текст

// Было String: abcdef

// Result: a++bcdef
[textView insertText:@"++" replacementRange:NSMakeRange(1, 0)];

// Result: a++def
[textView insertText:@"++" replacementRange:NSMakeRange(1, 2)];

// Result: a++f
[textView insertText:@"++" replacementRange:NSMakeRange(1, 4)];

Если в replacementRange указать номер несуществующей позиций (locate) больше нуля, например больше, чем на самом деле есть символов, то никакого исключения и краша не возникнет, просто новые данные добавятся в самый конец. Но значение меньше нуля указывать нельзя, будет краш.

Метод экземпляра InsertText:replacementRange: доступен с macOS 10.5+. Подробнее здесь 

Как получить выделенный текст

// Одно выделение
NSString *string = [[textView string] substringWithRange:[textView selectedRange]];

// Если мультивыделение
NSArray *ranges = [textView selectedRanges];
for (int i = 0; i < ranges.count; i++) {
    NSValue *rangeItem = [ranges objectAtIndex:i];
    NSRange theRange = [rangeItem rangeValue];
    NSString *string = [[textView string] substringWithRange:theRange];
    NSLog(@"string %d: %@", i, string);
}

 

Как проверить, есть ли выделение в textView?

// В NSTextView может быть множественный выбор, методы
// selectedRanges возвращают массив всех выборок.

// Example 1
if (textView.selectedRanges.count > 0) {
    NSLog(@"Some text is selected!");
}

// Example 2
NSArray *selections = textView.selectedRanges;

BOOL hasSelections = selections.count > 1;
BOOL hasSelection = (selections.count == 1 && allSelections[0].length != 0);

 

Как изменить цвет текста указанного участка

// Покрасим в красный цвет 2 символа, которые идут с позиции 3.
[textView setTextColor:[NSColor redColor] range:NSMakeRange(3, 2)];

Здесь в range нельзя указывать номер несуществующей позиций (locate) как больше нуля, так и больше, чем на самом деле есть символов. Тоже самое относится и к параметру длина (length). Иначе будет краш приложения.

Как сохранить данные из NSTextView в файл в кодировке utf-8

NSString *string = [[textView textStorage] string];
NSError *error = nil;

// Сохранить строку в файл в кодировке utf-8
if (![string writeToFile:@"/Users/admin/Desktop/mydir/test_utf8.txt" atomically:YES encoding:NSUTF8StringEncoding error:&error]) {
  NSLog(@"Cannot write file: %@", error);
}

Как сохранить данные из NSTextView в файл в кодировке unicode

NSString *string = [[textView textStorage] string];
NSError *error = nil;

// Сохранить строку в файл в кодировке unicode
if (![string writeToFile:@"/Users/admin/Desktop/mydir/test_uni.txt" atomically:YES encoding:NSUnicodeStringEncoding error:&error]) {
  NSLog(@"Cannot write file: %@", error);
}

Как загрузить RTF текст из файла в textView

// Загрузить rtf текст из файла в textView
[textView readRTFDFromFile:@"/Users/admin/Desktop/mydir/test.rtf"];

Как сохранить RTF текст в файл из textView

// Сохранить rtf текст в файл из textView
NSRange allTextRange = NSMakeRange(0, [[textView textStorage] length]);
[[textView RTFFromRange: allTextRange] writeToFile: @"/Users/admin/Desktop/mydir/test.rtf" atomically:YES];

Как узнать, что курсор мыши находится над NSTextView

Чтобы отследить заход курсора мыши над текстовым редактором или его выход, необходимо создать подкласс для NSTextView и реализовать там следующие методы: mouseEntered:theEvent, mouseExited:theEvent, viewWillMoveToWindow:newWindow. Но чтобы реализовать методы mouseEntered: и mouseExited:, нам необходимо использовать class NSTrackingArea.

//------------------------------------------------------------------------//
// Курсор мыши вошел в объект
//------------------------------------------------------------------------//

-(void)mouseEntered:(NSEvent *)theEvent {
    NSLog(@"mouseEntered");
}

//------------------------------------------------------------------------//
// Курсор мыши вышел из объекта
//------------------------------------------------------------------------//

-(void)mouseExited:(NSEvent *)theEvent {
    NSLog(@"mouseExited");
}

//------------------------------------------------------------------------//
// Если мы хотим использовать mouseEntered: и mouseExited: нам нужно
// использовать class NSTrackingArea.
//------------------------------------------------------------------------//

- (void) viewWillMoveToWindow:(NSWindow *)newWindow {
    // Установить зону отслеживания объекта, когда View будет добавлен в Window.
    NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
    [self addTrackingArea:trackingArea];
} 

Как управлять контекстным меню для NSTextView, смотрите здесь.

Контекстное меню, это объект NSMenu. По указанной ссылке вы можете узнать о нем более подробно.

 



Указаны примеры для языка Objective-C

 

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *