NSAttributedString copy/paste on UITextView - uikit

My UITextView has NSAttributedString as it's text. I need to implement copy/paste in UITextView (both from within the same UITextView or from external sources). It seems UIPasteBoard simply copies the text without attributes. What do I need to do to implement custom copy/paste in UITextView that supports copying and pasting NSAttributedString?

Related

NSTextview won't show pop-up menu for Korean text replacements

(Disclaimer -- I don't understand Korean, so I have some test examples that don't make sense but demonstrate the issue.)
I have a heavily customized NSTextView/NSTextStorage to provide syntax highlighting and other behaviors in my app. A Korean user pointed out some difficulties using the macOS text replacement functionality.
The pop-up menu to accept/reject text replacements doesn't appear.
Text replacements of multi-character strings don't work -- it seems to only allow the last character to trigger a replacement.
To test, I configured the following text replacements on my (US English) mac:
해 (created by typing go) is replaced with GO (creative, I know...)
새 (to) is replaced with TO
ㅂㅈ (qw) is replaced with qw
햅ㅈ (goqw) with go qw
I enabled the 2-Set Korean input source (the "Caps Lock to switch" feature is a life saver) (If it matters, I have Font Size 18, Input format Hangul (Hanja), and Delete by Gulja.
I am running 10.12.6 on this machine.
Test environments:
I downloaded Apple's source for TextEdit, compiled, and used that (so that I could confirm TextEdit was compiled using same SDK as my app)
I created a "toy" application that consists of a single window. In the ViewController's viewDidLoad, I use this to replace the contents with a basic NSTextView (without any of my customizations):
- (void)viewDidLoad {
[super viewDidLoad];
NSView * contentView = [self view];
NSRect cFrame = [contentView bounds];
NSView * oldView = [[self.view subviews] firstObject];
[oldView removeFromSuperview];
// Create basic NSTextView with mostly default settings
NSTextView * newView = [[NSTextView alloc] initWithFrame:cFrame];
[newView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
[newView setVerticallyResizable:YES];
[newView setHorizontallyResizable:NO];
// Scrollview for convenience
NSScrollView * scroller = [[NSScrollView alloc] initWithFrame:cFrame];
[scroller setAutoresizingMask:NSViewWidthSizable | NSViewWidthSizable];
[scroller setHasVerticalRuler:YES];
[scroller setUsesPredominantAxisScrolling:YES];
[scroller setHorizontalScrollElasticity:NSScrollElasticityNone];
[scroller setDocumentView:newView];
[self.view addSubview:scroller];
// Do any additional setup after loading the view.
textView = newView;
[textView setRulerVisible:YES];
}
Results:
Using TextEdit, all of the replacements display a pop-up menu allowing me to accept/reject the replacement as I type (Korean as well as my own English text replacements).
Using the toy application, single character replacements are changed automatically, but no pop-up menu is displayed.
The two character replacement is not triggered in the toy app.
Typing quickly in the toy app (with a space after) allows all Korean replacements to happen, but still no pop-up.
English text replacements, including multi-letter words, show the pop-up menu (e.g. mmd -> MultiMarkdown).
Changing the font for the NSTextView doesn't change behavior (e.g. Times is same as AppleMyungjo).
Reviewing the TextEdit code, I was unable to find anything relevant to indicate what I am doing wrong. The fact that pop-ups appear with English replacements but not Korean ones seems odd, especially with an unmodified NSTextView. Using a programmatic NSTextView should exclude me doing something wrong with the Xcode interface builder setup. TextEdit uses programmatic NSTextViews, and I couldn't see anything obvious in their setup that differs meaningfully from mine, but obviously there is something going on.
Any solutions?
Thanks!

Highlight a selection in NSTextField

I want to be able to highlight a portion of text in an NSTextField but I've not been able to Google a way of doing this.
I have defined an NSRange but I cannot find a way of using this range to highlight the text. The only thing I have turned up is textField.selectText but this supposedly highlights the whole field.
I'm using Swift 2.
You may have noticed that an NSTextField only shows a selection range when it has focus, i.e., is the first responder. In this case, editing is handled by an NSTextView called the field editor. So, make sure the field has focus (e.g., by using the makeFirstResponder: method of NSWindow), then use the NSControl method currentEditor to get the field editor, and then you can use the NSText method setSelectedRange:.
ObjC
NSText* fieldEditor = [myField currentEditor];
[fieldEditor setSelectedRange: mySelRange];
Swift
let fieldEditor = textfield.currentEditor()
fieldEditor?.selectedRange = range

How to make textfield with scrolling functionality, Xcode, swift

I have working program with Wrapping Text Fields, and I would like to add vertical scrolling. I have found that there is Text View object in xcode library and it has NSTextView in NSScrollView. The problems came when I simply tried to substitute Text Fields with Text View. First, when I made outlet, this outlet belongs to NSScrollView (no NSTextView), and NSScrollView doesn't have String type, which I need for working code. Second, when I deleted NSScrollView (I don't know if it was right to do this) and typed instead NSTextView in outlet, I could use type string, but code didn't work. What I did wrong, what should I do ?
Add an UITextView
Drag an outlet from it to your class
Make this class implement UITextViewDelegate
In code, set this text views delegate to this class
It is really simple, I'm confused by steps you took to try to get it working.

NSOutlineView with transparent field editor

I'm working with a NSOutlineView located on a HUD panel. I configured it so that it doesn't draw its background. Everything looks fine until I double click to edit a cell.
The field editor draws its background and focus ring which completely ruin the whole user experience.
This is what I'm doing in the subclass of NSTextFieldCell:
- (NSText *)setUpFieldEditorAttributes:(NSText *)textObj
{
NSText *text = [super setUpFieldEditorAttributes:textObj];
[text setDrawsBackground:YES];
[text setBackgroundColor:[NSColor darkGrayColor]];
return text;
}
If I use setDrawsBackground:NO it's completely ignored and I get a white background. My solution is far from being good because I can't touch the alpha component of the color (if I do that, again the field editor will use another color as a background), but at least I don't get a white background.
I'm wondering if there's an actual solution to this problem. Do I have to provide my own field editor? Is it worth it?
What I want is simply a field editor with no background and no focus ring, just the cursor blinking.
Thanks!
The problem is that the white background is drawn by NSTableView when it's sent -editColumn:row:withEvent:select:. It fills the cell's rect with +[NSColor textBackgroundColor].
If there's a public API for overriding the current setting for named colors from the developer colorspace, we could set it inside an override of -editColumn:row:withEvent:select: or the like. I do not recall such an API (pointers are appreciated). ALSO: I've only tested this code on Snow Leopard (even the Leopard SDK addendum below). Verify the code against the actual SDKs and runtime environments you intend to support.
NSTableView has a private accessor it uses for the fill color, but it's a read-only property. No setter, so we can't just change the value on a standard NSTableView. We must subclass it. (Since you want the same behavior in an outlineView and NSOutlineView is already a subclass of NSTableView, we're going to subclass NSOutlineView. But, aside from the superclass, the code is identical.)
#interface ASCOutlineView : NSOutlineView {
}
#end
#implementation ASCOutlineView
- _textBackgroundColor
{
return ([NSColor clearColor]);
}
#end
seems to be all one needs to prevent that glaring white block from ruining your HUD when editing table cells in Snow Leopard.
Apps compiled against the Leopard SDK need a little more support though. Leopard's tableViews may have hard-coded some rendering properties so we need to override a choice method.
NSTextFieldCells are actually wrappers for NSTextViews so they can be used inside controls. They normally share the same textView instance, which is managed by the window (or its subclass, panel, in this case). NSTableView alters the settings of the NSTextFieldCell to conform to system UI settings for editing data. Mostly. The NSTextFieldCell then propagates those settings to the NSTextView. At any point along this pipeline we can override a method or two to alter the values of those properties to match our own UI.
I use -[NSTextFieldCell setDrawsBackground:] because it requires little effort to get correct. It's also important to keep the internal state as consistent with the effect we're hoping to achieve in the event some other object might depend on that state.
#interface ASCTextFieldCell : NSTextFieldCell {
}
#end
#implementation ASCTextFieldCell
- (void)setDrawsBackground: (BOOL)flag
{
[super setDrawsBackground: NO];
}
#end
And preventing the focus ring from appearing while the cell's being edited is a simple matter of changing the setting of its focus ring type. Frustratingly, IB doesn't provide access to this property, so it must be done programmatically:
for(eachColumn in [hudOutlineView tableColumns])
{
columnCell = [[ASCTextFieldCell alloc] initTextCell: #""];
[eachColumn setDataCell: columnCell];
if([columnCell respondsToSelector: #selector(setFocusRingType:)] != NO)
[(NSTextFieldCell *)columnCell setFocusRingType: NSFocusRingTypeNone];
}
It looks like there is other background behind field editor, which is drawn as white.
Probably, NSCell, or background of row, whatever else.

Text formatting in NSTextField

I have a graphics app that uses a NSTextField instance for in-place text editing, this feature was added long time ago and I never had a reason to check it, however, I have recently received a report: text filed doesn't allow text formatting. Format -> Text menu subitems are all disabled, so there is no way to set the paragraph of a text item.
The question: how should I set up the NSTextField to support paragraph editing? I'm sure it did work before since I have some projects with formatted text and NSTextField was there since the app was born. Did I miss something with system/XCode updates?
My NSTextField is multiline, editable, allowed to edit text attributes.
If someone will face this in the future, I can describe the problem in details:
NSTextView refuses to apply formatting if there is no ruler used (with recent OS update, I suppose)
NSTextField itself does no text editing, it uses shared NSTextView instance driven by the owning NSWindow
Default text editor from the NSWindow doesn't use rulers.
This results disabled text formatting when using NSTextField.
Solution is to subclass the NSWindow:
#implementation MyWindow
- (NSText *)fieldEditor:(BOOL)createWhenNeeded forObject:(id)anObject
{
NSText* text = [super fieldEditor:createWhenNeeded forObject:anObject];
if ([text isKindOfClass:[NSTextView class]])
[(NSTextView *)text setUsesRuler:YES];
return text;
}
#end
And voila, formatting is back.

Resources