Skip to content

Commit

Permalink
Implemented highlighting view.
Browse files Browse the repository at this point in the history
  • Loading branch information
macguru committed Sep 29, 2013
1 parent 860bad1 commit 57f34d9
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 15 deletions.
22 changes: 22 additions & 0 deletions TextKitDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
5041485617F80E5C008D88C6 /* TextKitDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041485517F80E5C008D88C6 /* TextKitDemoTests.m */; };
5041486817F8112A008D88C6 /* TKDConfigurationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041486417F8112A008D88C6 /* TKDConfigurationViewController.m */; };
5041486917F8112A008D88C6 /* TKDHighlightingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041486717F8112A008D88C6 /* TKDHighlightingViewController.m */; };
5041486C17F81F2F008D88C6 /* TKDHighlightingTextStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041486B17F81F2F008D88C6 /* TKDHighlightingTextStorage.m */; };
5041486F17F821E5008D88C6 /* lorem.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5041486E17F821E5008D88C6 /* lorem.txt */; };
5041487117F82265008D88C6 /* iText.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5041487017F82265008D88C6 /* iText.txt */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -59,6 +62,10 @@
5041486417F8112A008D88C6 /* TKDConfigurationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKDConfigurationViewController.m; sourceTree = "<group>"; };
5041486617F8112A008D88C6 /* TKDHighlightingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKDHighlightingViewController.h; sourceTree = "<group>"; };
5041486717F8112A008D88C6 /* TKDHighlightingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKDHighlightingViewController.m; sourceTree = "<group>"; };
5041486A17F81F2F008D88C6 /* TKDHighlightingTextStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKDHighlightingTextStorage.h; sourceTree = "<group>"; };
5041486B17F81F2F008D88C6 /* TKDHighlightingTextStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKDHighlightingTextStorage.m; sourceTree = "<group>"; };
5041486E17F821E5008D88C6 /* lorem.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = lorem.txt; sourceTree = "<group>"; };
5041487017F82265008D88C6 /* iText.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = iText.txt; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -126,6 +133,7 @@
5041483F17F80E5C008D88C6 /* TKDSecondViewController.h */,
5041484017F80E5C008D88C6 /* TKDSecondViewController.m */,
5041484217F80E5C008D88C6 /* Images.xcassets */,
5041486D17F821CC008D88C6 /* Texts */,
5041482E17F80E5C008D88C6 /* Supporting Files */,
);
path = TextKitDemo;
Expand Down Expand Up @@ -174,10 +182,21 @@
children = (
5041486617F8112A008D88C6 /* TKDHighlightingViewController.h */,
5041486717F8112A008D88C6 /* TKDHighlightingViewController.m */,
5041486A17F81F2F008D88C6 /* TKDHighlightingTextStorage.h */,
5041486B17F81F2F008D88C6 /* TKDHighlightingTextStorage.m */,
);
path = Highlighting;
sourceTree = "<group>";
};
5041486D17F821CC008D88C6 /* Texts */ = {
isa = PBXGroup;
children = (
5041486E17F821E5008D88C6 /* lorem.txt */,
5041487017F82265008D88C6 /* iText.txt */,
);
path = Texts;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -257,6 +276,8 @@
files = (
5041484317F80E5C008D88C6 /* Images.xcassets in Resources */,
5041483217F80E5C008D88C6 /* InfoPlist.strings in Resources */,
5041487117F82265008D88C6 /* iText.txt in Resources */,
5041486F17F821E5008D88C6 /* lorem.txt in Resources */,
5041483B17F80E5C008D88C6 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -276,6 +297,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5041486C17F81F2F008D88C6 /* TKDHighlightingTextStorage.m in Sources */,
5041486817F8112A008D88C6 /* TKDConfigurationViewController.m in Sources */,
5041483817F80E5C008D88C6 /* TKDAppDelegate.m in Sources */,
5041486917F8112A008D88C6 /* TKDHighlightingViewController.m in Sources */,
Expand Down
12 changes: 6 additions & 6 deletions TextKitDemo/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,20 @@
<rect key="frame" x="20" y="64" width="280" height="214"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.99743288622493753" green="1" blue="0.91486229109652462" alpha="1" colorSpace="calibratedRGB"/>
<string key="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus magna dolor, volutpat a ipsum et, porttitor molestie justo. Vestibulum sed augue malesuada, congue magna sed, fringilla ligula. Sed aliquet porta vestibulum. Phasellus gravida elit ut ligula vulputate fringilla. Pellentesque sit amet dolor pulvinar, dictum eros non, suscipit purus. Aenean metus mi, sodales ut augue in, varius sagittis mi. Sed semper est vel placerat scelerisque. In hac habitasse platea dictumst. Mauris auctor accumsan sagittis. Etiam interdum ante in condimentum iaculis. Aliquam porta facilisis lorem in auctor. Nullam non tortor eget urna iaculis faucibus et in augue. Integer nec libero placerat magna rhoncus ultrices eu venenatis massa. Suspendisse ullamcorper molestie lorem eget consequat.

Duis viverra, nibh vitae dapibus aliquet, dui sapien tristique enim, sit amet lacinia justo ligula sit amet arcu. Donec consequat, sapien nec varius placerat, lectus ante sollicitudin lorem, mattis dictum nisl diam id massa. Curabitur mattis turpis ac est cursus sagittis. Nunc in mattis mi, eu aliquet magna. Suspendisse arcu dolor, tincidunt nec eros in, dapibus auctor risus. Curabitur auctor sit amet eros sit amet imperdiet. Etiam et eros tempus, posuere justo ut, ultrices risus. Cras fringilla risus sapien, sit amet congue mauris fringilla quis. Mauris molestie tincidunt iaculis. Mauris nunc ante, faucibus et eros sed, imperdiet congue justo. Suspendisse euismod rhoncus sollicitudin. Maecenas non pretium nulla.</string>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="p6y-UU-k5s">
<rect key="frame" x="20" y="286" width="139" height="213"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.94144815948450833" green="0.97199554947534716" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iew-4U-Oam">
<rect key="frame" x="161" y="286" width="139" height="213"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.94144815948450833" green="0.97199554947534716" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
Expand Down Expand Up @@ -88,8 +83,9 @@ Duis viverra, nibh vitae dapibus aliquet, dui sapien tristique enim, sit amet la
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" userInteractionEnabled="NO" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" delaysContentTouches="NO" canCancelContentTouches="NO" minimumZoomScale="0.0" maximumZoomScale="0.0" bouncesZoom="NO" editable="NO" text="Loaded by the first view controller — an instance of TKDFirstViewController — specified in the app delegate." textAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="tZ3-Hv-Q7E">
<textView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" delaysContentTouches="NO" canCancelContentTouches="NO" minimumZoomScale="0.0" maximumZoomScale="0.0" bouncesZoom="NO" text="Loaded by the first view controller — an instance of TKDFirstViewController — specified in the app delegate." textAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="tZ3-Hv-Q7E">
<rect key="frame" x="20" y="20" width="280" height="479"/>
<color key="backgroundColor" red="1" green="0.90707121920624501" blue="0.92926867484110121" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" size="system"/>
<textInputTraits key="textInputTraits"/>
</textView>
Expand All @@ -103,6 +99,9 @@ Duis viverra, nibh vitae dapibus aliquet, dui sapien tristique enim, sit amet la
</constraints>
</view>
<tabBarItem key="tabBarItem" title="Highlighting" image="first" id="u1e-5L-l1D"/>
<connections>
<outlet property="textView" destination="tZ3-Hv-Q7E" id="eUE-j0-wMy"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Qh2-T1-AhA" sceneMemberID="firstResponder"/>
</objects>
Expand Down Expand Up @@ -191,6 +190,7 @@ Duis viverra, nibh vitae dapibus aliquet, dui sapien tristique enim, sit amet la
</scene>
</scenes>
<resources>
<image name="first" width="30" height="30"/>
<image name="first" width="30" height="30"/>
<image name="second" width="30" height="30"/>
</resources>
Expand Down
3 changes: 2 additions & 1 deletion TextKitDemo/Configuration/TKDConfigurationViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ - (void)viewDidLoad
{
[super viewDidLoad];

// Take text storage from single view
// Load text
NSTextStorage *singleTextStorage = self.singleTextView.textStorage;
[singleTextStorage replaceCharactersInRange:NSMakeRange(0, 0) withString:[NSString stringWithContentsOfURL:[NSBundle.mainBundle URLForResource:@"lorem" withExtension:@"txt"] usedEncoding:NULL error:NULL]];


// Connect first layout manager to the same text storage
Expand Down
13 changes: 13 additions & 0 deletions TextKitDemo/Highlighting/TKDHighlightingTextStorage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// TKDHighlightingTextStorage.h
// TextKitDemo
//
// Created by Max Seelemann on 29.09.13.
// Copyright (c) 2013 Max Seelemann. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface TKDHighlightingTextStorage : NSTextStorage

@end
84 changes: 84 additions & 0 deletions TextKitDemo/Highlighting/TKDHighlightingTextStorage.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//
// TKDHighlightingTextStorage.m
// TextKitDemo
//
// Created by Max Seelemann on 29.09.13.
// Copyright (c) 2013 Max Seelemann. All rights reserved.
//

#import "TKDHighlightingTextStorage.h"


@implementation TKDHighlightingTextStorage
{
NSTextStorage *_imp;
}

- (id)init
{
self = [super init];

if (self) {
_imp = [NSTextStorage new];
}

return self;
}


#pragma mark - Reading Text

- (NSString *)string
{
return _imp.string;
}

- (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range
{
return [_imp attributesAtIndex:location effectiveRange:range];
}


#pragma mark - Text Editing

- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str
{
[_imp replaceCharactersInRange:range withString:str];
[self edited:NSTextStorageEditedCharacters range:range changeInLength:(NSInteger)str.length - (NSInteger)range.length];
}

- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range
{
[_imp setAttributes:attrs range:range];
[self edited:NSTextStorageEditedAttributes range:range changeInLength:0];
}


#pragma mark - Syntax highlighting

- (void)processEditing
{
[super processEditing];


// Regular expression matching all iWords -- first character i, followed by an uppercase alphabetic character, followed by at least one other character. Matches words like iPod, iPhone, etc.
static NSRegularExpression *iExpression;
iExpression = iExpression ?: [NSRegularExpression regularExpressionWithPattern:@"i[\\p{Alphabetic}&&\\p{Uppercase}][\\p{Alphabetic}]+" options:0 error:NULL];


// Clear text color of edited range
NSRange paragaphRange = [self.string paragraphRangeForRange: self.editedRange];
[self removeAttribute:NSForegroundColorAttributeName range:paragaphRange];

// Find all iWords in range
[iExpression enumerateMatchesInString:self.string options:0 range:paragaphRange usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
// Add red highlight color
[self addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:result.range];
}];


// Note that we did change text attributes
[self edited:NSTextStorageEditedAttributes range:paragaphRange changeInLength:0];
}

@end
1 change: 1 addition & 0 deletions TextKitDemo/Highlighting/TKDHighlightingViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
#import <UIKit/UIKit.h>

@interface TKDHighlightingViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITextView *textView;

@end
20 changes: 12 additions & 8 deletions TextKitDemo/Highlighting/TKDHighlightingViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,26 @@

#import "TKDHighlightingViewController.h"

@interface TKDHighlightingViewController ()
#import "TKDHighlightingTextStorage.h"

@end

@implementation TKDHighlightingViewController
{
// Text storage must be held strongly, only the default storage is retained by the text view.
TKDHighlightingTextStorage *_textStorage;
}


- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
// Replace text storage
_textStorage = [TKDHighlightingTextStorage new];
[_textStorage addLayoutManager: self.textView.layoutManager];

// Load iText
[_textStorage replaceCharactersInRange:NSMakeRange(0, 0) withString:[NSString stringWithContentsOfURL:[NSBundle.mainBundle URLForResource:@"iText" withExtension:@"txt"] usedEncoding:NULL error:NULL]];
}

@end
3 changes: 3 additions & 0 deletions TextKitDemo/Texts/iText.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Lorem iPsum dolor sit amet, consectetur adipiscing iPod. Phasellus magna dolor, volutpat a iPsum et, molestie justo. Vestibulum sed augue malesuada, congue iWork sed, fringilla ligula. Sed aliquet iCloud vestibulum. Phasellus gravida elit ut ligula vulputate fringilla. Pellentesque sit amet dolor pulvinar, dictum eros non, suscipit purus. Aenean metus mi, sodales ut augue in, varius sagittis mi. Sed semper est vel placerat scelerisque. In hac habitasse platea dictumst. Mauris auctor accumsan sagittis. Etiam interdum ante in condimentum iaculis. Aliquam porta facilisis lorem in auctor. Nullam non tortor eget urna iaculis faucibus et in augue. Integer nec libero placerat magna rhoncus ultrices eu venenatis massa. Suspendisse ullamcorper molestie lorem eget consequat.

Duis viverra, nibh vitae dapibus aliquet, dui sapien tristique enim, sit amet lacinia justo ligula sit amet arcu. Donec consequat, sapien nec varius placerat, lectus ante sollicitudin lorem, mattis dictum nisl diam id massa. Curabitur mattis turpis ac est cursus sagittis. Nunc in mattis mi, eu aliquet magna. Suspendisse arcu dolor, tincidunt nec eros in, dapibus auctor risus. Curabitur auctor sit amet eros sit amet imperdiet. Etiam et eros tempus, posuere justo ut, ultrices risus. Cras fringilla risus sapien, sit amet congue mauris fringilla quis. Mauris molestie tincidunt iaculis. Mauris nunc ante, faucibus et eros sed, imperdiet congue justo. Suspendisse euismod rhoncus sollicitudin. Maecenas non pretium nulla.
3 changes: 3 additions & 0 deletions TextKitDemo/Texts/lorem.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus magna dolor, volutpat a ipsum et, porttitor molestie justo. Vestibulum sed augue malesuada, congue magna sed, fringilla ligula. Sed aliquet porta vestibulum. Phasellus gravida elit ut ligula vulputate fringilla. Pellentesque sit amet dolor pulvinar, dictum eros non, suscipit purus. Aenean metus mi, sodales ut augue in, varius sagittis mi. Sed semper est vel placerat scelerisque. In hac habitasse platea dictumst. Mauris auctor accumsan sagittis. Etiam interdum ante in condimentum iaculis. Aliquam porta facilisis lorem in auctor. Nullam non tortor eget urna iaculis faucibus et in augue. Integer nec libero placerat magna rhoncus ultrices eu venenatis massa. Suspendisse ullamcorper molestie lorem eget consequat.

Duis viverra, nibh vitae dapibus aliquet, dui sapien tristique enim, sit amet lacinia justo ligula sit amet arcu. Donec consequat, sapien nec varius placerat, lectus ante sollicitudin lorem, mattis dictum nisl diam id massa. Curabitur mattis turpis ac est cursus sagittis. Nunc in mattis mi, eu aliquet magna. Suspendisse arcu dolor, tincidunt nec eros in, dapibus auctor risus. Curabitur auctor sit amet eros sit amet imperdiet. Etiam et eros tempus, posuere justo ut, ultrices risus. Cras fringilla risus sapien, sit amet congue mauris fringilla quis. Mauris molestie tincidunt iaculis. Mauris nunc ante, faucibus et eros sed, imperdiet congue justo. Suspendisse euismod rhoncus sollicitudin. Maecenas non pretium nulla.

0 comments on commit 57f34d9

Please sign in to comment.