NSTextFinder Class Reference

Inherits from
Conforms to
Framework
/System/Library/Frameworks/AppKit.framework
Availability
Available in OS X v10.7 and later.
Declared in
NSTextFinder.h

Overview

The NSTextFinder class provides an optional search and replace find-bar interface inside a view, usually a scroll view.

The class serves as a controller for the standard Cocoa find bar. The NSTextFinder class interacts heavily with a client object which supports the NSTextFinderClient protocol. The client object provides access to the content being searched and provides visual feedback for a search operation.

All menu items related to finding (Find…, Find Next, Find Previous, Use Selection for Find, etc.) should have the same action, performTextFinderAction:, which gets sent down the responder chain in the standard method.

Implementing a Find Bar

A responder of performTextFinderAction: is responsible for creating and owning an instance of NSTextFinder. Before any other messages are sent to the NSTextFinder, you should set its client property to an object which implements the NSTextFinderClient protocol.

Each user interface item used for finding has a different tag value , which corresponds to the appropriate value in “NSTextFinderAction.” Upon receipt of the performTextFinderAction: message, the responder should call the following on its NSTextFinder instance:

- (void)performAction:(NSTextFinderAction)action;

This method will determine the desired action from the tag and make various callbacks to client to perform that action. These callbacks are defined in the NSTextFinderClient protocol.

Validation occurs by a similar pattern. The responder should implement validateUserInterfaceItem: and, when the item's action is the performTextFinderAction: method, it should pass the item's tag to the following method and return the result:

- (BOOL)validateAction:(NSTextFinderAction)action;

This method will invoke the required client methods to determine what the appropriate response should be. These callbacks are also defined in the NSTextFinderClient protocol.

When an action is performed, the text finder will ask its client for the string to search. There are two ways the client can provide this string. It can either implement the string method, and simply return an NSString instance, or it can implement the following methods: stringAtIndex:effectiveRange:endsWithSearchBoundary: and stringLength.

These methods make it possible to use the text finder with data that cannot be easily or efficiently flattened into a single string. In the first method, the client should return the string which contains the character at the given index in as conceptual concatenation of all strings that are to be searched.

For example, if a client had the strings “The quick”, “brown fox” , “jumped over the lazy”, and “dog”, and a NSTextFinder instance requests the string at index 18, then the client should return "brown fox”. If all the strings were concatenated together would be the ‘x’ in "fox". Additionally, the client should return, by-reference through the outRange parameter, the effective range of the string that is returned. In this example, the range of “brown fox” is {9, 10}, because, in the imagined concatenation, the substring starts at index 9 and is 10 characters long.

In some cases, it is not desirable for a match to be found which overlaps multiple strings returned by the stringAtIndex:effectiveRange:endsWithSearchBoundary: method. For example, suppose a client has a list of names like “John Doe”, and “Jane Doe”, etc. Normally, if the string is concatenated together like so: "John Doe Jane Doe", then a search for "Doe Jane" would succeed. To prevent this often undesirable behavior, the client should return YES, by-reference, through the outFlag parameter, when returning each individual string. This indicates that there is a boundary between the current string and the next string that should not be crossed when searching for a match.

One of the two approaches (implementing the string method the stringAtIndex:effectiveRange:endsWithSearchBoundary: and stringLength methods) must be implemented by the client or the NSTextFinder instance will not function. If all three methods are implemented, stringAtIndex:effectiveRange:endsWithSearchBoundary: will be used by default.

The text finder may require additional information from the client object to perform an action, or it may require the client to perform some parts of the action on its behalf. The methods and properties described in “Text Finder Client Implementation Requirements” describes the hooks the text finder requires for each of the actions it supports. If the client does not implement one of these methods or properties, then the action that requires it will be disabled.

Text Finder Client Implementation Requirements

