- (NSBezierPath *) makePathFromString: (NSString *) string forFont: (NSFont *) font { NSTextView *textview; textview = [[NSTextView alloc] init]; [textview setString: string]; [textview setFont: font]; NSLayoutManager *layoutManager; layoutManager = [textview layoutManager]; NSRange range; range = [layoutManager glyphRangeForCharacterRange: NSMakeRange (0, [string length]) actualCharacterRange: NULL]; NSGlyph *glyphs; glyphs = (NSGlyph *) malloc (sizeof(NSGlyph) * (range.length * 2)); [layoutManager getGlyphs: glyphs range: range]; NSBezierPath *path; path = [NSBezierPath bezierPath]; [path moveToPoint: NSMakePoint (20.0, 20.0)]; [path appendBezierPathWithGlyphs: glyphs count: range.length inFont: font]; free (glyphs); [textview release]; return (path); } // makePathFromString
NSRange range; range = NSMakeRange ([[textView string] length], 0); [textView replaceCharactersInRange: range withString: string];And Peter Hosey provided a one-liner that may suit your needs better:
[[[textView textStorage] mutableString] appendString: string];
NSNumberFormatter
, add this method, and hook up the formatter to your text fields.
- (BOOL) isPartialStringValid: (NSString **) partialStringPtr proposedSelectedRange: (NSRangePointer) proposedSelRangePtr originalString: (NSString *) origString originalSelectedRange: (NSRange) origSelRange errorDescription: (NSString **) error { NSCharacterSet *nonDigits; NSRange newStuff; NSString *newStuffString; nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; newStuff = NSMakeRange(origSelRange.location, proposedSelRangePtr->location - origSelRange.location); newStuffString = [*partialStringPtr substringWithRange: newStuff]; if ([newStuffString rangeOfCharacterFromSet: nonDigits options: NSLiteralSearch].location != NSNotFound) { *error = @"Input is not an integer"; return (NO); } else { *error = nil; return (YES); } } // isPartialStringValid
NSRange range; range = NSMakeRange ([[textView string] length], 0); [textView scrollRangeToVisible: range];I've heard that
scrollRangeToVisible
is O(N) for the length of the text. So be on the lookout if you have lots of text involved.
-(NSUInteger) jacWordCount: (NSString *) string { __block NSUInteger wordCount = 0; [string enumerateSubstringsInRange:NSMakeRange(0, string.length) options:NSStringEnumerationByWords usingBlock:^(NSString *character, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { wordCount++; }]; return wordCount; }(Muchos thankos to Jared Crawford for a more modern implementation)
NSAttributedString *string = ...; NSRange totalRange = NSMakeRange (0, string.length); [string enumerateAttributesInRange: totalRange options: 0 usingBlock: ^(NSDictionary *attributes, NSRange range, BOOL *stop) { NSLog (@"range: %@ attributes: %@", NSStringFromRange(range), attributes); }];and if you're in 10.5 or earlier:
- (void) iterateAttributesForString: (NSAttributedString *) string { NSDictionary *attributeDict; NSRange effectiveRange = { 0, 0 }; do { NSRange range; range = NSMakeRange (NSMaxRange(effectiveRange), [string length] - NSMaxRange(effectiveRange)); attributeDict = [string attributesAtIndex: range.location longestEffectiveRange: &effectiveRange inRange: range]; NSLog (@"Range: %@ Attributes: %@", NSStringFromRange(effectiveRange), attributeDict); } while (NSMaxRange(effectiveRange) < [string length]); } // iterateAttributesForString
NSMutableString *mstring = [NSMutableString stringWithString:string]; NSRange wholeShebang = NSMakeRange(0, [mstring length]); [mstring replaceOccurrencesOfString: @" " withString: @"" options: 0 range: wholeShebang]; return [NSString stringWithString: mstring];(this can also be used for generic string manipulations, not just stripping out newlines).
This technique takes half the time (at least) of split/join. But probably not enough to make an impact. In a simple test, split/join took 0.124 seconds to strip 36909 newlines in a 1.5 meg textfile, and 0.071 seconds to do the same.