├── .gitignore ├── LICENSE ├── README.md ├── TextKitDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── max.xcuserdatad │ └── xcschemes │ ├── TextKitDemo.xcscheme │ └── xcschememanagement.plist └── TextKitDemo ├── Base.lproj └── Main.storyboard ├── Configuration ├── TKDConfigurationViewController.h └── TKDConfigurationViewController.m ├── Highlighting ├── TKDHighlightingTextStorage.h ├── TKDHighlightingTextStorage.m ├── TKDHighlightingViewController.h └── TKDHighlightingViewController.m ├── Images.xcassets ├── AppIcon.appiconset │ └── Contents.json ├── LaunchImage.launchimage │ └── Contents.json ├── clip.imageset │ ├── 187-1.png │ ├── 187.png │ └── Contents.json ├── first.imageset │ ├── Contents.json │ ├── first.png │ └── first@2x.png └── second.imageset │ ├── Contents.json │ ├── second.png │ └── second@2x.png ├── Interaction ├── TKDCircleView.h ├── TKDCircleView.m ├── TKDInteractionViewController.h └── TKDInteractionViewController.m ├── Layout ├── TKDLayoutingViewController.h ├── TKDLayoutingViewController.m ├── TKDLinkDetectingTextStorage.h ├── TKDLinkDetectingTextStorage.m ├── TKDOutliningLayoutManager.h └── TKDOutliningLayoutManager.m ├── TKDAppDelegate.h ├── TKDAppDelegate.m ├── TextKitDemo-Info.plist ├── TextKitDemo-Prefix.pch ├── Texts ├── iText.txt ├── layout.txt └── lorem.txt ├── en.lproj └── InfoPlist.strings └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Max Seelemann 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TextKitDemo 2 | =========== 3 | 4 | A little demo application showing off some features of the new **TextKit** classes in iOS 7. Licensed BSD, it is free for everyone to download and modify. Let me know what you think! -------------------------------------------------------------------------------- /TextKitDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5041482817F80E5C008D88C6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5041482717F80E5C008D88C6 /* Foundation.framework */; }; 11 | 5041482A17F80E5C008D88C6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5041482917F80E5C008D88C6 /* CoreGraphics.framework */; }; 12 | 5041482C17F80E5C008D88C6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5041482B17F80E5C008D88C6 /* UIKit.framework */; }; 13 | 5041483217F80E5C008D88C6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5041483017F80E5C008D88C6 /* InfoPlist.strings */; }; 14 | 5041483417F80E5C008D88C6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041483317F80E5C008D88C6 /* main.m */; }; 15 | 5041483817F80E5C008D88C6 /* TKDAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041483717F80E5C008D88C6 /* TKDAppDelegate.m */; }; 16 | 5041483B17F80E5C008D88C6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5041483917F80E5C008D88C6 /* Main.storyboard */; }; 17 | 5041484317F80E5C008D88C6 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5041484217F80E5C008D88C6 /* Images.xcassets */; }; 18 | 5041486817F8112A008D88C6 /* TKDConfigurationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041486417F8112A008D88C6 /* TKDConfigurationViewController.m */; }; 19 | 5041486917F8112A008D88C6 /* TKDHighlightingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041486717F8112A008D88C6 /* TKDHighlightingViewController.m */; }; 20 | 5041486C17F81F2F008D88C6 /* TKDHighlightingTextStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041486B17F81F2F008D88C6 /* TKDHighlightingTextStorage.m */; }; 21 | 5041486F17F821E5008D88C6 /* lorem.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5041486E17F821E5008D88C6 /* lorem.txt */; }; 22 | 5041487117F82265008D88C6 /* iText.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5041487017F82265008D88C6 /* iText.txt */; }; 23 | 5041487517F8418B008D88C6 /* TKDLayoutingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041487417F8418B008D88C6 /* TKDLayoutingViewController.m */; }; 24 | 5041487717F843EA008D88C6 /* layout.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5041487617F843EA008D88C6 /* layout.txt */; }; 25 | 5041487A17F844E5008D88C6 /* TKDLinkDetectingTextStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041487917F844E5008D88C6 /* TKDLinkDetectingTextStorage.m */; }; 26 | 5041487D17F84DB2008D88C6 /* TKDOutliningLayoutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041487C17F84DB2008D88C6 /* TKDOutliningLayoutManager.m */; }; 27 | 5041488117F85464008D88C6 /* TKDInteractionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041488017F85464008D88C6 /* TKDInteractionViewController.m */; }; 28 | 5041488417F854EF008D88C6 /* TKDCircleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5041488317F854EF008D88C6 /* TKDCircleView.m */; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 5041482417F80E5C008D88C6 /* TextKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TextKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | 5041482717F80E5C008D88C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 34 | 5041482917F80E5C008D88C6 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 35 | 5041482B17F80E5C008D88C6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 36 | 5041482F17F80E5C008D88C6 /* TextKitDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TextKitDemo-Info.plist"; sourceTree = ""; }; 37 | 5041483117F80E5C008D88C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 38 | 5041483317F80E5C008D88C6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 39 | 5041483517F80E5C008D88C6 /* TextKitDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TextKitDemo-Prefix.pch"; sourceTree = ""; }; 40 | 5041483617F80E5C008D88C6 /* TKDAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKDAppDelegate.h; sourceTree = ""; }; 41 | 5041483717F80E5C008D88C6 /* TKDAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKDAppDelegate.m; sourceTree = ""; }; 42 | 5041483A17F80E5C008D88C6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 43 | 5041484217F80E5C008D88C6 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 44 | 5041484917F80E5C008D88C6 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 45 | 5041486317F8112A008D88C6 /* TKDConfigurationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKDConfigurationViewController.h; sourceTree = ""; }; 46 | 5041486417F8112A008D88C6 /* TKDConfigurationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKDConfigurationViewController.m; sourceTree = ""; }; 47 | 5041486617F8112A008D88C6 /* TKDHighlightingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKDHighlightingViewController.h; sourceTree = ""; }; 48 | 5041486717F8112A008D88C6 /* TKDHighlightingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKDHighlightingViewController.m; sourceTree = ""; }; 49 | 5041486A17F81F2F008D88C6 /* TKDHighlightingTextStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKDHighlightingTextStorage.h; sourceTree = ""; }; 50 | 5041486B17F81F2F008D88C6 /* TKDHighlightingTextStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKDHighlightingTextStorage.m; sourceTree = ""; }; 51 | 5041486E17F821E5008D88C6 /* lorem.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = lorem.txt; sourceTree = ""; }; 52 | 5041487017F82265008D88C6 /* iText.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = iText.txt; sourceTree = ""; }; 53 | 5041487317F8418B008D88C6 /* TKDLayoutingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKDLayoutingViewController.h; sourceTree = ""; }; 54 | 5041487417F8418B008D88C6 /* TKDLayoutingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKDLayoutingViewController.m; sourceTree = ""; }; 55 | 5041487617F843EA008D88C6 /* layout.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = layout.txt; sourceTree = ""; }; 56 | 5041487817F844E5008D88C6 /* TKDLinkDetectingTextStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKDLinkDetectingTextStorage.h; sourceTree = ""; }; 57 | 5041487917F844E5008D88C6 /* TKDLinkDetectingTextStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKDLinkDetectingTextStorage.m; sourceTree = ""; }; 58 | 5041487B17F84DB2008D88C6 /* TKDOutliningLayoutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKDOutliningLayoutManager.h; sourceTree = ""; }; 59 | 5041487C17F84DB2008D88C6 /* TKDOutliningLayoutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKDOutliningLayoutManager.m; sourceTree = ""; }; 60 | 5041487F17F85464008D88C6 /* TKDInteractionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKDInteractionViewController.h; sourceTree = ""; }; 61 | 5041488017F85464008D88C6 /* TKDInteractionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKDInteractionViewController.m; sourceTree = ""; }; 62 | 5041488217F854EF008D88C6 /* TKDCircleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKDCircleView.h; sourceTree = ""; }; 63 | 5041488317F854EF008D88C6 /* TKDCircleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKDCircleView.m; sourceTree = ""; }; 64 | /* End PBXFileReference section */ 65 | 66 | /* Begin PBXFrameworksBuildPhase section */ 67 | 5041482117F80E5C008D88C6 /* Frameworks */ = { 68 | isa = PBXFrameworksBuildPhase; 69 | buildActionMask = 2147483647; 70 | files = ( 71 | 5041482A17F80E5C008D88C6 /* CoreGraphics.framework in Frameworks */, 72 | 5041482C17F80E5C008D88C6 /* UIKit.framework in Frameworks */, 73 | 5041482817F80E5C008D88C6 /* Foundation.framework in Frameworks */, 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | /* End PBXFrameworksBuildPhase section */ 78 | 79 | /* Begin PBXGroup section */ 80 | 5041481B17F80E5C008D88C6 = { 81 | isa = PBXGroup; 82 | children = ( 83 | 5041482D17F80E5C008D88C6 /* TextKitDemo */, 84 | 5041482617F80E5C008D88C6 /* Frameworks */, 85 | 5041482517F80E5C008D88C6 /* Products */, 86 | ); 87 | sourceTree = ""; 88 | }; 89 | 5041482517F80E5C008D88C6 /* Products */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 5041482417F80E5C008D88C6 /* TextKitDemo.app */, 93 | ); 94 | name = Products; 95 | sourceTree = ""; 96 | }; 97 | 5041482617F80E5C008D88C6 /* Frameworks */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 5041482717F80E5C008D88C6 /* Foundation.framework */, 101 | 5041482917F80E5C008D88C6 /* CoreGraphics.framework */, 102 | 5041482B17F80E5C008D88C6 /* UIKit.framework */, 103 | 5041484917F80E5C008D88C6 /* XCTest.framework */, 104 | ); 105 | name = Frameworks; 106 | sourceTree = ""; 107 | }; 108 | 5041482D17F80E5C008D88C6 /* TextKitDemo */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 5041483617F80E5C008D88C6 /* TKDAppDelegate.h */, 112 | 5041483717F80E5C008D88C6 /* TKDAppDelegate.m */, 113 | 5041483917F80E5C008D88C6 /* Main.storyboard */, 114 | 5041486217F8112A008D88C6 /* Configuration */, 115 | 5041486517F8112A008D88C6 /* Highlighting */, 116 | 5041487217F8418B008D88C6 /* Layout */, 117 | 5041487E17F85448008D88C6 /* Interaction */, 118 | 5041484217F80E5C008D88C6 /* Images.xcassets */, 119 | 5041486D17F821CC008D88C6 /* Texts */, 120 | 5041482E17F80E5C008D88C6 /* Supporting Files */, 121 | ); 122 | path = TextKitDemo; 123 | sourceTree = ""; 124 | }; 125 | 5041482E17F80E5C008D88C6 /* Supporting Files */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 5041482F17F80E5C008D88C6 /* TextKitDemo-Info.plist */, 129 | 5041483017F80E5C008D88C6 /* InfoPlist.strings */, 130 | 5041483317F80E5C008D88C6 /* main.m */, 131 | 5041483517F80E5C008D88C6 /* TextKitDemo-Prefix.pch */, 132 | ); 133 | name = "Supporting Files"; 134 | sourceTree = ""; 135 | }; 136 | 5041486217F8112A008D88C6 /* Configuration */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 5041486317F8112A008D88C6 /* TKDConfigurationViewController.h */, 140 | 5041486417F8112A008D88C6 /* TKDConfigurationViewController.m */, 141 | ); 142 | path = Configuration; 143 | sourceTree = ""; 144 | }; 145 | 5041486517F8112A008D88C6 /* Highlighting */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 5041486617F8112A008D88C6 /* TKDHighlightingViewController.h */, 149 | 5041486717F8112A008D88C6 /* TKDHighlightingViewController.m */, 150 | 5041486A17F81F2F008D88C6 /* TKDHighlightingTextStorage.h */, 151 | 5041486B17F81F2F008D88C6 /* TKDHighlightingTextStorage.m */, 152 | ); 153 | path = Highlighting; 154 | sourceTree = ""; 155 | }; 156 | 5041486D17F821CC008D88C6 /* Texts */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 5041486E17F821E5008D88C6 /* lorem.txt */, 160 | 5041487017F82265008D88C6 /* iText.txt */, 161 | 5041487617F843EA008D88C6 /* layout.txt */, 162 | ); 163 | path = Texts; 164 | sourceTree = ""; 165 | }; 166 | 5041487217F8418B008D88C6 /* Layout */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | 5041487317F8418B008D88C6 /* TKDLayoutingViewController.h */, 170 | 5041487417F8418B008D88C6 /* TKDLayoutingViewController.m */, 171 | 5041487B17F84DB2008D88C6 /* TKDOutliningLayoutManager.h */, 172 | 5041487C17F84DB2008D88C6 /* TKDOutliningLayoutManager.m */, 173 | 5041487817F844E5008D88C6 /* TKDLinkDetectingTextStorage.h */, 174 | 5041487917F844E5008D88C6 /* TKDLinkDetectingTextStorage.m */, 175 | ); 176 | path = Layout; 177 | sourceTree = ""; 178 | }; 179 | 5041487E17F85448008D88C6 /* Interaction */ = { 180 | isa = PBXGroup; 181 | children = ( 182 | 5041487F17F85464008D88C6 /* TKDInteractionViewController.h */, 183 | 5041488017F85464008D88C6 /* TKDInteractionViewController.m */, 184 | 5041488217F854EF008D88C6 /* TKDCircleView.h */, 185 | 5041488317F854EF008D88C6 /* TKDCircleView.m */, 186 | ); 187 | path = Interaction; 188 | sourceTree = ""; 189 | }; 190 | /* End PBXGroup section */ 191 | 192 | /* Begin PBXNativeTarget section */ 193 | 5041482317F80E5C008D88C6 /* TextKitDemo */ = { 194 | isa = PBXNativeTarget; 195 | buildConfigurationList = 5041485917F80E5C008D88C6 /* Build configuration list for PBXNativeTarget "TextKitDemo" */; 196 | buildPhases = ( 197 | 5041482017F80E5C008D88C6 /* Sources */, 198 | 5041482117F80E5C008D88C6 /* Frameworks */, 199 | 5041482217F80E5C008D88C6 /* Resources */, 200 | ); 201 | buildRules = ( 202 | ); 203 | dependencies = ( 204 | ); 205 | name = TextKitDemo; 206 | productName = TextKitDemo; 207 | productReference = 5041482417F80E5C008D88C6 /* TextKitDemo.app */; 208 | productType = "com.apple.product-type.application"; 209 | }; 210 | /* End PBXNativeTarget section */ 211 | 212 | /* Begin PBXProject section */ 213 | 5041481C17F80E5C008D88C6 /* Project object */ = { 214 | isa = PBXProject; 215 | attributes = { 216 | CLASSPREFIX = TKD; 217 | LastUpgradeCheck = 0500; 218 | ORGANIZATIONNAME = "Max Seelemann"; 219 | }; 220 | buildConfigurationList = 5041481F17F80E5C008D88C6 /* Build configuration list for PBXProject "TextKitDemo" */; 221 | compatibilityVersion = "Xcode 3.2"; 222 | developmentRegion = English; 223 | hasScannedForEncodings = 0; 224 | knownRegions = ( 225 | en, 226 | Base, 227 | ); 228 | mainGroup = 5041481B17F80E5C008D88C6; 229 | productRefGroup = 5041482517F80E5C008D88C6 /* Products */; 230 | projectDirPath = ""; 231 | projectRoot = ""; 232 | targets = ( 233 | 5041482317F80E5C008D88C6 /* TextKitDemo */, 234 | ); 235 | }; 236 | /* End PBXProject section */ 237 | 238 | /* Begin PBXResourcesBuildPhase section */ 239 | 5041482217F80E5C008D88C6 /* Resources */ = { 240 | isa = PBXResourcesBuildPhase; 241 | buildActionMask = 2147483647; 242 | files = ( 243 | 5041484317F80E5C008D88C6 /* Images.xcassets in Resources */, 244 | 5041483217F80E5C008D88C6 /* InfoPlist.strings in Resources */, 245 | 5041487117F82265008D88C6 /* iText.txt in Resources */, 246 | 5041486F17F821E5008D88C6 /* lorem.txt in Resources */, 247 | 5041487717F843EA008D88C6 /* layout.txt in Resources */, 248 | 5041483B17F80E5C008D88C6 /* Main.storyboard in Resources */, 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | }; 252 | /* End PBXResourcesBuildPhase section */ 253 | 254 | /* Begin PBXSourcesBuildPhase section */ 255 | 5041482017F80E5C008D88C6 /* Sources */ = { 256 | isa = PBXSourcesBuildPhase; 257 | buildActionMask = 2147483647; 258 | files = ( 259 | 5041488417F854EF008D88C6 /* TKDCircleView.m in Sources */, 260 | 5041486C17F81F2F008D88C6 /* TKDHighlightingTextStorage.m in Sources */, 261 | 5041486817F8112A008D88C6 /* TKDConfigurationViewController.m in Sources */, 262 | 5041488117F85464008D88C6 /* TKDInteractionViewController.m in Sources */, 263 | 5041483817F80E5C008D88C6 /* TKDAppDelegate.m in Sources */, 264 | 5041487D17F84DB2008D88C6 /* TKDOutliningLayoutManager.m in Sources */, 265 | 5041487A17F844E5008D88C6 /* TKDLinkDetectingTextStorage.m in Sources */, 266 | 5041486917F8112A008D88C6 /* TKDHighlightingViewController.m in Sources */, 267 | 5041487517F8418B008D88C6 /* TKDLayoutingViewController.m in Sources */, 268 | 5041483417F80E5C008D88C6 /* main.m in Sources */, 269 | ); 270 | runOnlyForDeploymentPostprocessing = 0; 271 | }; 272 | /* End PBXSourcesBuildPhase section */ 273 | 274 | /* Begin PBXVariantGroup section */ 275 | 5041483017F80E5C008D88C6 /* InfoPlist.strings */ = { 276 | isa = PBXVariantGroup; 277 | children = ( 278 | 5041483117F80E5C008D88C6 /* en */, 279 | ); 280 | name = InfoPlist.strings; 281 | sourceTree = ""; 282 | }; 283 | 5041483917F80E5C008D88C6 /* Main.storyboard */ = { 284 | isa = PBXVariantGroup; 285 | children = ( 286 | 5041483A17F80E5C008D88C6 /* Base */, 287 | ); 288 | name = Main.storyboard; 289 | sourceTree = ""; 290 | }; 291 | /* End PBXVariantGroup section */ 292 | 293 | /* Begin XCBuildConfiguration section */ 294 | 5041485717F80E5C008D88C6 /* Debug */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ALWAYS_SEARCH_USER_PATHS = NO; 298 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 299 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 300 | CLANG_CXX_LIBRARY = "libc++"; 301 | CLANG_ENABLE_MODULES = YES; 302 | CLANG_ENABLE_OBJC_ARC = YES; 303 | CLANG_WARN_BOOL_CONVERSION = YES; 304 | CLANG_WARN_CONSTANT_CONVERSION = YES; 305 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 306 | CLANG_WARN_EMPTY_BODY = YES; 307 | CLANG_WARN_ENUM_CONVERSION = YES; 308 | CLANG_WARN_INT_CONVERSION = YES; 309 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 310 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 311 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 312 | COPY_PHASE_STRIP = NO; 313 | GCC_C_LANGUAGE_STANDARD = gnu99; 314 | GCC_DYNAMIC_NO_PIC = NO; 315 | GCC_OPTIMIZATION_LEVEL = 0; 316 | GCC_PREPROCESSOR_DEFINITIONS = ( 317 | "DEBUG=1", 318 | "$(inherited)", 319 | ); 320 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 321 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 322 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 323 | GCC_WARN_UNDECLARED_SELECTOR = YES; 324 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 325 | GCC_WARN_UNUSED_FUNCTION = YES; 326 | GCC_WARN_UNUSED_VARIABLE = YES; 327 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 328 | ONLY_ACTIVE_ARCH = YES; 329 | SDKROOT = iphoneos; 330 | }; 331 | name = Debug; 332 | }; 333 | 5041485817F80E5C008D88C6 /* Release */ = { 334 | isa = XCBuildConfiguration; 335 | buildSettings = { 336 | ALWAYS_SEARCH_USER_PATHS = NO; 337 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 338 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 339 | CLANG_CXX_LIBRARY = "libc++"; 340 | CLANG_ENABLE_MODULES = YES; 341 | CLANG_ENABLE_OBJC_ARC = YES; 342 | CLANG_WARN_BOOL_CONVERSION = YES; 343 | CLANG_WARN_CONSTANT_CONVERSION = YES; 344 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 345 | CLANG_WARN_EMPTY_BODY = YES; 346 | CLANG_WARN_ENUM_CONVERSION = YES; 347 | CLANG_WARN_INT_CONVERSION = YES; 348 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 349 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 350 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 351 | COPY_PHASE_STRIP = YES; 352 | ENABLE_NS_ASSERTIONS = NO; 353 | GCC_C_LANGUAGE_STANDARD = gnu99; 354 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 355 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 356 | GCC_WARN_UNDECLARED_SELECTOR = YES; 357 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 358 | GCC_WARN_UNUSED_FUNCTION = YES; 359 | GCC_WARN_UNUSED_VARIABLE = YES; 360 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 361 | SDKROOT = iphoneos; 362 | VALIDATE_PRODUCT = YES; 363 | }; 364 | name = Release; 365 | }; 366 | 5041485A17F80E5C008D88C6 /* Debug */ = { 367 | isa = XCBuildConfiguration; 368 | buildSettings = { 369 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 370 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 371 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 372 | GCC_PREFIX_HEADER = "TextKitDemo/TextKitDemo-Prefix.pch"; 373 | INFOPLIST_FILE = "TextKitDemo/TextKitDemo-Info.plist"; 374 | PRODUCT_NAME = "$(TARGET_NAME)"; 375 | WRAPPER_EXTENSION = app; 376 | }; 377 | name = Debug; 378 | }; 379 | 5041485B17F80E5C008D88C6 /* Release */ = { 380 | isa = XCBuildConfiguration; 381 | buildSettings = { 382 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 383 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 384 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 385 | GCC_PREFIX_HEADER = "TextKitDemo/TextKitDemo-Prefix.pch"; 386 | INFOPLIST_FILE = "TextKitDemo/TextKitDemo-Info.plist"; 387 | PRODUCT_NAME = "$(TARGET_NAME)"; 388 | WRAPPER_EXTENSION = app; 389 | }; 390 | name = Release; 391 | }; 392 | /* End XCBuildConfiguration section */ 393 | 394 | /* Begin XCConfigurationList section */ 395 | 5041481F17F80E5C008D88C6 /* Build configuration list for PBXProject "TextKitDemo" */ = { 396 | isa = XCConfigurationList; 397 | buildConfigurations = ( 398 | 5041485717F80E5C008D88C6 /* Debug */, 399 | 5041485817F80E5C008D88C6 /* Release */, 400 | ); 401 | defaultConfigurationIsVisible = 0; 402 | defaultConfigurationName = Release; 403 | }; 404 | 5041485917F80E5C008D88C6 /* Build configuration list for PBXNativeTarget "TextKitDemo" */ = { 405 | isa = XCConfigurationList; 406 | buildConfigurations = ( 407 | 5041485A17F80E5C008D88C6 /* Debug */, 408 | 5041485B17F80E5C008D88C6 /* Release */, 409 | ); 410 | defaultConfigurationIsVisible = 0; 411 | defaultConfigurationName = Release; 412 | }; 413 | /* End XCConfigurationList section */ 414 | }; 415 | rootObject = 5041481C17F80E5C008D88C6 /* Project object */; 416 | } 417 | -------------------------------------------------------------------------------- /TextKitDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TextKitDemo.xcodeproj/xcuserdata/max.xcuserdatad/xcschemes/TextKitDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /TextKitDemo.xcodeproj/xcuserdata/max.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | TextKitDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 5041482317F80E5C008D88C6 16 | 17 | primary 18 | 19 | 20 | 5041484717F80E5C008D88C6 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TextKitDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | -------------------------------------------------------------------------------- /TextKitDemo/Configuration/TKDConfigurationViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKDConfigurationViewController.h 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKDConfigurationViewController : UIViewController 12 | 13 | @property (weak, nonatomic) IBOutlet UITextView *originalTextView; 14 | 15 | @property (weak, nonatomic) IBOutlet UIView *otherContainerView; 16 | @property (weak, nonatomic) IBOutlet UIView *thirdContainerView; 17 | 18 | - (IBAction)endEditing:(UIBarButtonItem *)sender; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /TextKitDemo/Configuration/TKDConfigurationViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKDConfigurationViewController.m 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import "TKDConfigurationViewController.h" 10 | 11 | @interface TKDConfigurationViewController () 12 | 13 | @property (weak, nonatomic) UITextView *otherTextView; 14 | @property (weak, nonatomic) UITextView *thirdTextView; 15 | 16 | @end 17 | 18 | @implementation TKDConfigurationViewController 19 | 20 | - (void)viewDidLoad 21 | { 22 | [super viewDidLoad]; 23 | 24 | // Load text 25 | NSTextStorage *sharedTextStorage = self.originalTextView.textStorage; 26 | [sharedTextStorage replaceCharactersInRange:NSMakeRange(0, 0) withString:[NSString stringWithContentsOfURL:[NSBundle.mainBundle URLForResource:@"lorem" withExtension:@"txt"] usedEncoding:NULL error:NULL]]; 27 | 28 | 29 | // Create a new text view on the original text storage 30 | NSLayoutManager *otherLayoutManager = [NSLayoutManager new]; 31 | [sharedTextStorage addLayoutManager: otherLayoutManager]; 32 | 33 | NSTextContainer *otherTextContainer = [NSTextContainer new]; 34 | [otherLayoutManager addTextContainer: otherTextContainer]; 35 | 36 | UITextView *otherTextView = [[UITextView alloc] initWithFrame:self.otherContainerView.bounds textContainer:otherTextContainer]; 37 | otherTextView.backgroundColor = self.otherContainerView.backgroundColor; 38 | otherTextView.translatesAutoresizingMaskIntoConstraints = YES; 39 | otherTextView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 40 | 41 | otherTextView.scrollEnabled = NO; 42 | 43 | [self.otherContainerView addSubview: otherTextView]; 44 | self.otherTextView = otherTextView; 45 | 46 | 47 | // Create a second text view on the new layout manager text storage 48 | NSTextContainer *thirdTextContainer = [NSTextContainer new]; 49 | [otherLayoutManager addTextContainer: thirdTextContainer]; 50 | 51 | UITextView *thirdTextView = [[UITextView alloc] initWithFrame:self.thirdContainerView.bounds textContainer:thirdTextContainer]; 52 | thirdTextView.backgroundColor = self.thirdContainerView.backgroundColor; 53 | thirdTextView.translatesAutoresizingMaskIntoConstraints = YES; 54 | thirdTextView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 55 | 56 | [self.thirdContainerView addSubview: thirdTextView]; 57 | self.thirdTextView = thirdTextView; 58 | } 59 | 60 | - (IBAction)endEditing:(UIBarButtonItem *)sender 61 | { 62 | [self.view endEditing: YES]; 63 | } 64 | 65 | @end -------------------------------------------------------------------------------- /TextKitDemo/Highlighting/TKDHighlightingTextStorage.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKDHighlightingTextStorage.h 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKDHighlightingTextStorage : NSTextStorage 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /TextKitDemo/Highlighting/TKDHighlightingTextStorage.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKDHighlightingTextStorage.m 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import "TKDHighlightingTextStorage.h" 10 | 11 | 12 | @implementation TKDHighlightingTextStorage 13 | { 14 | NSMutableAttributedString *_imp; 15 | } 16 | 17 | - (id)init 18 | { 19 | self = [super init]; 20 | 21 | if (self) { 22 | _imp = [NSMutableAttributedString new]; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | 29 | #pragma mark - Reading Text 30 | 31 | - (NSString *)string 32 | { 33 | return _imp.string; 34 | } 35 | 36 | - (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range 37 | { 38 | return [_imp attributesAtIndex:location effectiveRange:range]; 39 | } 40 | 41 | 42 | #pragma mark - Text Editing 43 | 44 | - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str 45 | { 46 | [_imp replaceCharactersInRange:range withString:str]; 47 | [self edited:NSTextStorageEditedCharacters range:range changeInLength:(NSInteger)str.length - (NSInteger)range.length]; 48 | } 49 | 50 | - (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range 51 | { 52 | [_imp setAttributes:attrs range:range]; 53 | [self edited:NSTextStorageEditedAttributes range:range changeInLength:0]; 54 | } 55 | 56 | 57 | #pragma mark - Syntax highlighting 58 | 59 | - (void)processEditing 60 | { 61 | // 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. 62 | static NSRegularExpression *iExpression; 63 | iExpression = iExpression ?: [NSRegularExpression regularExpressionWithPattern:@"i[\\p{Alphabetic}&&\\p{Uppercase}][\\p{Alphabetic}]+" options:0 error:NULL]; 64 | 65 | 66 | // Clear text color of edited range 67 | NSRange paragaphRange = [self.string paragraphRangeForRange: self.editedRange]; 68 | [self removeAttribute:NSForegroundColorAttributeName range:paragaphRange]; 69 | 70 | // Find all iWords in range 71 | [iExpression enumerateMatchesInString:self.string options:0 range:paragaphRange usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 72 | // Add red highlight color 73 | [self addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:result.range]; 74 | }]; 75 | 76 | // Call super *after* changing the attrbutes, as it finalizes the attributes and calls the delegate methods. 77 | [super processEditing]; 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /TextKitDemo/Highlighting/TKDHighlightingViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKDFirstViewController.h 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKDHighlightingViewController : UIViewController 12 | 13 | @property (weak, nonatomic) IBOutlet UITextView *textView; 14 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomInset; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /TextKitDemo/Highlighting/TKDHighlightingViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKDFirstViewController.m 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import "TKDHighlightingViewController.h" 10 | 11 | #import "TKDHighlightingTextStorage.h" 12 | 13 | 14 | @implementation TKDHighlightingViewController 15 | { 16 | // Text storage must be held strongly, only the default storage is retained by the text view. 17 | TKDHighlightingTextStorage *_textStorage; 18 | } 19 | 20 | 21 | #pragma mark - View lifecycle 22 | 23 | - (void)viewDidLoad 24 | { 25 | [super viewDidLoad]; 26 | 27 | // Replace text storage 28 | _textStorage = [TKDHighlightingTextStorage new]; 29 | [_textStorage addLayoutManager: self.textView.layoutManager]; 30 | 31 | // Load iText 32 | [_textStorage replaceCharactersInRange:NSMakeRange(0, 0) withString:[NSString stringWithContentsOfURL:[NSBundle.mainBundle URLForResource:@"iText" withExtension:@"txt"] usedEncoding:NULL error:NULL]]; 33 | } 34 | 35 | - (void)viewDidAppear:(BOOL)animated 36 | { 37 | [super viewDidAppear: animated]; 38 | 39 | [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(keyboardWillShowOrHide:) name:UIKeyboardWillShowNotification object:nil]; 40 | [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(keyboardWillShowOrHide:) name:UIKeyboardDidHideNotification object:nil]; 41 | } 42 | 43 | - (void)viewWillDisappear:(BOOL)animated 44 | { 45 | [super viewWillDisappear: animated]; 46 | 47 | [NSNotificationCenter.defaultCenter removeObserver:self name:UIKeyboardWillShowNotification object:nil]; 48 | [NSNotificationCenter.defaultCenter removeObserver:self name:UIKeyboardWillHideNotification object:nil]; 49 | } 50 | 51 | 52 | #pragma mark - Keyboard status 53 | 54 | - (void)keyboardWillShowOrHide:(NSNotification *)notification 55 | { 56 | CGFloat newInset; 57 | if ([notification.name isEqualToString: UIKeyboardWillShowNotification]) 58 | newInset = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; 59 | else 60 | newInset = 20; 61 | 62 | [self.bottomInset setConstant: newInset]; 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /TextKitDemo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TextKitDemo/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TextKitDemo/Images.xcassets/clip.imageset/187-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objcio/issue-5-textkit/5ebb2cd62fb993363eb9d626a96f4953801d25d0/TextKitDemo/Images.xcassets/clip.imageset/187-1.png -------------------------------------------------------------------------------- /TextKitDemo/Images.xcassets/clip.imageset/187.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objcio/issue-5-textkit/5ebb2cd62fb993363eb9d626a96f4953801d25d0/TextKitDemo/Images.xcassets/clip.imageset/187.png -------------------------------------------------------------------------------- /TextKitDemo/Images.xcassets/clip.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "187-1.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "187.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /TextKitDemo/Images.xcassets/first.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "first.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "first@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /TextKitDemo/Images.xcassets/first.imageset/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objcio/issue-5-textkit/5ebb2cd62fb993363eb9d626a96f4953801d25d0/TextKitDemo/Images.xcassets/first.imageset/first.png -------------------------------------------------------------------------------- /TextKitDemo/Images.xcassets/first.imageset/first@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objcio/issue-5-textkit/5ebb2cd62fb993363eb9d626a96f4953801d25d0/TextKitDemo/Images.xcassets/first.imageset/first@2x.png -------------------------------------------------------------------------------- /TextKitDemo/Images.xcassets/second.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "second.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "second@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /TextKitDemo/Images.xcassets/second.imageset/second.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objcio/issue-5-textkit/5ebb2cd62fb993363eb9d626a96f4953801d25d0/TextKitDemo/Images.xcassets/second.imageset/second.png -------------------------------------------------------------------------------- /TextKitDemo/Images.xcassets/second.imageset/second@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objcio/issue-5-textkit/5ebb2cd62fb993363eb9d626a96f4953801d25d0/TextKitDemo/Images.xcassets/second.imageset/second@2x.png -------------------------------------------------------------------------------- /TextKitDemo/Interaction/TKDCircleView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKDCircleView.h 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKDCircleView : UIView 12 | @end 13 | -------------------------------------------------------------------------------- /TextKitDemo/Interaction/TKDCircleView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKDCircleView.m 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import "TKDCircleView.h" 10 | 11 | @implementation TKDCircleView 12 | 13 | - (void)drawRect:(CGRect)rect 14 | { 15 | [self.tintColor setFill]; 16 | [[UIBezierPath bezierPathWithOvalInRect: self.bounds] fill]; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /TextKitDemo/Interaction/TKDInteractionViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKDInteractionViewController.h 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import 10 | @class TKDCircleView; 11 | 12 | @interface TKDInteractionViewController : UIViewController 13 | 14 | @property (weak, nonatomic) IBOutlet UIView *clippyView; 15 | @property (weak, nonatomic) IBOutlet TKDCircleView *circleView; 16 | @property (weak, nonatomic) IBOutlet UITextView *textView; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /TextKitDemo/Interaction/TKDInteractionViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKDInteractionViewController.m 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import "TKDInteractionViewController.h" 10 | 11 | #import "TKDCircleView.h" 12 | 13 | 14 | @interface TKDInteractionViewController () 15 | { 16 | CGPoint _panOffset; 17 | } 18 | @end 19 | 20 | @implementation TKDInteractionViewController 21 | 22 | - (void)viewDidLoad 23 | { 24 | [super viewDidLoad]; 25 | 26 | // Load text 27 | [self.textView.textStorage replaceCharactersInRange:NSMakeRange(0, 0) withString:[NSString stringWithContentsOfURL:[NSBundle.mainBundle URLForResource:@"lorem" withExtension:@"txt"] usedEncoding:NULL error:NULL]]; 28 | 29 | // Delegate 30 | self.textView.delegate = self; 31 | self.clippyView.hidden = YES; 32 | 33 | // Set up circle pan 34 | [self.circleView addGestureRecognizer: [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(circlePan:)]]; 35 | [self updateExclusionPaths]; 36 | 37 | // Enable hyphenation 38 | self.textView.layoutManager.hyphenationFactor = 1.0; 39 | } 40 | 41 | 42 | #pragma mark - Exclusion 43 | 44 | - (void)circlePan:(UIPanGestureRecognizer *)pan 45 | { 46 | // Capute offset in view on begin 47 | if (pan.state == UIGestureRecognizerStateBegan) 48 | _panOffset = [pan locationInView: self.circleView]; 49 | 50 | // Update view location 51 | CGPoint location = [pan locationInView: self.view]; 52 | CGPoint circleCenter = self.circleView.center; 53 | 54 | circleCenter.x = location.x - _panOffset.x + self.circleView.frame.size.width / 2; 55 | circleCenter.y = location.y - _panOffset.y + self.circleView.frame.size.width / 2; 56 | self.circleView.center = circleCenter; 57 | 58 | // Update exclusion path 59 | [self updateExclusionPaths]; 60 | } 61 | 62 | - (void)updateExclusionPaths 63 | { 64 | CGRect ovalFrame = [self.textView convertRect:self.circleView.bounds fromView:self.circleView]; 65 | 66 | // Since text container does not know about the inset, we must shift the frame to container coordinates 67 | ovalFrame.origin.x -= self.textView.textContainerInset.left; 68 | ovalFrame.origin.y -= self.textView.textContainerInset.top; 69 | 70 | // Simply set the exclusion path 71 | UIBezierPath *ovalPath = [UIBezierPath bezierPathWithOvalInRect: ovalFrame]; 72 | self.textView.textContainer.exclusionPaths = @[ovalPath]; 73 | 74 | // And don't forget clippy 75 | [self updateClippy]; 76 | } 77 | 78 | 79 | #pragma mark - Selection tracking 80 | 81 | - (void)textViewDidChangeSelection:(UITextView *)textView 82 | { 83 | [self updateClippy]; 84 | } 85 | 86 | - (void)updateClippy 87 | { 88 | // Zero length selection hide clippy 89 | NSRange selectedRange = self.textView.selectedRange; 90 | if (!selectedRange.length) { 91 | self.clippyView.hidden = YES; 92 | return; 93 | } 94 | 95 | // Find last rect of selection 96 | NSRange glyphRange = [self.textView.layoutManager glyphRangeForCharacterRange:selectedRange actualCharacterRange:NULL]; 97 | __block CGRect lastRect; 98 | [self.textView.layoutManager enumerateEnclosingRectsForGlyphRange:glyphRange withinSelectedGlyphRange:glyphRange inTextContainer:self.textView.textContainer usingBlock:^(CGRect rect, BOOL *stop) { 99 | lastRect = rect; 100 | }]; 101 | 102 | 103 | // Position clippy at bottom-right of selection 104 | CGPoint clippyCenter; 105 | clippyCenter.x = CGRectGetMaxX(lastRect) + self.textView.textContainerInset.left; 106 | clippyCenter.y = CGRectGetMaxY(lastRect) + self.textView.textContainerInset.top; 107 | 108 | clippyCenter = [self.textView convertPoint:clippyCenter toView:self.view]; 109 | clippyCenter.x += self.clippyView.bounds.size.width / 2; 110 | clippyCenter.y += self.clippyView.bounds.size.height / 2; 111 | 112 | self.clippyView.hidden = NO; 113 | self.clippyView.center = clippyCenter; 114 | } 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /TextKitDemo/Layout/TKDLayoutingViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKDSecondViewController.h 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKDLayoutingViewController : UIViewController 12 | @end 13 | -------------------------------------------------------------------------------- /TextKitDemo/Layout/TKDLayoutingViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKDSecondViewController.m 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import "TKDLayoutingViewController.h" 10 | 11 | #import "TKDLinkDetectingTextStorage.h" 12 | #import "TKDOutliningLayoutManager.h" 13 | 14 | 15 | @interface TKDLayoutingViewController () 16 | { 17 | // Text storage must be held strongly, only the default storage is retained by the text view. 18 | TKDLinkDetectingTextStorage *_textStorage; 19 | } 20 | @end 21 | 22 | @implementation TKDLayoutingViewController 23 | 24 | - (void)viewDidLoad 25 | { 26 | [super viewDidLoad]; 27 | 28 | // Create componentes 29 | _textStorage = [TKDLinkDetectingTextStorage new]; 30 | 31 | NSLayoutManager *layoutManager = [TKDOutliningLayoutManager new]; 32 | [_textStorage addLayoutManager: layoutManager]; 33 | 34 | NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize: CGSizeZero]; 35 | [layoutManager addTextContainer: textContainer]; 36 | 37 | UITextView *textView = [[UITextView alloc] initWithFrame:CGRectInset(self.view.bounds, 5, 20) textContainer: textContainer]; 38 | textView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 39 | textView.translatesAutoresizingMaskIntoConstraints = YES; 40 | textView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; 41 | [self.view addSubview: textView]; 42 | 43 | 44 | // Set delegate 45 | layoutManager.delegate = self; 46 | 47 | // Load layout text 48 | [_textStorage replaceCharactersInRange:NSMakeRange(0, 0) withString:[NSString stringWithContentsOfURL:[NSBundle.mainBundle URLForResource:@"layout" withExtension:@"txt"] usedEncoding:NULL error:NULL]]; 49 | } 50 | 51 | 52 | #pragma mark - Layout 53 | 54 | - (BOOL)layoutManager:(NSLayoutManager *)layoutManager shouldBreakLineByWordBeforeCharacterAtIndex:(NSUInteger)charIndex 55 | { 56 | NSRange range; 57 | NSURL *linkURL = [layoutManager.textStorage attribute:NSLinkAttributeName atIndex:charIndex effectiveRange:&range]; 58 | 59 | // Do not break lines in links unless absolutely required 60 | if (linkURL && charIndex > range.location && charIndex <= NSMaxRange(range)) 61 | return NO; 62 | else 63 | return YES; 64 | } 65 | 66 | - (CGFloat)layoutManager:(NSLayoutManager *)layoutManager lineSpacingAfterGlyphAtIndex:(NSUInteger)glyphIndex withProposedLineFragmentRect:(CGRect)rect 67 | { 68 | return floorf(glyphIndex / 100); 69 | } 70 | 71 | - (CGFloat)layoutManager:(NSLayoutManager *)layoutManager paragraphSpacingAfterGlyphAtIndex:(NSUInteger)glyphIndex withProposedLineFragmentRect:(CGRect)rect 72 | { 73 | return 10; 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /TextKitDemo/Layout/TKDLinkDetectingTextStorage.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKDLinkDetectingTextStorage.h 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKDLinkDetectingTextStorage : NSTextStorage 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /TextKitDemo/Layout/TKDLinkDetectingTextStorage.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKDLinkDetectingTextStorage.m 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import "TKDLinkDetectingTextStorage.h" 10 | 11 | 12 | @implementation TKDLinkDetectingTextStorage 13 | { 14 | NSTextStorage *_imp; 15 | } 16 | 17 | - (id)init 18 | { 19 | self = [super init]; 20 | 21 | if (self) { 22 | _imp = [NSTextStorage new]; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | 29 | #pragma mark - Reading Text 30 | 31 | - (NSString *)string 32 | { 33 | return _imp.string; 34 | } 35 | 36 | - (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range 37 | { 38 | return [_imp attributesAtIndex:location effectiveRange:range]; 39 | } 40 | 41 | 42 | #pragma mark - Text Editing 43 | 44 | - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str 45 | { 46 | // Normal replace 47 | [_imp replaceCharactersInRange:range withString:str]; 48 | [self edited:NSTextStorageEditedCharacters range:range changeInLength:(NSInteger)str.length - (NSInteger)range.length]; 49 | 50 | 51 | 52 | // 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. 53 | static NSDataDetector *linkDetector; 54 | linkDetector = linkDetector ?: [[NSDataDetector alloc] initWithTypes:NSTextCheckingTypeLink error:NULL]; 55 | 56 | // Clear text color of edited range 57 | NSRange paragaphRange = [self.string paragraphRangeForRange: NSMakeRange(range.location, str.length)]; 58 | [self removeAttribute:NSLinkAttributeName range:paragaphRange]; 59 | [self removeAttribute:NSBackgroundColorAttributeName range:paragaphRange]; 60 | [self removeAttribute:NSUnderlineStyleAttributeName range:paragaphRange]; 61 | 62 | // Find all iWords in range 63 | [linkDetector enumerateMatchesInString:self.string options:0 range:paragaphRange usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 64 | // Add red highlight color 65 | [self addAttribute:NSLinkAttributeName value:result.URL range:result.range]; 66 | [self addAttribute:NSBackgroundColorAttributeName value:[UIColor yellowColor] range:result.range]; 67 | [self addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:result.range]; 68 | }]; 69 | } 70 | 71 | - (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range 72 | { 73 | [_imp setAttributes:attrs range:range]; 74 | [self edited:NSTextStorageEditedAttributes range:range changeInLength:0]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /TextKitDemo/Layout/TKDOutliningLayoutManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKDOutliningLayoutManager.h 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKDOutliningLayoutManager : NSLayoutManager 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /TextKitDemo/Layout/TKDOutliningLayoutManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKDOutliningLayoutManager.m 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import "TKDOutliningLayoutManager.h" 10 | 11 | @implementation TKDOutliningLayoutManager 12 | 13 | - (void)drawUnderlineForGlyphRange:(NSRange)glyphRange underlineType:(NSUnderlineStyle)underlineVal baselineOffset:(CGFloat)baselineOffset lineFragmentRect:(CGRect)lineRect lineFragmentGlyphRange:(NSRange)lineGlyphRange containerOrigin:(CGPoint)containerOrigin 14 | { 15 | // Left border (== position) of first underlined glyph 16 | CGFloat firstPosition = [self locationForGlyphAtIndex: glyphRange.location].x; 17 | 18 | // Right border (== position + width) of last underlined glyph 19 | CGFloat lastPosition; 20 | 21 | // When link is not the last text in line, just use the location of the next glyph 22 | if (NSMaxRange(glyphRange) < NSMaxRange(lineGlyphRange)) { 23 | lastPosition = [self locationForGlyphAtIndex: NSMaxRange(glyphRange)].x; 24 | } 25 | // Otherwise get the end of the actually used rect 26 | else { 27 | lastPosition = [self lineFragmentUsedRectForGlyphAtIndex:NSMaxRange(glyphRange)-1 effectiveRange:NULL].size.width; 28 | } 29 | 30 | // Inset line fragment to underlined area 31 | lineRect.origin.x += firstPosition; 32 | lineRect.size.width = lastPosition - firstPosition; 33 | 34 | // Offset line by container origin 35 | lineRect.origin.x += containerOrigin.x; 36 | lineRect.origin.y += containerOrigin.y; 37 | 38 | // Align line to pixel boundaries, passed rects may be 39 | lineRect = CGRectInset(CGRectIntegral(lineRect), .5, .5); 40 | 41 | [[UIColor greenColor] set]; 42 | [[UIBezierPath bezierPathWithRect: lineRect] stroke]; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /TextKitDemo/TKDAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKDAppDelegate.h 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKDAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /TextKitDemo/TKDAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKDAppDelegate.m 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import "TKDAppDelegate.h" 10 | 11 | @implementation TKDAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /TextKitDemo/TextKitDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | io.objc.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarTintParameters 34 | 35 | UINavigationBar 36 | 37 | Style 38 | UIBarStyleDefault 39 | Translucent 40 | 41 | 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /TextKitDemo/TextKitDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /TextKitDemo/Texts/iText.txt: -------------------------------------------------------------------------------- 1 | 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. 2 | 3 | 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. 4 | 5 | Fusce tincidunt erat sit amet magna porttitor nec iaculis diam varius. Aliquam eget odio leo. Sed faucibus, libero non consectetur tristique, metus leo tempus libero, quis ornare felis purus in odio. Proin metus arcu, dictum id faucibus gravida, pulvinar ut metus. Mauris nisl sapien, cursus nec auctor quis, bibendum vitae. -------------------------------------------------------------------------------- /TextKitDemo/Texts/layout.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, tomorrow consectetur adipiscing http://stackoverflow.com/questions/tagged/objective-c?sort=featured&pageSize=15 elit. dictum eros non, suscipit purus. Aenean metus mi, sodales ut augue in, varius sagittis http://apple.com magnadolortligulavulputatefringilla. 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 http://www.objc.io/issue-4/editorial.html ipsum eterant, porttitor molestie justo. Vestibulum sed augue malesuada, congue magna sed, fringilla ligula. Sed aliquet porta vestibulum. Phasellus gravida elit uatea 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. 2 | 3 | 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. -------------------------------------------------------------------------------- /TextKitDemo/Texts/lorem.txt: -------------------------------------------------------------------------------- 1 | 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. 2 | 3 | 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. -------------------------------------------------------------------------------- /TextKitDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /TextKitDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TextKitDemo 4 | // 5 | // Created by Max Seelemann on 29.09.13. 6 | // Copyright (c) 2013 Max Seelemann. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "TKDAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([TKDAppDelegate class])); 17 | } 18 | } 19 | --------------------------------------------------------------------------------