The text finder’s client may implement the following properties for by the validateAction: method: isSelectable, allowsMultipleSelection, and editable. If any of these properties is not implemented, a value of YES is assumed. Returning NO from any of these methods will disable the actions that require them. For more information about these properties see NSTextFinderClient Protocol Reference.

The following implementation’s are required by the text client to support the specified actions:

Incremental Search Support

A common feature used in conjunction with the find bar is incremental search. This feature allows users to find matches immediately as they are typing. In OS X v10.7, the text finder provides this feature for its clients with minimal additional API.

Incremental searching can be enabled by setting the incrementalSearchingEnabled property YES. This property alone is sufficient to start searching incrementally.

For improved responsiveness, when a document is sufficiently long, the text finder will search the document in the background. To ensure thread-safety, a client using incremental search must call the noteClientStringWillChange method before any changes are made to the string provided to the text finder.

During incremental search, all visible matches are highlighted. If the client object that conforms to the NSTextFinderClient protocol implements the read-only visibleCharacterRanges property, then by default a gray overlay will appear over your find bar container’s content view with transparent areas for each match. This view should be a superview of all subviews reported by the text finder client. The NSScrollView class already implements this property, so you only need to implement this property when using a different container class.

Finally, this mode also requires the same two NSTextFinderClient protocol methods that are used to display the find indicator: contentViewAtIndex:effectiveCharacterRange: and rectsForCharacterRange: be implemented. However, the implementation of these methods is identical for both purposes, so no additional work is required to support incremental search.

Replacing Text

The text replacement methods:shouldReplaceCharactersInRanges:withStrings:, replaceCharactersInRange:withString:, and didReplaceCharacters are used by the replace, replace all, replace all in section, and replace and find actions.

Before a replace operation is performed, the NSTextFinder instance calls the client object’s shouldReplaceCharactersInRanges:withStrings: method to determine if a replacement should take place. If it returns NO, then the characters in the given ranges will not be replaced. If the method returns YES, or is not implemented, then the second method, replaceCharactersInRange:withString:, instructing the client to carry out the replacement. Finally, didReplaceCharacters, if implemented, is invoked to indicate that the replacement was completed.

For replace all actions, these methods will be called multiple times, starting from the last match and moving toward the first, in order to preserve the indexes of the matches which precede the current one.

The Text Finder Container

In order to display the find bar, a container for the find bar must be specified. The container is an object that conforms to the NSTextFinderBarContainer protocol. You specify a find bar container using the following NSTextFinder class’s findBarContainer property.

When a new NSTextFinder instance is created and instructed to display the find bar, it will create a view for the find bar and assign that to the container via the NSTextFinderBarContainer class’s findBarView property. The container then owns that view and should release it when the container is deallocated. The container should make the find bar visible when the container’s findBarVisible property is set to YES. The container should implement the findBarViewDidChangeHeight method so it can reposition the find bar when its height changes, usually in response to user action.

Implementation by Application Kit Classes

Two Application Kit classes already provide support for the NSTextFinder class, including: the NSScrollView and NSTextView classes.

Scroll View Support for the Find Bar

In OS X v10.7, the NSScrollView class conforms to NSTextFinderBarContainer protocol in order to support the find bar for any document view searched by the find bar. The find bar can be positioned either above or below the document view by assigning one of the values of the NSScrollViewFindBarPosition constants declared in NSScrollView to the NSScrollView class’s setFindBarPosition: method.

Text View Support for the Find Bar

The NSTextView class also now supports the find bar. The find bar can be enabled or disabled on a text view with the following methods: setUsesFindBar: and usesFindbar.

Since OS X v10.5, the NSTextView class has used an animated find indicator to give feedback to the user about a successful find action. The find indicator could be activated manually on an text view via the showFindIndicatorForRange: method.

To provide this functionality for text finder clients in OS X v10.7, the NSTextFinder class shows the find indicator at the appropriate time automatically when performing a find. However, text finder needs to know where to show the indicator and it needs assistance in drawing the text contents of the find indicator. During incremental search the NSTextFinder class needs also to know the locations of all the visible matches so it can highlight them as well. The following method additions to the NSTextFinderClient protocol provide these capabilities: contentViewAtIndex:effectiveCharacterRange: and rectsForCharacterRange:.

The contentViewAtIndex:effectiveCharacterRange: method is called to determine what view the content is displayed in, that is, over which the find indicator will be displayed. Since content may potentially be spread over multiple views (like the NSLayoutManager class , which supports multiple text views), the method asks for the view at a given index, and the full range of the string that is contained by that view.

In the rectsForCharacterRange: method, the client should determine and return the rectangles in which the content with the given range is displayed in its contentView. The given range is guaranteed not to span multiple content views. The returned rectangles tell the NSTextFinder instance where the matched range is found, so it can show the find indicator there.

The NSTextFinder and NSView classes will handle the find indicator correctly when the contentView is resized, moved, or removed from the view hierarchy. If your content view's scrolling is done by an NSScrollView, the find indicator will also be handled for you during scrolling. Beyond these cases, there may be some circumstances where the find indicator should be immediately cancelled and hidden, such as when the view's content or selection is changed without the knowledge of the text finder . The find indicator can be cancelled using the NSTextFinder cancelFindIndicator method. If your document is not scrolled by NSScrollView, then you should set the findIndicatorNeedsUpdate property to YES.

NSTextFinder is responsible for drawing the yellow find indicator background bezel, but the view must provide the contents. NSTextFinder will setup a drawing context and cause the contentView to draw into it. There are two ways this can happen.

  • The NSTextFinder instance will invoke the client object’s drawCharactersInRange:forContentView: method, if implemented. The client should then draw the requested characters (or ask the containing view to draw the characters, which is provided as a convenience) at the origin of the current context. If the requested character range partially intersects a glyph range, the client may draw the entire glyph, if necessary for performance.

  • If drawCharactersInRange:forContentView: method is not implemented, then the NSTextFinder instance will use the normal view drawing mechanisms. The contentView does not need take any additional action to make this happen

In OS X v10.7, the NSTextView class also provides incremental search support. It is disabled by default, but can be enabled by setting the incrementalSearchingEnabled property to YES. Also, since incremental searching requires the find bar, usesFindBar must be set to YES for incremental searching to be occur.

Tasks

Initializing the Text Finder

Validating and Performing Text Finding

Getting the Find Bar Container

Getting and Setting the Find Bar Client

Noting Changes in the Original Content

Updating the Find Indicator

Incremental Search Configuration

Properties

client

The object that provides the target search string, find bar location, and feedback methods.

@property(assign) IBOutlet id <NSTextFinderClient> client
Discussion

The NSTextFinder instance class must be associated with a client object that implements the NSTextFinderClient protocol in order to function. The client is responsible for providing the string to be searched, the location for the find bar, and the methods which control feedback to the user about the search results.

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

findBarContainer

Specifies the find bar container.

@property(assign) IBOutlet id <NSTextFinderBarContainer> findBarContainer
Discussion

This property must be set to support the find bar.

When the find bar is to be shown, NSTextFinder invokes showFindBarView: on the findBarContainer object, passing the view for the find bar, which it should display somewhere that is associated appropriately with the content being searched.

The NSScrollView class implements NSTextFinderBarContainer protocol and is the correct place to display the find bar in most circumstances. The container may freely modify the find bar view's width and origin, but not its height.

If this property is not set, then the find bar cannot be shown.

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

findIndicatorNeedsUpdate

Invoke to specify that the find indicator needs updating when not contained within a scroll view.

@property BOOL findIndicatorNeedsUpdate
Discussion

If the client object’s document is not scrolled by an instance of NSScrollView, then set this property to YES when scrolling occurs to cause the find indicator to be updated appropriately.

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

incrementalMatchRanges

Array of incremental search matches posted on the main queue, which have been found during a background search. (read-only)

@property(readonly) NSArray *incrementalMatchRanges
Discussion

This array is updated periodically on the main queue as the incremental search operation on a background queue finds matches. You can use this property when incrementalSearchingShouldDimContentView is NO to know where to draw highlights for incremental matches.

If no incremental search is active, or there are no matches found, this array will be empty. If an incremental search is currently in progress, but not yet complete, this will return all the ranges found so far.

This array is key-value observing compliant and can be observed to know when to update your highlights. When NSKeyValueObservingOptionNew and NSKeyValueObservingOptionOld options are used, the key-value observing change dictionary provides the ranges (and their indexes) that are added or removed. This allows the invalidation of the minimal region necessary to sync highlights with the receiver’s results.

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

incrementalSearchingEnabled

Determines if incremental searching is enabled.

@property(getter=isIncrementalSearchingEnabled) BOOL incrementalSearchingEnabled
Discussion

If YES, then the find bar will do incremental searches. If it returns NO, then the find bar will behave regularly.

The default value is NO.

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

incrementalSearchingShouldDimContentView

Determines the type of incremental search feedback to be presented

@property BOOL incrementalSearchingShouldDimContentView
Discussion

If YES, then when an incremental search begins, the findBarContainer instance’s parent contentView will be dimmed, except for the locations of the incremental matches. If NO, then the incremental matches will not be highlighted automatically, but you can use incrementalMatchRanges to highlight the matches yourself.

The default value is YES.

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

Class Methods

drawIncrementalMatchHighlightInRect:

Override this method to draw custom highlighting.

+ (void)drawIncrementalMatchHighlightInRect:(NSRect)rect
Parameters
rect

The rectangle that needs to be drawn highlighted in the current coordinate system.

Discussion

If incrementalSearchingShouldDimContentView is NO, it is recommended to highlight incremental matches in your own view. However, some applications may choose to show incremental search values in a different manner.

This method is not recommended to be overridden. The text finder never calls it. The view calls it to get the standard highlight behavior. It is recommended that views use this method do draw the highlight for consistency and to allow Application Kit to tweak the behavior in the future. If the view wants custom drawing, then it should be implemented by the view.

The common usage pattern for this is: draw the background, draw the incremental match highlights for the incrementalMatchRanges, and then draw the text.

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

Instance Methods

cancelFindIndicator

Cancels the find indicator immediately.

- (void)cancelFindIndicator
Discussion

There may be some circumstances where the find indicator should be immediately cancelled or hidden, such as when the view's content or selection is changed without the knowledge of the text finder. This method will immediately cancel the current find indicator.

The NSTextFinder and NSView classes will handle the find indicator correctly when a content view is resized, moved, or removed from the view hierarchy. If your content view's scrolling is done by an NSScrollView, the find indicator will also be handled for you during scrolling.

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

init

Initializes and returns a new NSTextFinder instance.

- (id)init
Return Value

An initialized NSTextFinder instance.

Discussion

This is the designated initiator for the NSTextFinder class.

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

noteClientStringWillChange

Invoke this method when the searched content will change.

- (void)noteClientStringWillChange
Discussion

When incremental search is enabled, this method must be called when it is known that the client's string will be modified. This method must be called before the client string modification takes place.

Availability
  • Available in OS X v10.7 and later.
See Also
Declared In
NSTextFinder.h

performAction:

Performs the specified text finding action.

- (void)performAction:(NSTextFinderAction)op
Parameters
op

The text finding action. See NSTextFinderAction for the possible values.

Discussion

Objects that respond to performTextFinderAction: typically call validateAction: to ensure that the action is valid and then invoke performAction: if validation is successful.

When invoking the validateAction: and performAction: the item or sender’s tag should be passed as the parameter. By convention, the sender parameter for this method will have an “NSTextFinderAction” set as its tag. The responder that receives this method should pass the tag as the action for this method:

- (void)performTextFinderAction:(id)sender {
    [self.textFinder performAction:[sender tag]];
}
Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

validateAction:

Allows validation of the find action before performing.

- (BOOL)validateAction:(NSTextFinderAction)op
Parameters
op

The sender’s tag.

Return Value

YES if the operation is valid; otherwise NO.

Discussion

Responders the NSResponder method performTextFinderAction: should call this method.

This method should be called by an implementation of validateUserInterfaceItem: to properly validate items with an action of performTextFinderAction:. The responder’s validateUserInterfaceItem: or validateMenuItem: implementation should pass the tag as the action for this method..

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

Constants

NSTextFinderAction

These constants specify the user interface item tags that correspond find action. These constants are passed to the performTextFinderAction: method, the responder will call the appropriate method for the tag. That method will, in turn, determine the desired action and invoke the appropriate method in the NSTextFinder object’s NSTextFinderClient protocol.

enum {
   NSTextFinderActionShowFindInterface = 1,
   NSTextFinderActionNextMatch = 2,
   NSTextFinderActionPreviousMatch = 3,
   NSTextFinderActionReplaceAll = 4,
   NSTextFinderActionReplace = 5,
   NSTextFinderActionReplaceAndFind = 6,
   NSTextFinderActionSetSearchString = 7,
   NSTextFinderActionReplaceAllInSelection = 8,
   NSTextFinderActionSelectAll = 9,
   NSTextFinderActionSelectAllInSelection = 10,
   NSTextFinderActionHideFindInterface = 11,
   NSTextFinderActionShowReplaceInterface = 12,
   NSTextFinderActionHideReplaceInterface = 13
};
typedef NSInteger NSTextFinderAction;
Constants
NSTextFinderActionShowFindInterface

The find bar interface is displayed.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionNextMatch

The next match, if any, is displayed.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionPreviousMatch

The previous match, if any, is displayed.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionReplaceAll

All occurrences of the string are replaced.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionReplace

Replaces a single instance of the string.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionReplaceAndFind

Replaces a single instance of the string and searches for the next match.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionSetSearchString

Sets the search string.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionReplaceAllInSelection

Replaces all occurrences of the string within the current selection.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionSelectAll

Selects all matching search strings.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionSelectAllInSelection

Selects all matching search strings within the current selection.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionHideFindInterface

Hides the find bar interface.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionShowReplaceInterface

Displays the find bar interface including the replace functionality.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderActionHideReplaceInterface

Displays the find bar interface including the replace functionality.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h

Text Finder Options For The Pasteboard

The following keys are used for communicating NSTextFinder search options via pasteboard. Use the NSPasteboardTypeTextFinderOptions type

NSString *const NSTextFinderCaseInsensitiveKey;
NSString *const NSTextFinderMatchingTypeKey;
Constants
NSTextFinderCaseInsensitiveKey

The value of this key must be an Boolean NSValue object that indicates if the search should be case sensitive.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderMatchingTypeKey

The value of this key must be an NSNumber containing an NSTextFinderMatchingType value that indicates the type of search matching to perform..

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderMatchingType

The following constants indicate the type of search anchor an action should perform.

enum {
   NSTextFinderMatchingTypeContains = 0,
   NSTextFinderMatchingTypeStartsWith = 1,
   NSTextFinderMatchingTypeFullWord = 2,
   NSTextFinderMatchingTypeEndsWith = 3
};
typedef NSInteger NSTextFinderMatchingType;
Constants
NSTextFinderMatchingTypeContains

The match contains the string.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderMatchingTypeStartsWith

The match begins with the string.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderMatchingTypeFullWord

The match exactly matches the string.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

NSTextFinderMatchingTypeEndsWith

The match ends with the string.

Available in OS X v10.7 and later.

Declared in NSTextFinder.h.

Availability
  • Available in OS X v10.7 and later.
Declared In
NSTextFinder.h