├── .gitignore ├── LICENSE ├── README.md ├── Sample3DTouch ├── Sample3DTouch-Bridging-Header.h ├── Sample3DTouch.xcodeproj │ └── project.pbxproj ├── Sample3DTouch │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.swift │ └── WebViewController.swift └── data.html ├── UZTextView.podspec ├── UZTextView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── UZTextView.xcscheme ├── UZTextView ├── Info.plist ├── UZCursorView.h ├── UZCursorView.m ├── UZLoupeView.h ├── UZLoupeView.m ├── UZTextView.h └── UZTextView.m ├── UZTextViewSample ├── AppDelegate.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Bridging-Header.h ├── Info.plist ├── MainTableViewController.swift ├── SampleCell.swift ├── mona.ttf ├── source.json └── trash │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift ├── build.sh ├── html ├── Categories │ ├── UIGestureRecognizer+UZTextView.html │ └── UITouch+UZTextView.html ├── Classes │ └── UZTextView.html ├── Constants │ ├── UZTextViewGlyphEdgeType.html │ └── UZTextViewStatus.html ├── Protocols │ └── UZTextViewDelegate.html ├── css │ ├── styles.css │ └── stylesPrint.css ├── hierarchy.html ├── img │ ├── button_bar_background.png │ ├── disclosure.png │ ├── disclosure_open.png │ ├── library_background.png │ └── title_background.png └── index.html └── screenshot ├── UZTextView.gif └── sample01.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | 3 | .DS_Store 4 | */build/* 5 | ======= 6 | build/* 7 | Product/* 8 | 9 | *.pbxuser 10 | !default.pbxuser 11 | *.mode1v3 12 | !default.mode1v3 13 | *.mode2v3 14 | !default.mode2v3 15 | *.perspectivev3 16 | !default.perspectivev3 17 | 18 | xcuserdata 19 | profile 20 | *.moved-aside 21 | DerivedData 22 | .idea/ 23 | *.hmap 24 | *.xccheckout 25 | 26 | #CocoaPods 27 | Pods 28 | ======= 29 | *.xcworkspace 30 | !default.xcworkspace 31 | xcuserdata 32 | profile 33 | *.moved-aside 34 | .DS_Store 35 | *~ 36 | *.xccheckout 37 | 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, sonson 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 | Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | UZTextView 2 | ========== 3 | Clickable and selectable text view for iOS 4 | 5 | ###What's UZTextView? 6 | - UZTextView class implements implements the behavior for a scrollable, multiline, selectable, clickable text region. 7 | The class supports the display of text using custom style and link information. 8 | - Create subclass of the class and use UZTextView internal category methods if you want to expand the UZTextView class. For example, you have to override some methods of the class in order to add your custom UIMenuItem objects. 9 | - You can use the Class on the UITableView cell and set custom style text using NSAttributedString class objects(like the following image). 10 | 11 | ![image](https://raw.github.com/sonsongithub/UZTextView/master/screenshot/UZTextView.gif) 12 | 13 | ###Supported attributes of NSAttributedString 14 | - NSLinkAttributeName 15 | - NSFontAttributeName 16 | - NSStrikethroughStyleAttributeName 17 | - NSUnderlineStyleAttributeName 18 | - NSBackgroundColorAttributeName 19 | 20 | ###How to build 21 | - Use build.sh. Automatically lib and header file generated at ./build/. 22 | - UZTextView supports [CocoaPods](http://cocoapods.org/). 23 | 24 | ###Document 25 | - See html/index.html 26 | 27 | ###License 28 | - UZTextView is available under BSD-License. See LICENSE file in this repository. 29 | - UZTextView uses [SECoreTextView](https://github.com/kishikawakatsumi/SECoreTextView) source code. [SECoreTextView](https://github.com/kishikawakatsumi/SECoreTextView) is available under the MIT license. -------------------------------------------------------------------------------- /Sample3DTouch/Sample3DTouch-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "UZTextView.h" 6 | -------------------------------------------------------------------------------- /Sample3DTouch/Sample3DTouch.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1442D6EC1D7B985F00BDAC7D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1442D6EB1D7B985F00BDAC7D /* AppDelegate.swift */; }; 11 | 1442D6EE1D7B985F00BDAC7D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1442D6ED1D7B985F00BDAC7D /* ViewController.swift */; }; 12 | 1442D6F11D7B985F00BDAC7D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1442D6EF1D7B985F00BDAC7D /* Main.storyboard */; }; 13 | 1442D6F31D7B985F00BDAC7D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1442D6F21D7B985F00BDAC7D /* Assets.xcassets */; }; 14 | 1442D6F61D7B985F00BDAC7D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1442D6F41D7B985F00BDAC7D /* LaunchScreen.storyboard */; }; 15 | 1442D7051D7B988700BDAC7D /* UZCursorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1442D7001D7B988700BDAC7D /* UZCursorView.m */; }; 16 | 1442D7061D7B988700BDAC7D /* UZLoupeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1442D7021D7B988700BDAC7D /* UZLoupeView.m */; }; 17 | 1442D7071D7B988700BDAC7D /* UZTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1442D7041D7B988700BDAC7D /* UZTextView.m */; }; 18 | 1442D7091D7BA68C00BDAC7D /* data.html in Resources */ = {isa = PBXBuildFile; fileRef = 1442D7081D7BA68C00BDAC7D /* data.html */; }; 19 | 14CC08F21D7BBFBD0026A0AB /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14CC08F11D7BBFBD0026A0AB /* WebViewController.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 1442D6E81D7B985F00BDAC7D /* Sample3DTouch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample3DTouch.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 1442D6EB1D7B985F00BDAC7D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 25 | 1442D6ED1D7B985F00BDAC7D /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 26 | 1442D6F01D7B985F00BDAC7D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 27 | 1442D6F21D7B985F00BDAC7D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 28 | 1442D6F51D7B985F00BDAC7D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 29 | 1442D6F71D7B985F00BDAC7D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | 1442D6FE1D7B988600BDAC7D /* Sample3DTouch-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Sample3DTouch-Bridging-Header.h"; sourceTree = ""; }; 31 | 1442D6FF1D7B988700BDAC7D /* UZCursorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UZCursorView.h; path = ../UZTextView/UZCursorView.h; sourceTree = ""; }; 32 | 1442D7001D7B988700BDAC7D /* UZCursorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UZCursorView.m; path = ../UZTextView/UZCursorView.m; sourceTree = ""; }; 33 | 1442D7011D7B988700BDAC7D /* UZLoupeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UZLoupeView.h; path = ../UZTextView/UZLoupeView.h; sourceTree = ""; }; 34 | 1442D7021D7B988700BDAC7D /* UZLoupeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UZLoupeView.m; path = ../UZTextView/UZLoupeView.m; sourceTree = ""; }; 35 | 1442D7031D7B988700BDAC7D /* UZTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UZTextView.h; path = ../UZTextView/UZTextView.h; sourceTree = ""; }; 36 | 1442D7041D7B988700BDAC7D /* UZTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UZTextView.m; path = ../UZTextView/UZTextView.m; sourceTree = ""; }; 37 | 1442D7081D7BA68C00BDAC7D /* data.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = data.html; path = ../data.html; sourceTree = ""; }; 38 | 14CC08F11D7BBFBD0026A0AB /* WebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewController.swift; sourceTree = ""; }; 39 | /* End PBXFileReference section */ 40 | 41 | /* Begin PBXFrameworksBuildPhase section */ 42 | 1442D6E51D7B985F00BDAC7D /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | ); 47 | runOnlyForDeploymentPostprocessing = 0; 48 | }; 49 | /* End PBXFrameworksBuildPhase section */ 50 | 51 | /* Begin PBXGroup section */ 52 | 1442D6DF1D7B985F00BDAC7D = { 53 | isa = PBXGroup; 54 | children = ( 55 | 1442D6FD1D7B987800BDAC7D /* UZTextView */, 56 | 1442D6EA1D7B985F00BDAC7D /* Sample3DTouch */, 57 | 1442D6E91D7B985F00BDAC7D /* Products */, 58 | ); 59 | sourceTree = ""; 60 | }; 61 | 1442D6E91D7B985F00BDAC7D /* Products */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | 1442D6E81D7B985F00BDAC7D /* Sample3DTouch.app */, 65 | ); 66 | name = Products; 67 | sourceTree = ""; 68 | }; 69 | 1442D6EA1D7B985F00BDAC7D /* Sample3DTouch */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 1442D7081D7BA68C00BDAC7D /* data.html */, 73 | 1442D6EB1D7B985F00BDAC7D /* AppDelegate.swift */, 74 | 1442D6ED1D7B985F00BDAC7D /* ViewController.swift */, 75 | 14CC08F11D7BBFBD0026A0AB /* WebViewController.swift */, 76 | 1442D6EF1D7B985F00BDAC7D /* Main.storyboard */, 77 | 1442D6F21D7B985F00BDAC7D /* Assets.xcassets */, 78 | 1442D6F41D7B985F00BDAC7D /* LaunchScreen.storyboard */, 79 | 1442D6F71D7B985F00BDAC7D /* Info.plist */, 80 | ); 81 | path = Sample3DTouch; 82 | sourceTree = ""; 83 | }; 84 | 1442D6FD1D7B987800BDAC7D /* UZTextView */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 1442D6FF1D7B988700BDAC7D /* UZCursorView.h */, 88 | 1442D7001D7B988700BDAC7D /* UZCursorView.m */, 89 | 1442D7011D7B988700BDAC7D /* UZLoupeView.h */, 90 | 1442D7021D7B988700BDAC7D /* UZLoupeView.m */, 91 | 1442D7031D7B988700BDAC7D /* UZTextView.h */, 92 | 1442D7041D7B988700BDAC7D /* UZTextView.m */, 93 | 1442D6FE1D7B988600BDAC7D /* Sample3DTouch-Bridging-Header.h */, 94 | ); 95 | name = UZTextView; 96 | sourceTree = ""; 97 | }; 98 | /* End PBXGroup section */ 99 | 100 | /* Begin PBXNativeTarget section */ 101 | 1442D6E71D7B985F00BDAC7D /* Sample3DTouch */ = { 102 | isa = PBXNativeTarget; 103 | buildConfigurationList = 1442D6FA1D7B985F00BDAC7D /* Build configuration list for PBXNativeTarget "Sample3DTouch" */; 104 | buildPhases = ( 105 | 1442D6E41D7B985F00BDAC7D /* Sources */, 106 | 1442D6E51D7B985F00BDAC7D /* Frameworks */, 107 | 1442D6E61D7B985F00BDAC7D /* Resources */, 108 | ); 109 | buildRules = ( 110 | ); 111 | dependencies = ( 112 | ); 113 | name = Sample3DTouch; 114 | productName = Sample3DTouch; 115 | productReference = 1442D6E81D7B985F00BDAC7D /* Sample3DTouch.app */; 116 | productType = "com.apple.product-type.application"; 117 | }; 118 | /* End PBXNativeTarget section */ 119 | 120 | /* Begin PBXProject section */ 121 | 1442D6E01D7B985F00BDAC7D /* Project object */ = { 122 | isa = PBXProject; 123 | attributes = { 124 | LastSwiftUpdateCheck = 0800; 125 | LastUpgradeCheck = 0810; 126 | ORGANIZATIONNAME = sonson; 127 | TargetAttributes = { 128 | 1442D6E71D7B985F00BDAC7D = { 129 | CreatedOnToolsVersion = 8.0; 130 | DevelopmentTeam = JP866VWWSD; 131 | LastSwiftMigration = 0800; 132 | ProvisioningStyle = Automatic; 133 | }; 134 | }; 135 | }; 136 | buildConfigurationList = 1442D6E31D7B985F00BDAC7D /* Build configuration list for PBXProject "Sample3DTouch" */; 137 | compatibilityVersion = "Xcode 3.2"; 138 | developmentRegion = English; 139 | hasScannedForEncodings = 0; 140 | knownRegions = ( 141 | en, 142 | Base, 143 | ); 144 | mainGroup = 1442D6DF1D7B985F00BDAC7D; 145 | productRefGroup = 1442D6E91D7B985F00BDAC7D /* Products */; 146 | projectDirPath = ""; 147 | projectRoot = ""; 148 | targets = ( 149 | 1442D6E71D7B985F00BDAC7D /* Sample3DTouch */, 150 | ); 151 | }; 152 | /* End PBXProject section */ 153 | 154 | /* Begin PBXResourcesBuildPhase section */ 155 | 1442D6E61D7B985F00BDAC7D /* Resources */ = { 156 | isa = PBXResourcesBuildPhase; 157 | buildActionMask = 2147483647; 158 | files = ( 159 | 1442D6F61D7B985F00BDAC7D /* LaunchScreen.storyboard in Resources */, 160 | 1442D6F31D7B985F00BDAC7D /* Assets.xcassets in Resources */, 161 | 1442D7091D7BA68C00BDAC7D /* data.html in Resources */, 162 | 1442D6F11D7B985F00BDAC7D /* Main.storyboard in Resources */, 163 | ); 164 | runOnlyForDeploymentPostprocessing = 0; 165 | }; 166 | /* End PBXResourcesBuildPhase section */ 167 | 168 | /* Begin PBXSourcesBuildPhase section */ 169 | 1442D6E41D7B985F00BDAC7D /* Sources */ = { 170 | isa = PBXSourcesBuildPhase; 171 | buildActionMask = 2147483647; 172 | files = ( 173 | 1442D7051D7B988700BDAC7D /* UZCursorView.m in Sources */, 174 | 14CC08F21D7BBFBD0026A0AB /* WebViewController.swift in Sources */, 175 | 1442D6EE1D7B985F00BDAC7D /* ViewController.swift in Sources */, 176 | 1442D6EC1D7B985F00BDAC7D /* AppDelegate.swift in Sources */, 177 | 1442D7061D7B988700BDAC7D /* UZLoupeView.m in Sources */, 178 | 1442D7071D7B988700BDAC7D /* UZTextView.m in Sources */, 179 | ); 180 | runOnlyForDeploymentPostprocessing = 0; 181 | }; 182 | /* End PBXSourcesBuildPhase section */ 183 | 184 | /* Begin PBXVariantGroup section */ 185 | 1442D6EF1D7B985F00BDAC7D /* Main.storyboard */ = { 186 | isa = PBXVariantGroup; 187 | children = ( 188 | 1442D6F01D7B985F00BDAC7D /* Base */, 189 | ); 190 | name = Main.storyboard; 191 | sourceTree = ""; 192 | }; 193 | 1442D6F41D7B985F00BDAC7D /* LaunchScreen.storyboard */ = { 194 | isa = PBXVariantGroup; 195 | children = ( 196 | 1442D6F51D7B985F00BDAC7D /* Base */, 197 | ); 198 | name = LaunchScreen.storyboard; 199 | sourceTree = ""; 200 | }; 201 | /* End PBXVariantGroup section */ 202 | 203 | /* Begin XCBuildConfiguration section */ 204 | 1442D6F81D7B985F00BDAC7D /* Debug */ = { 205 | isa = XCBuildConfiguration; 206 | buildSettings = { 207 | ALWAYS_SEARCH_USER_PATHS = NO; 208 | CLANG_ANALYZER_NONNULL = YES; 209 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 210 | CLANG_CXX_LIBRARY = "libc++"; 211 | CLANG_ENABLE_MODULES = YES; 212 | CLANG_ENABLE_OBJC_ARC = YES; 213 | CLANG_WARN_BOOL_CONVERSION = YES; 214 | CLANG_WARN_CONSTANT_CONVERSION = YES; 215 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 216 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 217 | CLANG_WARN_EMPTY_BODY = YES; 218 | CLANG_WARN_ENUM_CONVERSION = YES; 219 | CLANG_WARN_INFINITE_RECURSION = YES; 220 | CLANG_WARN_INT_CONVERSION = YES; 221 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 222 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 223 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 224 | CLANG_WARN_UNREACHABLE_CODE = YES; 225 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 226 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 227 | COPY_PHASE_STRIP = NO; 228 | DEBUG_INFORMATION_FORMAT = dwarf; 229 | ENABLE_STRICT_OBJC_MSGSEND = YES; 230 | ENABLE_TESTABILITY = YES; 231 | GCC_C_LANGUAGE_STANDARD = gnu99; 232 | GCC_DYNAMIC_NO_PIC = NO; 233 | GCC_NO_COMMON_BLOCKS = YES; 234 | GCC_OPTIMIZATION_LEVEL = 0; 235 | GCC_PREPROCESSOR_DEFINITIONS = ( 236 | "DEBUG=1", 237 | "$(inherited)", 238 | ); 239 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 240 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 241 | GCC_WARN_UNDECLARED_SELECTOR = YES; 242 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 243 | GCC_WARN_UNUSED_FUNCTION = YES; 244 | GCC_WARN_UNUSED_VARIABLE = YES; 245 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 246 | MTL_ENABLE_DEBUG_INFO = YES; 247 | ONLY_ACTIVE_ARCH = YES; 248 | SDKROOT = iphoneos; 249 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 250 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 251 | }; 252 | name = Debug; 253 | }; 254 | 1442D6F91D7B985F00BDAC7D /* Release */ = { 255 | isa = XCBuildConfiguration; 256 | buildSettings = { 257 | ALWAYS_SEARCH_USER_PATHS = NO; 258 | CLANG_ANALYZER_NONNULL = YES; 259 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 260 | CLANG_CXX_LIBRARY = "libc++"; 261 | CLANG_ENABLE_MODULES = YES; 262 | CLANG_ENABLE_OBJC_ARC = YES; 263 | CLANG_WARN_BOOL_CONVERSION = YES; 264 | CLANG_WARN_CONSTANT_CONVERSION = YES; 265 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 266 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 267 | CLANG_WARN_EMPTY_BODY = YES; 268 | CLANG_WARN_ENUM_CONVERSION = YES; 269 | CLANG_WARN_INFINITE_RECURSION = YES; 270 | CLANG_WARN_INT_CONVERSION = YES; 271 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 272 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 273 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 274 | CLANG_WARN_UNREACHABLE_CODE = YES; 275 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 276 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 277 | COPY_PHASE_STRIP = NO; 278 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 279 | ENABLE_NS_ASSERTIONS = NO; 280 | ENABLE_STRICT_OBJC_MSGSEND = YES; 281 | GCC_C_LANGUAGE_STANDARD = gnu99; 282 | GCC_NO_COMMON_BLOCKS = YES; 283 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 284 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 285 | GCC_WARN_UNDECLARED_SELECTOR = YES; 286 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 287 | GCC_WARN_UNUSED_FUNCTION = YES; 288 | GCC_WARN_UNUSED_VARIABLE = YES; 289 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 290 | MTL_ENABLE_DEBUG_INFO = NO; 291 | SDKROOT = iphoneos; 292 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 293 | VALIDATE_PRODUCT = YES; 294 | }; 295 | name = Release; 296 | }; 297 | 1442D6FB1D7B985F00BDAC7D /* Debug */ = { 298 | isa = XCBuildConfiguration; 299 | buildSettings = { 300 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 301 | CLANG_ENABLE_MODULES = YES; 302 | DEVELOPMENT_TEAM = JP866VWWSD; 303 | INFOPLIST_FILE = Sample3DTouch/Info.plist; 304 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 305 | PRODUCT_BUNDLE_IDENTIFIER = com.sonson.Sample3DTouch; 306 | PRODUCT_NAME = "$(TARGET_NAME)"; 307 | SWIFT_OBJC_BRIDGING_HEADER = "Sample3DTouch-Bridging-Header.h"; 308 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 309 | SWIFT_VERSION = 3.0; 310 | }; 311 | name = Debug; 312 | }; 313 | 1442D6FC1D7B985F00BDAC7D /* Release */ = { 314 | isa = XCBuildConfiguration; 315 | buildSettings = { 316 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 317 | CLANG_ENABLE_MODULES = YES; 318 | DEVELOPMENT_TEAM = JP866VWWSD; 319 | INFOPLIST_FILE = Sample3DTouch/Info.plist; 320 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 321 | PRODUCT_BUNDLE_IDENTIFIER = com.sonson.Sample3DTouch; 322 | PRODUCT_NAME = "$(TARGET_NAME)"; 323 | SWIFT_OBJC_BRIDGING_HEADER = "Sample3DTouch-Bridging-Header.h"; 324 | SWIFT_VERSION = 3.0; 325 | }; 326 | name = Release; 327 | }; 328 | /* End XCBuildConfiguration section */ 329 | 330 | /* Begin XCConfigurationList section */ 331 | 1442D6E31D7B985F00BDAC7D /* Build configuration list for PBXProject "Sample3DTouch" */ = { 332 | isa = XCConfigurationList; 333 | buildConfigurations = ( 334 | 1442D6F81D7B985F00BDAC7D /* Debug */, 335 | 1442D6F91D7B985F00BDAC7D /* Release */, 336 | ); 337 | defaultConfigurationIsVisible = 0; 338 | defaultConfigurationName = Release; 339 | }; 340 | 1442D6FA1D7B985F00BDAC7D /* Build configuration list for PBXNativeTarget "Sample3DTouch" */ = { 341 | isa = XCConfigurationList; 342 | buildConfigurations = ( 343 | 1442D6FB1D7B985F00BDAC7D /* Debug */, 344 | 1442D6FC1D7B985F00BDAC7D /* Release */, 345 | ); 346 | defaultConfigurationIsVisible = 0; 347 | defaultConfigurationName = Release; 348 | }; 349 | /* End XCConfigurationList section */ 350 | }; 351 | rootObject = 1442D6E01D7B985F00BDAC7D /* Project object */; 352 | } 353 | -------------------------------------------------------------------------------- /Sample3DTouch/Sample3DTouch/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Sample3DTouch 4 | // 5 | // Created by sonson on 2016/09/04. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // 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. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Sample3DTouch/Sample3DTouch/Assets.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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Sample3DTouch/Sample3DTouch/Base.lproj/LaunchScreen.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 | -------------------------------------------------------------------------------- /Sample3DTouch/Sample3DTouch/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 | -------------------------------------------------------------------------------- /Sample3DTouch/Sample3DTouch/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Sample3DTouch/Sample3DTouch/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Sample3DTouch 4 | // 5 | // Created by sonson on 2016/09/04. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController, UZTextViewDelegate, UIViewControllerPreviewingDelegate { 12 | 13 | @IBOutlet var textView: UZTextView! = nil 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | textView?.delegate = self 18 | textView?.scale = 1 19 | do { 20 | let data = try Data(contentsOf: Bundle.main.url(forResource: "data", withExtension: "html")!) 21 | let options: [String: Any] = [ 22 | NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, 23 | NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue 24 | ] 25 | let attr = try NSMutableAttributedString(data: data, options: options, documentAttributes: nil) 26 | attr.addAttribute(NSFontAttributeName, 27 | value: UIFont.systemFont(ofSize: 20), 28 | range: NSRange(location: 0, length: attr.length)) 29 | textView?.attributedString = attr 30 | 31 | } catch { 32 | print(error) 33 | } 34 | 35 | self.registerForPreviewing(with: self, sourceView: self.view) 36 | } 37 | 38 | override func didReceiveMemoryWarning() { 39 | super.didReceiveMemoryWarning() 40 | // Dispose of any resources that can be recreated. 41 | } 42 | 43 | func textView(_ textView: UZTextView, didLongTapLinkAttribute value: Any?) { 44 | if let attr = value as? [String: Any] { 45 | if let url = attr[NSLinkAttributeName] as? URL { 46 | let sheet = UIAlertController(title: url.absoluteString, message: nil, preferredStyle: .actionSheet) 47 | sheet.addAction( 48 | UIAlertAction(title: "Close", style: .cancel) { (action) in 49 | sheet.dismiss(animated: true, completion: nil) 50 | } 51 | ) 52 | sheet.addAction( 53 | UIAlertAction(title: "Open in Safari", style: .default) { (action) in 54 | UIApplication.shared.open(url, options: [:], completionHandler: nil) 55 | sheet.dismiss(animated: true, completion: nil) 56 | } 57 | ) 58 | sheet.addAction( 59 | UIAlertAction(title: "Open", style: .default) { (action) in 60 | let controller = WebViewController(nibName: nil, bundle: nil) 61 | controller.url = url 62 | let nav = UINavigationController(rootViewController: controller) 63 | self.present(nav, animated: true, completion: nil) 64 | } 65 | ) 66 | sheet.addAction( 67 | UIAlertAction(title: "Copy URL", style: .default) { (action) in 68 | UIPasteboard.general.setValue(url, forPasteboardType: "public.url") 69 | sheet.dismiss(animated: true, completion: nil) 70 | } 71 | ) 72 | present(sheet, animated: true, completion: nil) 73 | } 74 | } 75 | } 76 | 77 | func textView(_ textView: UZTextView, didClickLinkAttribute value: Any?) { 78 | if let attr = value as? [String: Any] { 79 | if let url = attr[NSLinkAttributeName] as? URL { 80 | let controller = WebViewController(nibName: nil, bundle: nil) 81 | controller.url = url 82 | let nav = UINavigationController(rootViewController: controller) 83 | self.present(nav, animated: true, completion: nil) 84 | } 85 | } 86 | } 87 | 88 | func selectionDidEnd(_ textView: UZTextView) { 89 | } 90 | 91 | func selectionDidBegin(_ textView: UZTextView) { 92 | } 93 | 94 | func didTapTextDoesNotIncludeLinkTextView(_ textView: UZTextView) { 95 | } 96 | 97 | func getInfo(locationInTextView: CGPoint) -> (URL, CGRect)? { 98 | if let attr = textView?.attributes(at: locationInTextView) { 99 | if let url = attr[NSLinkAttributeName] as? URL, 100 | let value = attr[UZTextViewClickedRect] as? CGRect { 101 | return (url, value) 102 | } 103 | } 104 | return nil 105 | } 106 | 107 | func previewingContext(_ previewingContext: UIViewControllerPreviewing, 108 | viewControllerForLocation location: CGPoint) -> UIViewController? { 109 | 110 | let locationInTextView = self.view.convert(location, to: textView) 111 | 112 | if let (url, rect) = getInfo(locationInTextView: locationInTextView) { 113 | previewingContext.sourceRect = self.view.convert(rect, from: textView) 114 | let controller = WebViewController(nibName: nil, bundle: nil) 115 | controller.url = url 116 | return controller 117 | } 118 | 119 | return nil 120 | } 121 | 122 | func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) { 123 | 124 | let nav = UINavigationController(rootViewController: viewControllerToCommit) 125 | self.present(nav, animated: true, completion: nil) 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Sample3DTouch/Sample3DTouch/WebViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewController.swift 3 | // Sample3DTouch 4 | // 5 | // Created by sonson on 2016/09/04. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import WebKit 11 | 12 | class WebViewController: UIViewController { 13 | let webView = WKWebView(frame: CGRect.zero) 14 | 15 | override var previewActionItems: [UIPreviewActionItem] { 16 | get { 17 | func previewActionForTitle(_ title: String, style: UIPreviewActionStyle = .default) -> UIPreviewAction { 18 | return UIPreviewAction(title: title, style: style) { previewAction, viewController in 19 | print(title) 20 | } 21 | } 22 | 23 | let action1 = previewActionForTitle("Action1") 24 | let action2 = previewActionForTitle("Destructive Action", style: .destructive) 25 | 26 | let subAction1 = previewActionForTitle("Sub1") 27 | let subAction2 = previewActionForTitle("Sub2") 28 | let groupedActions = UIPreviewActionGroup(title: "Sub Actions", style: .default, actions: [subAction1, subAction2] ) 29 | 30 | return [action1, action2, groupedActions] 31 | } 32 | } 33 | 34 | override func viewDidLoad() { 35 | super.viewDidLoad() 36 | view.addSubview(webView) 37 | webView.translatesAutoresizingMaskIntoConstraints = false 38 | 39 | let views = ["webView": webView] 40 | 41 | view.addConstraints ( 42 | NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[webView]-0-|", options: [], metrics: nil, views: views) 43 | ) 44 | view.addConstraints ( 45 | NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[webView]-0-|", options: [], metrics: nil, views: views) 46 | ) 47 | 48 | let bar = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(WebViewController.close(sender:))) 49 | self.navigationItem.rightBarButtonItem = bar 50 | } 51 | 52 | func close(sender: Any) { 53 | self.dismiss(animated: true, completion: nil) 54 | } 55 | 56 | var url: URL? = nil { 57 | didSet { 58 | if let aUrl = url { 59 | let request = URLRequest(url: aUrl) 60 | webView.load(request) 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Sample3DTouch/data.html: -------------------------------------------------------------------------------- 1 |

Let’s Encryptを使ってLINE Botからのcallbackを受けるサーバを作ったがダメで,さらにAWS API GatewayもLet’s Encrypt SSLを信用してなくて,大変だったというお話.

2 |

Let’s Encryptは,無料で使えるSSLの証明書取得サービスである. 3 | 自動取得/更新がサーバに実装されており,それのためのサーバ側の更新スクリプトも配布されている. 4 | DNSをハックされる危険性や平文をネットワークに流す危険性が危惧される昨今,無料でSSLの証明書を利用できる趣味でサービスを開発したりするエンジニアの強い味方となっている.

5 | -------------------------------------------------------------------------------- /UZTextView.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint UZTextView.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "UZTextView" 19 | s.version = "1.0.8" 20 | s.summary = "Clickable and selectable text view for iOS" 21 | 22 | s.description = <<-DESC 23 | UZTextView class implements implements the behavior for a scrollable, multiline, selectable, clickable text region. The class supports the display of text using custom style and link information. 24 | Create subclass of the class and use UZTextView internal category methods if you want to expand the UZTextView class. For example, you have to override some methods of the class in order to add your custom UIMenuItem objects. 25 | You can use the Class on the UITableView cell and set custom style text using NSAttributedString class objects. 26 | DESC 27 | 28 | s.homepage = "https://github.com/sonsongithub/UZTextView" 29 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 30 | 31 | 32 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 33 | # 34 | # Licensing your code is important. See http://choosealicense.com for more info. 35 | # CocoaPods will detect a license file if there is a named LICENSE* 36 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 37 | # 38 | 39 | # s.license = "BSD" 40 | s.license = { :type => "BSD", :file => "LICENSE" } 41 | 42 | 43 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 44 | # 45 | # Specify the authors of the library, with email addresses. Email addresses 46 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 47 | # accepts just a name if you'd rather not provide an email address. 48 | # 49 | # Specify a social_media_url where others can refer to, for example a twitter 50 | # profile URL. 51 | # 52 | 53 | s.author = { "sonson" => "" } 54 | # Or just: s.author = "sonson" 55 | # s.authors = { "sonson" => "" } 56 | s.social_media_url = "http://twitter.com/sonson_twit" 57 | 58 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 59 | # 60 | # If this Pod runs only on iOS or OS X, then specify the platform and 61 | # the deployment target. You can optionally include the target after the platform. 62 | # 63 | 64 | s.platform = :ios 65 | 66 | # When using multiple platforms 67 | s.ios.deployment_target = "7.0" 68 | # s.osx.deployment_target = "10.7" 69 | 70 | 71 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 72 | # 73 | # Specify the location from where the source should be retrieved. 74 | # Supports git, hg, bzr, svn and HTTP. 75 | # 76 | 77 | s.source = { :git => "https://github.com/sonsongithub/UZTextView.git", :tag => "v1.0.6" } 78 | 79 | 80 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 81 | # 82 | # CocoaPods is smart about how it includes source code. For source files 83 | # giving a folder will include any swift, h, m, mm, c & cpp files. 84 | # For header files it will include any header in the folder. 85 | # Not including the public_header_files will make all headers public. 86 | # 87 | 88 | s.source_files = "UZTextView/*" 89 | s.public_header_files = "UZTextView/UZTextView.h" 90 | 91 | 92 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 93 | # 94 | # A list of resources included with the Pod. These are copied into the 95 | # target bundle with a build phase script. Anything else will be cleaned. 96 | # You can preserve files from being cleaned, please don't preserve 97 | # non-essential files like tests, examples and documentation. 98 | # 99 | 100 | # s.resource = "icon.png" 101 | # s.resources = "Resources/*.png" 102 | 103 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 104 | 105 | 106 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 107 | # 108 | # Link your library with frameworks, or libraries. Libraries do not include 109 | # the lib prefix of their name. 110 | # 111 | 112 | # s.framework = "SomeFramework" 113 | s.frameworks = "QuartzCore", "CoreText" 114 | 115 | # s.library = "iconv" 116 | # s.libraries = "iconv", "xml2" 117 | 118 | 119 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 120 | # 121 | # If your library depends on compiler flags you can set them in the xcconfig hash 122 | # where they will only apply to your library. If you depend on other Podspecs 123 | # you can include multiple dependencies to ensure it works. 124 | 125 | s.requires_arc = true 126 | 127 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 128 | # s.dependency "JSONKit", "~> 1.4" 129 | 130 | end 131 | -------------------------------------------------------------------------------- /UZTextView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 14590BB51F009717002A31A0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14590BB41F009717002A31A0 /* AppDelegate.swift */; }; 11 | 14590BBA1F009717002A31A0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 14590BB81F009717002A31A0 /* Main.storyboard */; }; 12 | 14590BBC1F009717002A31A0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 14590BBB1F009717002A31A0 /* Assets.xcassets */; }; 13 | 14590BBF1F009717002A31A0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 14590BBD1F009717002A31A0 /* LaunchScreen.storyboard */; }; 14 | 14590BCD1F0097B4002A31A0 /* MainTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14590BC91F0097B4002A31A0 /* MainTableViewController.swift */; }; 15 | 14590BCE1F0097B4002A31A0 /* mona.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 14590BCA1F0097B4002A31A0 /* mona.ttf */; }; 16 | 14590BCF1F0097B4002A31A0 /* SampleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14590BCB1F0097B4002A31A0 /* SampleCell.swift */; }; 17 | 14590BD01F0097B4002A31A0 /* source.json in Resources */ = {isa = PBXBuildFile; fileRef = 14590BCC1F0097B4002A31A0 /* source.json */; }; 18 | 14590BD41F0099AE002A31A0 /* UZTextView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1485325C1E5354A500702442 /* UZTextView.framework */; }; 19 | 14590BD51F0099AE002A31A0 /* UZTextView.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1485325C1E5354A500702442 /* UZTextView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 20 | 14590BD61F0099EE002A31A0 /* UZTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F8867017C2BB02006F5514 /* UZTextView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | 148532691E5354AC00702442 /* UZTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F8867217C2BB02006F5514 /* UZTextView.m */; }; 22 | 1485326A1E5354AC00702442 /* UZCursorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F886E517C2BFA0006F5514 /* UZCursorView.m */; }; 23 | 1485326B1E5354AC00702442 /* UZLoupeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F886E717C2BFA0006F5514 /* UZLoupeView.m */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXContainerItemProxy section */ 27 | 14590BD71F009A69002A31A0 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = 14F8866017C2BB02006F5514 /* Project object */; 30 | proxyType = 1; 31 | remoteGlobalIDString = 1485325B1E5354A500702442; 32 | remoteInfo = UZTextView; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXCopyFilesBuildPhase section */ 37 | 14590BC81F009751002A31A0 /* Embed Frameworks */ = { 38 | isa = PBXCopyFilesBuildPhase; 39 | buildActionMask = 2147483647; 40 | dstPath = ""; 41 | dstSubfolderSpec = 10; 42 | files = ( 43 | 14590BD51F0099AE002A31A0 /* UZTextView.framework in Embed Frameworks */, 44 | ); 45 | name = "Embed Frameworks"; 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXCopyFilesBuildPhase section */ 49 | 50 | /* Begin PBXFileReference section */ 51 | 14590BB21F009717002A31A0 /* UZTextViewSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UZTextViewSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 14590BB41F009717002A31A0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 53 | 14590BB91F009717002A31A0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 54 | 14590BBB1F009717002A31A0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 55 | 14590BBE1F009717002A31A0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 56 | 14590BC01F009717002A31A0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 14590BC91F0097B4002A31A0 /* MainTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTableViewController.swift; sourceTree = ""; }; 58 | 14590BCA1F0097B4002A31A0 /* mona.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = mona.ttf; sourceTree = ""; }; 59 | 14590BCB1F0097B4002A31A0 /* SampleCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleCell.swift; sourceTree = ""; }; 60 | 14590BCC1F0097B4002A31A0 /* source.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = source.json; sourceTree = ""; }; 61 | 14590BD91F009BAA002A31A0 /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; 62 | 1485325C1E5354A500702442 /* UZTextView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = UZTextView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | 1485325F1E5354A500702442 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 64 | 14F8866B17C2BB02006F5514 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 65 | 14F8867017C2BB02006F5514 /* UZTextView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UZTextView.h; sourceTree = ""; }; 66 | 14F8867217C2BB02006F5514 /* UZTextView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UZTextView.m; sourceTree = ""; }; 67 | 14F8867917C2BB02006F5514 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 68 | 14F8869717C2BB4A006F5514 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 69 | 14F886E417C2BFA0006F5514 /* UZCursorView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UZCursorView.h; sourceTree = ""; }; 70 | 14F886E517C2BFA0006F5514 /* UZCursorView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UZCursorView.m; sourceTree = ""; }; 71 | 14F886E617C2BFA0006F5514 /* UZLoupeView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UZLoupeView.h; sourceTree = ""; }; 72 | 14F886E717C2BFA0006F5514 /* UZLoupeView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UZLoupeView.m; sourceTree = ""; }; 73 | /* End PBXFileReference section */ 74 | 75 | /* Begin PBXFrameworksBuildPhase section */ 76 | 14590BAF1F009717002A31A0 /* Frameworks */ = { 77 | isa = PBXFrameworksBuildPhase; 78 | buildActionMask = 2147483647; 79 | files = ( 80 | 14590BD41F0099AE002A31A0 /* UZTextView.framework in Frameworks */, 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | 148532581E5354A500702442 /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | /* End PBXFrameworksBuildPhase section */ 92 | 93 | /* Begin PBXGroup section */ 94 | 14590BB31F009717002A31A0 /* UZTextViewSample */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 14590BC91F0097B4002A31A0 /* MainTableViewController.swift */, 98 | 14590BCA1F0097B4002A31A0 /* mona.ttf */, 99 | 14590BCB1F0097B4002A31A0 /* SampleCell.swift */, 100 | 14590BCC1F0097B4002A31A0 /* source.json */, 101 | 14590BB41F009717002A31A0 /* AppDelegate.swift */, 102 | 14590BB81F009717002A31A0 /* Main.storyboard */, 103 | 14590BBB1F009717002A31A0 /* Assets.xcassets */, 104 | 14590BBD1F009717002A31A0 /* LaunchScreen.storyboard */, 105 | 14590BC01F009717002A31A0 /* Info.plist */, 106 | 14590BD91F009BAA002A31A0 /* Bridging-Header.h */, 107 | ); 108 | path = UZTextViewSample; 109 | sourceTree = ""; 110 | }; 111 | 14F8865F17C2BB02006F5514 = { 112 | isa = PBXGroup; 113 | children = ( 114 | 14F8866D17C2BB02006F5514 /* UZTextView */, 115 | 14590BB31F009717002A31A0 /* UZTextViewSample */, 116 | 14F8866A17C2BB02006F5514 /* Frameworks */, 117 | 14F8866917C2BB02006F5514 /* Products */, 118 | ); 119 | sourceTree = ""; 120 | }; 121 | 14F8866917C2BB02006F5514 /* Products */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 1485325C1E5354A500702442 /* UZTextView.framework */, 125 | 14590BB21F009717002A31A0 /* UZTextViewSample.app */, 126 | ); 127 | name = Products; 128 | sourceTree = ""; 129 | }; 130 | 14F8866A17C2BB02006F5514 /* Frameworks */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 14F8869717C2BB4A006F5514 /* CoreGraphics.framework */, 134 | 14F8866B17C2BB02006F5514 /* Foundation.framework */, 135 | 14F8867917C2BB02006F5514 /* XCTest.framework */, 136 | ); 137 | name = Frameworks; 138 | sourceTree = ""; 139 | }; 140 | 14F8866D17C2BB02006F5514 /* UZTextView */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 1485325F1E5354A500702442 /* Info.plist */, 144 | 14F8867017C2BB02006F5514 /* UZTextView.h */, 145 | 14F8867217C2BB02006F5514 /* UZTextView.m */, 146 | 14F886E417C2BFA0006F5514 /* UZCursorView.h */, 147 | 14F886E517C2BFA0006F5514 /* UZCursorView.m */, 148 | 14F886E617C2BFA0006F5514 /* UZLoupeView.h */, 149 | 14F886E717C2BFA0006F5514 /* UZLoupeView.m */, 150 | ); 151 | path = UZTextView; 152 | sourceTree = ""; 153 | }; 154 | /* End PBXGroup section */ 155 | 156 | /* Begin PBXHeadersBuildPhase section */ 157 | 148532591E5354A500702442 /* Headers */ = { 158 | isa = PBXHeadersBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | 14590BD61F0099EE002A31A0 /* UZTextView.h in Headers */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | /* End PBXHeadersBuildPhase section */ 166 | 167 | /* Begin PBXNativeTarget section */ 168 | 14590BB11F009717002A31A0 /* UZTextViewSample */ = { 169 | isa = PBXNativeTarget; 170 | buildConfigurationList = 14590BC11F009717002A31A0 /* Build configuration list for PBXNativeTarget "UZTextViewSample" */; 171 | buildPhases = ( 172 | 14590BAE1F009717002A31A0 /* Sources */, 173 | 14590BAF1F009717002A31A0 /* Frameworks */, 174 | 14590BB01F009717002A31A0 /* Resources */, 175 | 14590BC81F009751002A31A0 /* Embed Frameworks */, 176 | ); 177 | buildRules = ( 178 | ); 179 | dependencies = ( 180 | 14590BD81F009A69002A31A0 /* PBXTargetDependency */, 181 | ); 182 | name = UZTextViewSample; 183 | productName = UZTextViewSample; 184 | productReference = 14590BB21F009717002A31A0 /* UZTextViewSample.app */; 185 | productType = "com.apple.product-type.application"; 186 | }; 187 | 1485325B1E5354A500702442 /* UZTextView */ = { 188 | isa = PBXNativeTarget; 189 | buildConfigurationList = 148532651E5354A500702442 /* Build configuration list for PBXNativeTarget "UZTextView" */; 190 | buildPhases = ( 191 | 148532571E5354A500702442 /* Sources */, 192 | 148532581E5354A500702442 /* Frameworks */, 193 | 148532591E5354A500702442 /* Headers */, 194 | 1485325A1E5354A500702442 /* Resources */, 195 | ); 196 | buildRules = ( 197 | ); 198 | dependencies = ( 199 | ); 200 | name = UZTextView; 201 | productName = UZTextView; 202 | productReference = 1485325C1E5354A500702442 /* UZTextView.framework */; 203 | productType = "com.apple.product-type.framework"; 204 | }; 205 | /* End PBXNativeTarget section */ 206 | 207 | /* Begin PBXProject section */ 208 | 14F8866017C2BB02006F5514 /* Project object */ = { 209 | isa = PBXProject; 210 | attributes = { 211 | LastSwiftUpdateCheck = 0830; 212 | LastUpgradeCheck = 0830; 213 | ORGANIZATIONNAME = sonson; 214 | TargetAttributes = { 215 | 14590BB11F009717002A31A0 = { 216 | CreatedOnToolsVersion = 8.3.3; 217 | DevelopmentTeam = JP866VWWSD; 218 | ProvisioningStyle = Automatic; 219 | }; 220 | 1485325B1E5354A500702442 = { 221 | CreatedOnToolsVersion = 8.2; 222 | DevelopmentTeam = JP866VWWSD; 223 | ProvisioningStyle = Automatic; 224 | }; 225 | }; 226 | }; 227 | buildConfigurationList = 14F8866317C2BB02006F5514 /* Build configuration list for PBXProject "UZTextView" */; 228 | compatibilityVersion = "Xcode 3.2"; 229 | developmentRegion = English; 230 | hasScannedForEncodings = 0; 231 | knownRegions = ( 232 | en, 233 | Base, 234 | ); 235 | mainGroup = 14F8865F17C2BB02006F5514; 236 | productRefGroup = 14F8866917C2BB02006F5514 /* Products */; 237 | projectDirPath = ""; 238 | projectRoot = ""; 239 | targets = ( 240 | 1485325B1E5354A500702442 /* UZTextView */, 241 | 14590BB11F009717002A31A0 /* UZTextViewSample */, 242 | ); 243 | }; 244 | /* End PBXProject section */ 245 | 246 | /* Begin PBXResourcesBuildPhase section */ 247 | 14590BB01F009717002A31A0 /* Resources */ = { 248 | isa = PBXResourcesBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | 14590BBF1F009717002A31A0 /* LaunchScreen.storyboard in Resources */, 252 | 14590BBC1F009717002A31A0 /* Assets.xcassets in Resources */, 253 | 14590BBA1F009717002A31A0 /* Main.storyboard in Resources */, 254 | 14590BCE1F0097B4002A31A0 /* mona.ttf in Resources */, 255 | 14590BD01F0097B4002A31A0 /* source.json in Resources */, 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | 1485325A1E5354A500702442 /* Resources */ = { 260 | isa = PBXResourcesBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | }; 266 | /* End PBXResourcesBuildPhase section */ 267 | 268 | /* Begin PBXSourcesBuildPhase section */ 269 | 14590BAE1F009717002A31A0 /* Sources */ = { 270 | isa = PBXSourcesBuildPhase; 271 | buildActionMask = 2147483647; 272 | files = ( 273 | 14590BCF1F0097B4002A31A0 /* SampleCell.swift in Sources */, 274 | 14590BCD1F0097B4002A31A0 /* MainTableViewController.swift in Sources */, 275 | 14590BB51F009717002A31A0 /* AppDelegate.swift in Sources */, 276 | ); 277 | runOnlyForDeploymentPostprocessing = 0; 278 | }; 279 | 148532571E5354A500702442 /* Sources */ = { 280 | isa = PBXSourcesBuildPhase; 281 | buildActionMask = 2147483647; 282 | files = ( 283 | 148532691E5354AC00702442 /* UZTextView.m in Sources */, 284 | 1485326A1E5354AC00702442 /* UZCursorView.m in Sources */, 285 | 1485326B1E5354AC00702442 /* UZLoupeView.m in Sources */, 286 | ); 287 | runOnlyForDeploymentPostprocessing = 0; 288 | }; 289 | /* End PBXSourcesBuildPhase section */ 290 | 291 | /* Begin PBXTargetDependency section */ 292 | 14590BD81F009A69002A31A0 /* PBXTargetDependency */ = { 293 | isa = PBXTargetDependency; 294 | target = 1485325B1E5354A500702442 /* UZTextView */; 295 | targetProxy = 14590BD71F009A69002A31A0 /* PBXContainerItemProxy */; 296 | }; 297 | /* End PBXTargetDependency section */ 298 | 299 | /* Begin PBXVariantGroup section */ 300 | 14590BB81F009717002A31A0 /* Main.storyboard */ = { 301 | isa = PBXVariantGroup; 302 | children = ( 303 | 14590BB91F009717002A31A0 /* Base */, 304 | ); 305 | name = Main.storyboard; 306 | sourceTree = ""; 307 | }; 308 | 14590BBD1F009717002A31A0 /* LaunchScreen.storyboard */ = { 309 | isa = PBXVariantGroup; 310 | children = ( 311 | 14590BBE1F009717002A31A0 /* Base */, 312 | ); 313 | name = LaunchScreen.storyboard; 314 | sourceTree = ""; 315 | }; 316 | /* End PBXVariantGroup section */ 317 | 318 | /* Begin XCBuildConfiguration section */ 319 | 14590BC21F009717002A31A0 /* Debug */ = { 320 | isa = XCBuildConfiguration; 321 | buildSettings = { 322 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 323 | CLANG_ANALYZER_NONNULL = YES; 324 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 325 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 326 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 327 | DEBUG_INFORMATION_FORMAT = dwarf; 328 | DEVELOPMENT_TEAM = JP866VWWSD; 329 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 330 | GCC_WARN_UNUSED_FUNCTION = YES; 331 | INFOPLIST_FILE = UZTextViewSample/Info.plist; 332 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 333 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 334 | MTL_ENABLE_DEBUG_INFO = YES; 335 | PRODUCT_BUNDLE_IDENTIFIER = com.sonson.UZTextViewSample; 336 | PRODUCT_NAME = "$(TARGET_NAME)"; 337 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 338 | SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/UZTextViewSample/Bridging-Header.h"; 339 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 340 | SWIFT_VERSION = 3.0; 341 | }; 342 | name = Debug; 343 | }; 344 | 14590BC31F009717002A31A0 /* Release */ = { 345 | isa = XCBuildConfiguration; 346 | buildSettings = { 347 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 348 | CLANG_ANALYZER_NONNULL = YES; 349 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 350 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 351 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 352 | COPY_PHASE_STRIP = NO; 353 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 354 | DEVELOPMENT_TEAM = JP866VWWSD; 355 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 356 | GCC_WARN_UNUSED_FUNCTION = YES; 357 | INFOPLIST_FILE = UZTextViewSample/Info.plist; 358 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 359 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 360 | MTL_ENABLE_DEBUG_INFO = NO; 361 | PRODUCT_BUNDLE_IDENTIFIER = com.sonson.UZTextViewSample; 362 | PRODUCT_NAME = "$(TARGET_NAME)"; 363 | SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/UZTextViewSample/Bridging-Header.h"; 364 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 365 | SWIFT_VERSION = 3.0; 366 | }; 367 | name = Release; 368 | }; 369 | 148532661E5354A500702442 /* Debug */ = { 370 | isa = XCBuildConfiguration; 371 | buildSettings = { 372 | CLANG_ANALYZER_NONNULL = YES; 373 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 374 | CODE_SIGN_IDENTITY = ""; 375 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 376 | CURRENT_PROJECT_VERSION = 1; 377 | DEBUG_INFORMATION_FORMAT = dwarf; 378 | DEFINES_MODULE = YES; 379 | DEVELOPMENT_TEAM = JP866VWWSD; 380 | DYLIB_COMPATIBILITY_VERSION = 1; 381 | DYLIB_CURRENT_VERSION = 1; 382 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 383 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 384 | GCC_WARN_UNUSED_FUNCTION = YES; 385 | INFOPLIST_FILE = UZTextView/Info.plist; 386 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 387 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 388 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 389 | MTL_ENABLE_DEBUG_INFO = YES; 390 | PRODUCT_BUNDLE_IDENTIFIER = com.sonson.UZTextView; 391 | PRODUCT_NAME = "$(TARGET_NAME)"; 392 | SKIP_INSTALL = YES; 393 | TARGETED_DEVICE_FAMILY = "1,2"; 394 | VERSIONING_SYSTEM = "apple-generic"; 395 | VERSION_INFO_PREFIX = ""; 396 | }; 397 | name = Debug; 398 | }; 399 | 148532671E5354A500702442 /* Release */ = { 400 | isa = XCBuildConfiguration; 401 | buildSettings = { 402 | CLANG_ANALYZER_NONNULL = YES; 403 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 404 | CODE_SIGN_IDENTITY = ""; 405 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 406 | COPY_PHASE_STRIP = NO; 407 | CURRENT_PROJECT_VERSION = 1; 408 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 409 | DEFINES_MODULE = YES; 410 | DEVELOPMENT_TEAM = JP866VWWSD; 411 | DYLIB_COMPATIBILITY_VERSION = 1; 412 | DYLIB_CURRENT_VERSION = 1; 413 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 414 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 415 | GCC_WARN_UNUSED_FUNCTION = YES; 416 | INFOPLIST_FILE = UZTextView/Info.plist; 417 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 418 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 419 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 420 | MTL_ENABLE_DEBUG_INFO = NO; 421 | PRODUCT_BUNDLE_IDENTIFIER = com.sonson.UZTextView; 422 | PRODUCT_NAME = "$(TARGET_NAME)"; 423 | SKIP_INSTALL = YES; 424 | TARGETED_DEVICE_FAMILY = "1,2"; 425 | VERSIONING_SYSTEM = "apple-generic"; 426 | VERSION_INFO_PREFIX = ""; 427 | }; 428 | name = Release; 429 | }; 430 | 14F8868917C2BB02006F5514 /* Debug */ = { 431 | isa = XCBuildConfiguration; 432 | buildSettings = { 433 | ALWAYS_SEARCH_USER_PATHS = NO; 434 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 435 | CLANG_CXX_LIBRARY = "libc++"; 436 | CLANG_ENABLE_MODULES = YES; 437 | CLANG_ENABLE_OBJC_ARC = YES; 438 | CLANG_WARN_BOOL_CONVERSION = YES; 439 | CLANG_WARN_CONSTANT_CONVERSION = YES; 440 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 441 | CLANG_WARN_EMPTY_BODY = YES; 442 | CLANG_WARN_ENUM_CONVERSION = YES; 443 | CLANG_WARN_INFINITE_RECURSION = YES; 444 | CLANG_WARN_INT_CONVERSION = YES; 445 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 446 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 447 | CLANG_WARN_UNREACHABLE_CODE = YES; 448 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 449 | COPY_PHASE_STRIP = NO; 450 | ENABLE_STRICT_OBJC_MSGSEND = YES; 451 | ENABLE_TESTABILITY = YES; 452 | GCC_C_LANGUAGE_STANDARD = gnu99; 453 | GCC_DYNAMIC_NO_PIC = NO; 454 | GCC_NO_COMMON_BLOCKS = YES; 455 | GCC_OPTIMIZATION_LEVEL = 0; 456 | GCC_PREPROCESSOR_DEFINITIONS = ( 457 | "DEBUG=1", 458 | "$(inherited)", 459 | ); 460 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 461 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 462 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 463 | GCC_WARN_UNDECLARED_SELECTOR = YES; 464 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 465 | GCC_WARN_UNUSED_FUNCTION = NO; 466 | GCC_WARN_UNUSED_VARIABLE = YES; 467 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 468 | ONLY_ACTIVE_ARCH = YES; 469 | SDKROOT = iphoneos; 470 | }; 471 | name = Debug; 472 | }; 473 | 14F8868A17C2BB02006F5514 /* Release */ = { 474 | isa = XCBuildConfiguration; 475 | buildSettings = { 476 | ALWAYS_SEARCH_USER_PATHS = NO; 477 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 478 | CLANG_CXX_LIBRARY = "libc++"; 479 | CLANG_ENABLE_MODULES = YES; 480 | CLANG_ENABLE_OBJC_ARC = YES; 481 | CLANG_WARN_BOOL_CONVERSION = YES; 482 | CLANG_WARN_CONSTANT_CONVERSION = YES; 483 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 484 | CLANG_WARN_EMPTY_BODY = YES; 485 | CLANG_WARN_ENUM_CONVERSION = YES; 486 | CLANG_WARN_INFINITE_RECURSION = YES; 487 | CLANG_WARN_INT_CONVERSION = YES; 488 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 489 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 490 | CLANG_WARN_UNREACHABLE_CODE = YES; 491 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 492 | COPY_PHASE_STRIP = YES; 493 | ENABLE_NS_ASSERTIONS = NO; 494 | ENABLE_STRICT_OBJC_MSGSEND = YES; 495 | GCC_C_LANGUAGE_STANDARD = gnu99; 496 | GCC_NO_COMMON_BLOCKS = YES; 497 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 498 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 499 | GCC_WARN_UNDECLARED_SELECTOR = YES; 500 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 501 | GCC_WARN_UNUSED_FUNCTION = NO; 502 | GCC_WARN_UNUSED_VARIABLE = YES; 503 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 504 | SDKROOT = iphoneos; 505 | VALIDATE_PRODUCT = YES; 506 | }; 507 | name = Release; 508 | }; 509 | /* End XCBuildConfiguration section */ 510 | 511 | /* Begin XCConfigurationList section */ 512 | 14590BC11F009717002A31A0 /* Build configuration list for PBXNativeTarget "UZTextViewSample" */ = { 513 | isa = XCConfigurationList; 514 | buildConfigurations = ( 515 | 14590BC21F009717002A31A0 /* Debug */, 516 | 14590BC31F009717002A31A0 /* Release */, 517 | ); 518 | defaultConfigurationIsVisible = 0; 519 | }; 520 | 148532651E5354A500702442 /* Build configuration list for PBXNativeTarget "UZTextView" */ = { 521 | isa = XCConfigurationList; 522 | buildConfigurations = ( 523 | 148532661E5354A500702442 /* Debug */, 524 | 148532671E5354A500702442 /* Release */, 525 | ); 526 | defaultConfigurationIsVisible = 0; 527 | defaultConfigurationName = Release; 528 | }; 529 | 14F8866317C2BB02006F5514 /* Build configuration list for PBXProject "UZTextView" */ = { 530 | isa = XCConfigurationList; 531 | buildConfigurations = ( 532 | 14F8868917C2BB02006F5514 /* Debug */, 533 | 14F8868A17C2BB02006F5514 /* Release */, 534 | ); 535 | defaultConfigurationIsVisible = 0; 536 | defaultConfigurationName = Release; 537 | }; 538 | /* End XCConfigurationList section */ 539 | }; 540 | rootObject = 14F8866017C2BB02006F5514 /* Project object */; 541 | } 542 | -------------------------------------------------------------------------------- /UZTextView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /UZTextView.xcodeproj/xcshareddata/xcschemes/UZTextView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /UZTextView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /UZTextView/UZCursorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UZCursorView.h 3 | // UZTextView 4 | // 5 | // Created by sonson on 2013/07/19. 6 | // Copyright (c) 2013年 sonson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum _UZTextViewCursorDirection { 12 | UZTextViewUpCursor = 0, 13 | UZTextViewDownCursor = 1 14 | }UZTextViewCursorDirection; 15 | 16 | @interface UZCursorView : UIView { 17 | UZTextViewCursorDirection _direction; 18 | } 19 | - (id)initWithCursorDirection:(UZTextViewCursorDirection)direction; 20 | + (CGRect)cursorRectWithEdgeRect:(CGRect)rect cursorDirection:(UZTextViewCursorDirection)direction; 21 | @end 22 | -------------------------------------------------------------------------------- /UZTextView/UZCursorView.m: -------------------------------------------------------------------------------- 1 | // 2 | // UZCursorView.m 3 | // UZTextView 4 | // 5 | // Created by sonson on 2013/07/19. 6 | // Copyright (c) 2013年 sonson. All rights reserved. 7 | // 8 | 9 | #import "UZCursorView.h" 10 | #import "UZTextView.h" 11 | 12 | #define UZ_CURSOR_BALL_RADIUS 4 13 | #define UZ_CURSOR_POLE_WIDTH 2 14 | #define UZ_CURSOR_POLE_Y_MARGIN 7 15 | 16 | #define UZ_CURSOR_HORIZONTAL_MARGIN1 30 17 | #define UZ_CURSOR_HORIZONTAL_MARGIN2 10 18 | #define UZ_CURSOR_VERTICAL_MARGIN 20 19 | 20 | @implementation UZCursorView 21 | 22 | + (CGRect)cursorRectWithEdgeRect:(CGRect)rect cursorDirection:(UZTextViewCursorDirection)direction { 23 | if (direction == UZTextViewUpCursor) { 24 | return CGRectMake(rect.origin.x - UZ_CURSOR_HORIZONTAL_MARGIN1, 25 | rect.origin.y - UZ_CURSOR_VERTICAL_MARGIN, 26 | UZ_CURSOR_HORIZONTAL_MARGIN1 + UZ_CURSOR_HORIZONTAL_MARGIN2, 27 | rect.size.height + UZ_CURSOR_VERTICAL_MARGIN * 2); 28 | } 29 | else { 30 | return CGRectMake(rect.origin.x - UZ_CURSOR_HORIZONTAL_MARGIN2, 31 | rect.origin.y - UZ_CURSOR_VERTICAL_MARGIN, 32 | UZ_CURSOR_HORIZONTAL_MARGIN1 + UZ_CURSOR_HORIZONTAL_MARGIN2, 33 | rect.size.height + UZ_CURSOR_VERTICAL_MARGIN * 2); 34 | } 35 | } 36 | 37 | - (void)dealloc { 38 | if (UZTextView.checkMemoryLeak) { 39 | NSLog(@"UZCursorView has been released"); 40 | } 41 | } 42 | 43 | - (id)initWithCursorDirection:(UZTextViewCursorDirection)direction { 44 | self = [super initWithFrame:CGRectZero]; 45 | _direction = direction; 46 | self.backgroundColor = [UIColor clearColor]; 47 | return self; 48 | } 49 | 50 | - (void)layoutSubviews { 51 | [super layoutSubviews]; 52 | [self setNeedsDisplay]; 53 | } 54 | 55 | - (void)drawRect:(CGRect)rect { 56 | CGContextRef context = UIGraphicsGetCurrentContext(); 57 | 58 | CGRect lineRect; 59 | CGPoint circleCenter; 60 | 61 | #ifdef _UZTEXTVIEW_DEBUG_ 62 | // for debug 63 | [[UIColor blueColor] setStroke]; 64 | CGContextStrokeRect(context, CGRectInset(rect, 1, 1)); 65 | #endif 66 | 67 | if (_direction == UZTextViewUpCursor) { 68 | circleCenter = CGPointMake(UZ_CURSOR_HORIZONTAL_MARGIN1 - 1, UZ_CURSOR_VERTICAL_MARGIN - UZ_CURSOR_POLE_Y_MARGIN); 69 | lineRect = CGRectMake( 70 | circleCenter.x - UZ_CURSOR_POLE_WIDTH/2, circleCenter.y, 71 | UZ_CURSOR_POLE_WIDTH, rect.size.height - UZ_CURSOR_VERTICAL_MARGIN*2 + UZ_CURSOR_POLE_Y_MARGIN 72 | ); 73 | } 74 | else { 75 | circleCenter = CGPointMake(UZ_CURSOR_HORIZONTAL_MARGIN2, rect.size.height - (UZ_CURSOR_VERTICAL_MARGIN - UZ_CURSOR_POLE_Y_MARGIN)); 76 | lineRect = CGRectMake( 77 | circleCenter.x - UZ_CURSOR_POLE_WIDTH/2, circleCenter.y - (rect.size.height - UZ_CURSOR_VERTICAL_MARGIN*2 + UZ_CURSOR_POLE_Y_MARGIN), 78 | UZ_CURSOR_POLE_WIDTH, rect.size.height - UZ_CURSOR_VERTICAL_MARGIN*2 + UZ_CURSOR_POLE_Y_MARGIN 79 | ); 80 | } 81 | CGContextAddArc(context, circleCenter.x, circleCenter.y, UZ_CURSOR_BALL_RADIUS, 0, 2 * M_PI, 0); 82 | CGContextClosePath(context); 83 | [[self.tintColor colorWithAlphaComponent:1] setFill]; 84 | CGContextFillPath(context); 85 | CGContextFillRect(context, lineRect); 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /UZTextView/UZLoupeView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UZLoupeView.h 3 | // UZTextView 4 | // 5 | // Created by sonson on 2013/07/10. 6 | // Copyright (c) 2013年 sonson. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface UZLoupeView : UIView { 13 | CGFloat _loupeRadius; 14 | UIImage *_image; 15 | } 16 | - (id)initWithRadius:(CGFloat)radius; 17 | - (void)setVisible:(BOOL)visible animated:(BOOL)animated; 18 | - (void)updateAtLocation:(CGPoint)location textView:(UIView*)textView; 19 | @property (nonatomic, copy) UIColor *textViewBackgroundColor; 20 | @end 21 | -------------------------------------------------------------------------------- /UZTextView/UZLoupeView.m: -------------------------------------------------------------------------------- 1 | // 2 | // UZLoupeView.m 3 | // UZTextView 4 | // 5 | // Created by sonson on 2013/07/10. 6 | // Copyright (c) 2013年 sonson. All rights reserved. 7 | // 8 | 9 | #import "UZLoupeView.h" 10 | #import "UZTextView.h" 11 | 12 | // Animation duration 13 | #define UZ_LOUPE_NO_ANIMATION_DUARTION 0.0001 14 | #define UZ_LOUPE_ANIMATION_DUARTION 0.2 15 | 16 | // Rendering parameter 17 | #define UZ_LOUPE_OUTLINE_STROKE_WIDTH 2 18 | 19 | // Animation identifier 20 | static NSString * const UZCoreAnimationName = @"_UZCoreAnimationName"; 21 | static NSString * const UZLoupeViewAppearingAnimation = @"_UZLoupeViewAppearingAnimation"; 22 | static NSString * const UZLoupeViewDisappearingAnimation = @"_UZLoupeViewDisappearingAnimation"; 23 | 24 | // Declare preprocessor 'TARGET_IS_EXTENSION' if you use this class inside extension. 25 | #ifdef TARGET_IS_EXTENSION 26 | #define _WITHOUT_UIAPPLICATION 27 | #endif 28 | 29 | @interface UZLoupeView() { 30 | } 31 | @end 32 | 33 | @implementation UZLoupeView 34 | 35 | #ifdef _WITHOUT_UIAPPLICATION 36 | 37 | UIView *searchKeyWindow(UIView* view) { 38 | UIView *p = view.superview; 39 | if ([p isKindOfClass:[UIWindow class]]) { 40 | return view; 41 | } 42 | if (p == nil) 43 | return view; 44 | return searchKeyWindow(p); 45 | } 46 | 47 | #endif 48 | 49 | #pragma mark - Create Core Animation objects for appearing 50 | 51 | - (CAAnimation*)alphaAnimationWhileAppearing { 52 | CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; 53 | animation.values = @[@(0), @(0.97), @(1)]; 54 | animation.keyTimes = @[@(0), @(0.7), @(1)]; 55 | return animation; 56 | } 57 | 58 | - (CAAnimation*)transformScaleAnimationWhileAppearing { 59 | CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; 60 | animation.values = @[@(0), @(1)]; 61 | animation.keyTimes = @[@(0), @(1)]; 62 | return animation; 63 | } 64 | 65 | - (CAAnimation*)translationAnimationWhileAppearing { 66 | CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.y"]; 67 | animation.keyTimes = @[@(0), @(1)]; 68 | animation.values = @[@(self.frame.size.height/2), @(0)]; 69 | return animation; 70 | } 71 | 72 | #pragma mark - Create Core Animation objects for disappearing 73 | 74 | - (CAAnimation*)alphaAnimationWhileDisappearing { 75 | CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; 76 | animation.values = @[@(1.0), @(0.97), @(0)]; 77 | animation.keyTimes = @[@(0), @(0.7), @(1)]; 78 | return animation; 79 | } 80 | 81 | - (CAAnimation*)transformScaleAnimationWhileDisapearing { 82 | CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; 83 | animation.values = @[@(1), @(0)]; 84 | animation.keyTimes = @[@(0), @(1)]; 85 | return animation; 86 | } 87 | 88 | - (CAAnimation*)translationAnimationWhileDisappearing { 89 | CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.y"]; 90 | animation.keyTimes = @[@(0), @(1)]; 91 | animation.values = @[@(0), @(self.frame.size.height/2)]; 92 | return animation; 93 | } 94 | 95 | #pragma mark - Animate 96 | 97 | - (void)animateForAppearingWithDuration:(CGFloat)duration { 98 | // decide whether animation should be started or not 99 | if (!self.hidden) 100 | return; 101 | self.hidden = NO; 102 | 103 | // make animation group 104 | CAAnimationGroup *group = [CAAnimationGroup animation]; 105 | group.animations = @[[self transformScaleAnimationWhileAppearing], [self translationAnimationWhileAppearing], [self alphaAnimationWhileAppearing]]; 106 | group.duration = duration; 107 | group.removedOnCompletion = NO; 108 | group.fillMode = kCAFillModeForwards; 109 | 110 | // commit animation 111 | [self.layer addAnimation:group forKey:UZLoupeViewAppearingAnimation]; 112 | } 113 | 114 | - (void)animateForDisappearingWithDuration:(CGFloat)duration { 115 | // make group 116 | CAAnimationGroup *group = [CAAnimationGroup animation]; 117 | group.animations = @[[self translationAnimationWhileDisappearing], [self transformScaleAnimationWhileDisapearing], [self alphaAnimationWhileDisappearing]]; 118 | group.duration = duration; 119 | group.removedOnCompletion = NO; 120 | group.fillMode = kCAFillModeForwards; 121 | 122 | // commit animation 123 | [CATransaction begin]; 124 | [CATransaction setCompletionBlock:^{ 125 | self.hidden = YES; 126 | self.layer.transform = CATransform3DIdentity; 127 | }]; 128 | [self.layer addAnimation:group forKey:UZLoupeViewDisappearingAnimation]; 129 | [CATransaction commit]; 130 | } 131 | 132 | #pragma mark - Public 133 | 134 | - (void)setVisible:(BOOL)visible animated:(BOOL)animated { 135 | CGFloat duration = animated ? UZ_LOUPE_ANIMATION_DUARTION : UZ_LOUPE_NO_ANIMATION_DUARTION; 136 | if (visible) 137 | [self animateForAppearingWithDuration:duration]; 138 | else 139 | [self animateForDisappearingWithDuration:duration]; 140 | } 141 | 142 | - (void)updateAtLocation:(CGPoint)location textView:(UIView*)textView { 143 | CGFloat offset = _loupeRadius; 144 | CGFloat angle = 0; 145 | 146 | #ifdef _WITHOUT_UIAPPLICATION 147 | UIView *targetView = (UIWindow*)searchKeyWindow(self); 148 | #else 149 | UIView *targetView = [UIApplication sharedApplication].keyWindow.rootViewController.view; 150 | #endif 151 | CGPoint c = [targetView convertPoint:CGPointMake(location.x, location.y) fromView:textView]; 152 | 153 | // Create UIImage from source view controller's view. 154 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(_loupeRadius * 2, _loupeRadius * 2), NO, 0); 155 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 156 | CGContextTranslateCTM(ctx, -location.x + _loupeRadius, -location.y + _loupeRadius); 157 | 158 | c.y -= offset; 159 | 160 | // adjust orientation 161 | CGContextTranslateCTM(ctx, location.x, location.y); 162 | CGContextRotateCTM(ctx, angle); 163 | CGContextTranslateCTM(ctx, -location.x, -location.y); 164 | 165 | // Drawing code 166 | self.hidden = YES; 167 | [textView.layer renderInContext:ctx]; 168 | self.hidden = NO; 169 | 170 | // Create bitmap 171 | _image = UIGraphicsGetImageFromCurrentImageContext(); 172 | UIGraphicsEndImageContext(); 173 | 174 | // update location 175 | [targetView addSubview:self]; 176 | 177 | [self setCenter:c]; 178 | } 179 | 180 | #pragma mark - Override 181 | 182 | - (void)dealloc { 183 | if (UZTextView.checkMemoryLeak) { 184 | NSLog(@"UZLoupeView has been released"); 185 | } 186 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 187 | } 188 | 189 | - (void)setCenter:(CGPoint)center { 190 | [super setCenter:center]; 191 | [self setNeedsDisplay]; 192 | } 193 | 194 | - (id)initWithRadius:(CGFloat)radius { 195 | self = [super initWithFrame:CGRectMake(0, 0, radius * 2, radius * 2)]; 196 | if (self) { 197 | _loupeRadius = radius; 198 | self.backgroundColor = [UIColor clearColor]; 199 | self.hidden = YES; 200 | } 201 | return self; 202 | } 203 | 204 | - (void)drawRect:(CGRect)rect { 205 | CGContextRef context = UIGraphicsGetCurrentContext(); 206 | 207 | // draw back ground fill 208 | [self.textViewBackgroundColor setFill]; 209 | CGContextAddArc(context, _loupeRadius, _loupeRadius, _loupeRadius, 0, M_PI * 2, 0); 210 | CGContextClosePath(context); 211 | CGContextDrawPath(context, kCGPathFill); 212 | 213 | // draw captured UZTextView bitmap 214 | CGContextSaveGState(context); 215 | CGContextAddArc(context, _loupeRadius, _loupeRadius, _loupeRadius, 0, M_PI * 2, 0); 216 | CGContextClosePath(context); 217 | CGContextClip(context); 218 | [_image drawAtPoint:CGPointZero]; 219 | CGContextRestoreGState(context); 220 | 221 | // draw outline stroke 222 | [[self.tintColor colorWithAlphaComponent:1] setStroke]; 223 | CGContextSaveGState(context); 224 | CGContextSetLineWidth(context, UZ_LOUPE_OUTLINE_STROKE_WIDTH); 225 | CGContextAddArc(context, _loupeRadius, _loupeRadius, _loupeRadius-1, 0, M_PI * 2, 0); 226 | CGContextClosePath(context); 227 | CGContextDrawPath(context, kCGPathStroke); 228 | CGContextRestoreGState(context); 229 | } 230 | 231 | @end 232 | -------------------------------------------------------------------------------- /UZTextView/UZTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UZTextView.h 3 | // Text 4 | // 5 | // Created by sonson on 2013/06/13. 6 | // Copyright (c) 2013年 sonson. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | //! Project version number for UZTextView. 13 | FOUNDATION_EXPORT double UZTextViewVersionNumber; 14 | 15 | //! Project version string for UZTextView. 16 | FOUNDATION_EXPORT const unsigned char UZTextViewVersionString[]; 17 | 18 | // In this header, you should import all the public headers of your framework using statements like #import 19 | 20 | static NSString * _Nonnull const UZTextViewClickedRect = @"_UZTextViewClickedRect"; 21 | 22 | /** 23 | * To be written 24 | */ 25 | @interface UIGestureRecognizer (UZTextView) 26 | /** 27 | * To be written 28 | * \return To be written 29 | */ 30 | - (NSString* __nonnull)stateDescription; 31 | /** 32 | * To be written 33 | * \param view To be written 34 | * \param margin To be written 35 | * \return To be written 36 | */ 37 | - (CGPoint)locationInView:(UIView* __nonnull)view margin:(UIEdgeInsets)margin; 38 | @end 39 | 40 | /** 41 | * To be written 42 | */ 43 | @interface UITouch (UZTextView) 44 | /** 45 | * To be written 46 | * \param view To be written 47 | * \param margin To be written 48 | * \return To be written 49 | */ 50 | - (CGPoint)locationInView:(UIView* __nonnull)view margin:(UIEdgeInsets)margin; 51 | @end 52 | 53 | #define SAFE_CFRELEASE(p) if(p){CFRelease(p);p=NULL;} 54 | 55 | @class UZLoupeView; 56 | @class UZCursorView; 57 | 58 | /** Type of cursor view's direction. */ 59 | typedef NS_ENUM(NSUInteger, UZTextViewGlyphEdgeType) { 60 | /** The cursor is at the left edge of a selected range. */ 61 | UZTextViewLeftEdge = 0, 62 | /** The cursor is at the right edge of a selected range. */ 63 | UZTextViewRightEdge = 1 64 | }; 65 | 66 | /** Status of the current selection range of UZTextView class. */ 67 | typedef NS_ENUM(NSUInteger, UZTextViewStatus) { 68 | /** User does not select any text. */ 69 | UZTextViewNoSelection = 0, 70 | /** User selects some text. */ 71 | UZTextViewSelected = 1, 72 | /** User is moving the left cursor of a selected range. */ 73 | UZTextViewEditingFromSelection = 2, 74 | /** User is moving the right cursor of a selected range. */ 75 | UZTextViewEditingToSelection = 3, 76 | }; 77 | 78 | @class UZTextView; 79 | 80 | /** 81 | * UZTextViewDelegate protocol is order to receive selecting, scrolling-related messages for UZTextView objcects. 82 | * All of the methods in this protocol are optional. 83 | * You can use the methods in order to lock parent view's scroll while user selects text on UZTextView object. 84 | */ 85 | @protocol UZTextViewDelegate 86 | /** 87 | * Tells the delegate that a link attribute has been tapped. 88 | * \param textView The text view in which the link is tapped. 89 | * \param value The link attribute data which is specified as NSAttributedString's methods. 90 | */ 91 | - (void)textView:(UZTextView* __nonnull)textView didClickLinkAttribute:(id __nullable)value; 92 | 93 | /** 94 | * Tells the delegate that a link attribute has been tapped for a long time. 95 | * \param textView The text view in which the link is tapped. 96 | * \param value The link attribute data which is specified as NSAttributedString's methods. 97 | */ 98 | - (void)textView:(UZTextView* __nonnull)textView didLongTapLinkAttribute:(id __nullable)value; 99 | 100 | /** 101 | * Tells the delegate that selecting of the specified text view has begun. 102 | * 103 | * You can use this delegate method in order to make its parent view disabled scrolling. 104 | * \param textView The text view in which selecting began. 105 | */ 106 | - (void)selectionDidBeginTextView:(UZTextView* __nonnull)textView; 107 | 108 | /** 109 | * Tells the delegate that selecting of the specified text view has ended. 110 | * 111 | * You can use this delegate method in order to make its parent view enabled scrolling. 112 | * \param textView The text view in which selecting ended. 113 | */ 114 | - (void)selectionDidEndTextView:(UZTextView* __nonnull)textView; 115 | 116 | /** 117 | * Tells the delegate that tap an area which does not include any links. 118 | * 119 | * You can use this delegate method to pass this event to parent views. 120 | * For example, you can select/deselect the UITableViewCell object whose UZTextView is tapped by an user. 121 | * \param textView The text view in which is tapped. 122 | */ 123 | - (void)didTapTextDoesNotIncludeLinkTextView:(UZTextView* __nonnull)textView; 124 | @end 125 | 126 | /** 127 | The UZTextView class implements the behavior for a scrollable, multiline, selectable, clickable text region. 128 | The class supports the display of text using custom style and link information. 129 | 130 | Create subclass of the class and use UZTextView internal category methods if you want to expand the UZTextView class. 131 | */ 132 | @interface UZTextView : UIView { 133 | // Data 134 | NSAttributedString *_attributedString; 135 | 136 | // Layout 137 | UIEdgeInsets _margin; 138 | CGFloat _lastLayoutWidth; // save the width when view is laytouted previously. 139 | 140 | // Scaling 141 | CGFloat _scale; 142 | 143 | // CoreText 144 | CTFramesetterRef _framesetter; 145 | CTFrameRef _frame; 146 | CGRect _contentRect; 147 | CFStringTokenizerRef _tokenizer; 148 | 149 | // Tap link attribute 150 | NSRange _tappedLinkRange; 151 | id _tappedLinkAttribute; 152 | 153 | // Highlighted text 154 | NSArray *_highlightRanges; 155 | 156 | // Tap 157 | UILongPressGestureRecognizer *_longPressGestureRecognizer; 158 | CFTimeInterval _minimumPressDuration; 159 | 160 | // parameter 161 | NSUInteger _head; 162 | NSUInteger _tail; 163 | NSUInteger _headWhenBegan; 164 | NSUInteger _tailWhenBegan; 165 | 166 | UZTextViewStatus _status; 167 | BOOL _isLocked; 168 | 169 | // child view 170 | UZLoupeView *_loupeView; 171 | UZCursorView *_leftCursor; 172 | UZCursorView *_rightCursor; 173 | 174 | // tap event control 175 | CGPoint _locationWhenTapBegan; 176 | 177 | // invaliables 178 | CGFloat _cursorMargin; 179 | CGFloat _tintAlpha; 180 | CGFloat _durationToCancelSuperViewScrolling; 181 | } 182 | 183 | /** 184 | * \name Public methods 185 | */ 186 | 187 | /** 188 | * Receiver's delegate. 189 | * The delegate is sent messages when contents are selected and tapped. 190 | * 191 | * See UZTextViewDelegate Protocol Reference for the optional methods this delegate may implement. 192 | */ 193 | @property (nonatomic, assign) id __nullable delegate; 194 | 195 | /** 196 | * The contents of the string to be drawn in this view. 197 | */ 198 | @property (nonatomic, copy) NSAttributedString* __nullable attributedString; 199 | 200 | /** 201 | * The bounding size required to draw the string. 202 | */ 203 | @property (nonatomic, readonly) CGSize contentSize; 204 | 205 | /** 206 | * The rendering scaling parameter. 207 | */ 208 | @property (nonatomic, assign) CGFloat scale; 209 | 210 | /** 211 | * The current selection range of the receiver. 212 | */ 213 | @property (nonatomic, assign) NSRange selectedRange; 214 | 215 | /** 216 | * The duration (in seconds) of a wait before text selection will start. The unit of duration is secondes. The default value is 0.5. 217 | */ 218 | @property (nonatomic, assign) CFTimeInterval minimumPressDuration; 219 | 220 | /** 221 | * Ranges to be highlighted. 222 | */ 223 | @property (nonatomic, copy) NSArray* __nullable highlightRanges; 224 | 225 | /** 226 | * UIEdgeInsets object, describes a margin around the content. The default value is UIEdgeInsetsZero. 227 | */ 228 | @property (nonatomic, assign) UIEdgeInsets margin; 229 | 230 | /** 231 | * Returns the bounding size required to draw the string. 232 | * \param attributedString Contents of the string to be drawn. 233 | * \param width The width constraint to apply when computing the string’s bounding rectangle. 234 | * \return A rectangle whose size component indicates the width and height required to draw the entire contents of the string. 235 | */ 236 | + (CGSize)sizeForAttributedString:(NSAttributedString* __nonnull)attributedString withBoundWidth:(CGFloat)width __attribute__((deprecated)); 237 | 238 | /** 239 | * To be written 240 | * \param attributedString To be written 241 | * \param width To be written 242 | * \param margin To be written 243 | * \return To be written 244 | */ 245 | + (CGSize)sizeForAttributedString:(NSAttributedString* __nonnull)attributedString withBoundWidth:(CGFloat)width margin:(UIEdgeInsets)margin; 246 | 247 | /** 248 | * Prepares for reusing an object. You have to call this method before you set another attributed string to the object. 249 | */ 250 | - (void)prepareForReuse; 251 | 252 | /** 253 | * Returns the attributes for the character at the specified point. 254 | * \param point The CGPoint object indicates the location user tapped. 255 | * \return The attributes for the character at the specified point. 256 | */ 257 | - (NSDictionary* __nullable)attributesAtPoint:(CGPoint)point; 258 | 259 | - (void)selectAll; 260 | 261 | - (BOOL)isSelectingAnyText; 262 | 263 | @end 264 | 265 | @interface UZTextView(Internal) 266 | 267 | /** 268 | * Hides/shows the cursors on UZTextView. 269 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 270 | * 271 | * \param hidden Specify YES to hide the cursors or NO to show it. 272 | */ 273 | - (void)setCursorHidden:(BOOL)hidden; 274 | 275 | /** 276 | * Updates layout of UZTextView. 277 | * CTFrameSetter, CTFrame is created, and the content size is calculated. 278 | * You have to this method after updating attributedString. 279 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 280 | */ 281 | - (void)updateLayout; 282 | 283 | /** 284 | * Shows UIMenuController on the receiver. 285 | * \discussion You have to override `canBecomeFirstResponder` or this method if you want to make it hide or edit its items forcely. 286 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 287 | */ 288 | #if !defined(TARGET_OS_TV) 289 | - (void)showUIMenu; 290 | #endif 291 | 292 | /** 293 | * Deselects selected text of the receiver. 294 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 295 | * 296 | * \return YES if the receiver's text is selected or NO if it's not. 297 | */ 298 | - (BOOL)cancelSelectedText; 299 | 300 | /** 301 | * Returns the frame rectangle, which describes the cursor location and size. 302 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 303 | * 304 | * \param index Index value to show the cursor. 305 | * \param side The left of right position to show the cursor. See UZTextViewGlyphEdgeType. 306 | * \return The frame rectangle of the cursor. 307 | */ 308 | - (CGRect)fragmentRectForCursorAtIndex:(NSInteger)index side:(UZTextViewGlyphEdgeType)side; 309 | 310 | /** 311 | * Returns the array whose frame rectangles describes regions of strings by specified character indices. 312 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 313 | * 314 | * \param fromIndex A beginning index to specify strings. The value must lie within the bounds of the receiver. 315 | * \param toIndex A ending index to specify strings. The value must lie within the bounds of the receiver. 316 | * \return An NSArray object containing frame rectangles. 317 | */ 318 | - (NSArray* __nonnull)fragmentRectsForGlyphFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex; 319 | 320 | /** 321 | * Returns the frame rectangle circumscribing the specified string. 322 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 323 | * 324 | * \param fromIndex A beginning index to specify strings. The value must lie within the bounds of the receiver. 325 | * \param toIndex A ending index to specify strings. The value must lie within the bounds of the receiver. 326 | * \return CGRect object circumscribing the specified strings. 327 | */ 328 | - (CGRect)circumscribingRectForStringFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex; 329 | 330 | /** 331 | * Draw the frame rectangle with tintColor containing the tapped link element of string. 332 | * Draw nothing when user do not tap any links. 333 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 334 | */ 335 | - (void)drawSelectedLinkFragments; 336 | 337 | /** 338 | * Draw the frame rectangles with specified color, containing specified string. 339 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 340 | * 341 | * \param fromIndex A beginning index to specify strings. The value must lie within the bounds of the receiver. 342 | * \param toIndex A ending index to specify strings. The value must lie within the bounds of the receiver. 343 | * \param color UIColor object to fill rectangles. 344 | */ 345 | - (void)drawSelectedTextFragmentRectsFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex color:(UIColor* __nonnull)color; 346 | 347 | /** 348 | * Draw the background rectangles of strings for debugging. 349 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 350 | */ 351 | - (void)drawStringRectForDebug; 352 | 353 | /** 354 | * Draw all contents. 355 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 356 | */ 357 | - (void)drawContent; 358 | 359 | /** 360 | * Callback method for the UILongPressGestureRecognizer object. 361 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 362 | * 363 | * \param gestureRecognizer The UILongPressGestureRecognizer object tells this method. 364 | */ 365 | - (void)didChangeLongPressGesture:(UILongPressGestureRecognizer* __nonnull)gestureRecognizer; 366 | 367 | /** 368 | * Initialize all properties. This method is called in `init` methods. 369 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 370 | */ 371 | - (void)prepareForInitialization; 372 | 373 | /** 374 | * Returns the index range of the link element which locates at the point user tapped. 375 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 376 | * 377 | * \param point The CGPoint object indicates the location user tapped. 378 | * \return Returns index range of the link element. 379 | */ 380 | - (NSRange)rangeOfLinkStringAtPoint:(CGPoint)point; 381 | 382 | /** 383 | * Extracts and selects a word which locates at the point user tapped, using CFStringTokenizer. 384 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 385 | * 386 | * \param point The CGPoint object indicates the location user tapped. 387 | */ 388 | - (void)setSelectionWithPoint:(CGPoint)point; 389 | 390 | /** 391 | * Returns CFIndex object which describes the index of the character locating at the point user tapped. 392 | * \warning This is an internal/private method. Use this method in subclass of UZTextView. 393 | * 394 | * \param point point The CGPoint object indicates the location user tapped. 395 | * \return CFIndex object describes the index of the tapped character. 396 | */ 397 | - (CFIndex)indexForPoint:(CGPoint)point; 398 | 399 | /** 400 | Debug flag 401 | */ 402 | @property (class) BOOL checkMemoryLeak; 403 | @end 404 | -------------------------------------------------------------------------------- /UZTextViewSample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UZTextViewSample 4 | // 5 | // Created by sonson on 2017/03/24. 6 | // Copyright © 2017年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import UZTextView 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | 20 | let t = UZTextView(frame: .zero) 21 | print(t) 22 | 23 | return true 24 | } 25 | 26 | func applicationWillResignActive(_ application: UIApplication) { 27 | // 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. 28 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 29 | } 30 | 31 | func applicationDidEnterBackground(_ application: UIApplication) { 32 | // 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. 33 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 34 | } 35 | 36 | func applicationWillEnterForeground(_ application: UIApplication) { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | func applicationDidBecomeActive(_ application: UIApplication) { 41 | // 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. 42 | } 43 | 44 | func applicationWillTerminate(_ application: UIApplication) { 45 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /UZTextViewSample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /UZTextViewSample/Base.lproj/LaunchScreen.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 | -------------------------------------------------------------------------------- /UZTextViewSample/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 | -------------------------------------------------------------------------------- /UZTextViewSample/Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Bridging-Header.h 3 | // UZTextView 4 | // 5 | // Created by sonson on 2017/06/26. 6 | // Copyright © 2017年 sonson. All rights reserved. 7 | // 8 | 9 | #ifndef Bridging_Header_h 10 | #define Bridging_Header_h 11 | 12 | #import 13 | 14 | #endif /* Bridging_Header_h */ 15 | -------------------------------------------------------------------------------- /UZTextViewSample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIAppFonts 24 | 25 | mona.ttf 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /UZTextViewSample/MainTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainTableViewController.swift 3 | // UZTextView 4 | // 5 | // Created by sonson on 2017/03/31. 6 | // Copyright © 2017年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import UZTextView 11 | import SafariServices 12 | 13 | struct Content { 14 | public let attributedString: NSAttributedString 15 | public let height: CGFloat 16 | public let scale: CGFloat 17 | public let inset: UIEdgeInsets 18 | } 19 | 20 | class MainTableViewController: UITableViewController, UZTextViewDelegate, UIViewControllerPreviewingDelegate { 21 | var contents: [Content] = [] 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | 26 | UZTextView.checkMemoryLeak = false 27 | 28 | do { 29 | let data = try Data(contentsOf: Bundle.main.url(forResource: "source", withExtension: "json")!) 30 | if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] { 31 | self.contents = try json.flatMap({ 32 | guard let body = $0["body"] as? String else { return nil } 33 | guard let aa = $0["aa"] as? Bool else { return nil } 34 | guard let margin = $0["margin"] as? CGFloat else { return nil} 35 | 36 | guard let data = body.data(using: .utf8) else { return nil } 37 | let options: [String: Any] = [ 38 | NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, 39 | NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue 40 | ] 41 | let inset = UIEdgeInsets(top: margin, left: margin, bottom: margin, right: margin) 42 | let attributedString = try NSMutableAttributedString(data: data, options: options, documentAttributes: nil) 43 | if aa { 44 | let size = UZTextView.size(for: attributedString, withBoundWidth: self.view.frame.size.width - 16, margin: inset) 45 | let ratio = (self.view.frame.size.width - 16) / size.width 46 | return Content(attributedString: attributedString, height: size.height * ratio + 16, scale: ratio, inset: inset) 47 | } else { 48 | let size = UZTextView.size(for: attributedString, withBoundWidth: self.view.frame.size.width - 16, margin: inset) 49 | let height = size.height + 16 50 | return Content(attributedString: attributedString, height: height, scale: 1, inset: inset) 51 | } 52 | }) 53 | } 54 | tableView.reloadData() 55 | } catch { 56 | print(error) 57 | } 58 | 59 | self.registerForPreviewing(with: self, sourceView: self.view) 60 | } 61 | 62 | func previewingContext(_ previewingContext: UIViewControllerPreviewing, 63 | viewControllerForLocation location: CGPoint) -> UIViewController? { 64 | 65 | let cells: [SampleCell] = self.tableView.visibleCells 66 | .flatMap({ $0 as? SampleCell }) 67 | .filter({ 68 | previewingContext.sourceView.convert($0.textView.frame, from: $0.textView).contains(location) 69 | }) 70 | let attributes: [[AnyHashable: Any]] = cells.flatMap({ 71 | let locationInTextView = self.view.convert(location, to: $0.textView) 72 | guard var attributes = $0.textView.attributes(at: locationInTextView) else { return nil } 73 | if attributes[NSLinkAttributeName] as? URL != nil, let rect = attributes[UZTextViewClickedRect] as? CGRect { 74 | attributes["rect"] = previewingContext.sourceView.convert(rect, from: $0.textView) 75 | return attributes 76 | } else { 77 | return nil 78 | } 79 | }) 80 | 81 | guard let attribute = attributes.first else { return nil } 82 | 83 | guard let rect = attribute["rect"] as? CGRect else { return nil } 84 | guard let url = attribute[NSLinkAttributeName] as? URL else { return nil } 85 | 86 | previewingContext.sourceRect = rect 87 | let controller = SFSafariViewController(url: url) 88 | 89 | return controller 90 | } 91 | 92 | func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) { 93 | let nav = UINavigationController(rootViewController: viewControllerToCommit) 94 | self.present(nav, animated: true, completion: nil) 95 | } 96 | 97 | func selectionDidBegin(_ textView: UZTextView) { 98 | self.tableView.isScrollEnabled = false 99 | } 100 | 101 | func selectionDidEnd(_ textView: UZTextView) { 102 | self.tableView.isScrollEnabled = true 103 | } 104 | 105 | func didTapTextDoesNotIncludeLinkTextView(_ textView: UZTextView) { 106 | } 107 | 108 | func textView(_ textView: UZTextView, didClickLinkAttribute attribute: Any?) { 109 | if let attribute = attribute as? [String: Any], let link = attribute[NSLinkAttributeName] as? URL { 110 | let controller = SFSafariViewController(url: link) 111 | self.present(controller, animated: true, completion: nil) 112 | } 113 | } 114 | 115 | func textView(_ textView: UZTextView, didLongTapLinkAttribute attribute: Any?) { 116 | if let attribute = attribute as? [String: Any], let link = attribute[NSLinkAttributeName] as? URL { 117 | let sheet = UIAlertController(title: "Link", message: link.absoluteString, preferredStyle: .actionSheet) 118 | do { 119 | let action = UIAlertAction(title: "Copy", style: .default) { (_) in 120 | print("copy") 121 | } 122 | sheet.addAction(action) 123 | } 124 | do { 125 | let action = UIAlertAction(title: "Open", style: .default) { (_) in 126 | let controller = SFSafariViewController(url: link) 127 | self.present(controller, animated: true, completion: nil) 128 | } 129 | sheet.addAction(action) 130 | } 131 | do { 132 | let action = UIAlertAction(title: "Open in Safari", style: .default) { (_) in 133 | UIApplication.shared.open(link, options: [:], completionHandler: nil) 134 | } 135 | sheet.addAction(action) 136 | } 137 | do { 138 | let action = UIAlertAction(title: "Cancel", style: .cancel) { (_) in 139 | } 140 | sheet.addAction(action) 141 | } 142 | self.present(sheet, animated: true, completion: nil) 143 | } 144 | } 145 | 146 | // MARK: - Table view data source 147 | 148 | override func numberOfSections(in tableView: UITableView) -> Int { 149 | return 1 150 | } 151 | 152 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 153 | return contents.count 154 | } 155 | 156 | override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 157 | return contents[indexPath.row].height 158 | } 159 | 160 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 161 | } 162 | 163 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 164 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 165 | 166 | if let cell = cell as? SampleCell { 167 | cell.textView.attributedString = contents[indexPath.row].attributedString 168 | cell.textView.scale = contents[indexPath.row].scale 169 | cell.textView.margin = contents[indexPath.row].inset 170 | cell.textView.delegate = self 171 | } 172 | 173 | return cell 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /UZTextViewSample/SampleCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SampleCell.swift 3 | // UZTextView 4 | // 5 | // Created by sonson on 2017/03/29. 6 | // Copyright © 2017年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import UZTextView 11 | 12 | class SampleCell: UITableViewCell { 13 | let textView = UZTextView(frame: .zero) 14 | 15 | override func awakeFromNib() { 16 | super.awakeFromNib() 17 | self.contentView.addSubview(textView) 18 | 19 | let views: [String: UIView] = [ 20 | "contentView": self.contentView, 21 | "textView": textView 22 | ] 23 | 24 | textView.backgroundColor = .white 25 | 26 | textView.translatesAutoresizingMaskIntoConstraints = false 27 | 28 | self.contentView.addConstraints ( 29 | NSLayoutConstraint.constraints(withVisualFormat: "V:|-8-[textView]-8-|", options: NSLayoutFormatOptions(), metrics: nil, views: views) 30 | ) 31 | self.contentView.addConstraints ( 32 | NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[textView]-8-|", options: NSLayoutFormatOptions(), metrics: nil, views: views) 33 | ) 34 | 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /UZTextViewSample/mona.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/UZTextView/53ff6ecd0ee017b4d6a4e8d454fddd78b150a31b/UZTextViewSample/mona.ttf -------------------------------------------------------------------------------- /UZTextViewSample/source.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "body": "

Let’sEncryptを使っ'てLINE Botからのcallbackを受けるサーバを作ったがダメで,さらにAWS API GatewayもLet’s Encrypt SSLを信用してなくて,大変だったというお話.

Let’s Encryptは,無料で使えるSSLの証明書取得サービスである.自動取得/更新がサーバに実装されており,それのためのサーバ側の更新スクリプトも配布されている.DNSをハックされる危険性や平文をネットワークに流す危険性が危惧される昨今,無料でSSLの証明書を利用できる趣味でサービスを開発したりするエンジニアの強い味方となっている.

", 4 | "aa": false, 5 | "margin": 5 6 | }, 7 | { 8 | "body": "

Let’sEncryptを使っ'てLINE Botからのcallbackを受けるサーバを作ったがダメで,さらにAWS API GatewayもLet’s Encrypt SSLを信用してなくて,大変だったというお話.

Let’s Encryptは,無料で使えるSSLの証明書取得サービスである.自動取得/更新がサーバに実装されており,それのためのサーバ側の更新スクリプトも配布されている.DNSをハックされる危険性や平文をネットワークに流す危険性が危惧される昨今,無料でSSLの証明書を利用できる趣味でサービスを開発したりするエンジニアの強い味方となっている.

", 9 | "aa": false, 10 | "margin": 0 11 | }, 12 | { 13 | "body": "

Let’sEncryptを使っ'てLINE Botからのcallbackを受けるサーバを作ったがダメで,さらにAWS API GatewayもLet’s Encrypt SSLを信用してなくて,大変だったというお話.

Let’s Encryptは,無料で使えるSSLの証明書取得サービスである.自動取得/更新がサーバに実装されており,それのためのサーバ側の更新スクリプトも配布されている.DNSをハックされる危険性や平文をネットワークに流す危険性が危惧される昨今,無料でSSLの証明書を利用できる趣味でサービスを開発したりするエンジニアの強い味方となっている.

", 14 | "aa": false, 15 | "margin": 30 16 | }, 17 | { 18 | "body": "    , -.―――--.、
   ,イ,,i、リ,,リ,,ノノ,,;;;;;;;;ヽ
  .i;}'       \"ミ;;;;:}
  |} ,,..、_、  , _,,,..、  |;;;:|
  |} ,_tュ,〈  ヒ''tュ_  i;;;;|
  |  ー' | ` -     ト'{
 .「|   イ_i _ >、     }〉}
 `{| _.ノ;;/;;/,ゞ;ヽ、  .!-'
   |    ='\"     |
    i゙ 、_  ゙,,,  ,, ' {
  丿\  ̄ ̄  _,,-\"ヽ
''\"~ヽ  \、_;;,..-\" _ ,i`ー-
   ヽ、oヽ/ \  /o/  |



https://www.google.com
", 19 | "aa": true, 20 | "margin": 10 21 | }, 22 | { 23 | "body": "                 __|__     -┼-
         七_      ,-|ナ、    ,.-┼ト、
   あ    (乂 )    し'ヽ ノ   ヽ__ レノ
 小←──────────────────────→大

 薄
 ↑米米米米米米米 : : : : : : : : : : : : : : :
 |髟髟髟髟髟髟髟 :..:..:..:..:..:..:.:..:..:..:..:.:..:
 |面面面面面面面 :.:.:.:.:.:.:.:.:.:.::.:.:.:.:.:.:.:.:
 |鼎鼎鼎鼎鼎鼎鼎 :.::.::.::.::.::.::.::.::.::.::.::.:::
 |蠻蠻蠻蠻蠻蠻蠻 ::::::::::::::::::::::::::::::::::::::
 |鬣鬣鬣鬣鬣鬣鬣 ::::::::::::::::::::::::::::::::::::::
 |麌麌麌麌麌麌麌 ;:;::;::;::;::;::;::;::;::;::;::;::;::
 |黌黌黌黌黌黌黌 :;:;:;:;:;:;:;:;:;:;::;:;:;:;:;:;:;:;:
 |鬱鬱鬱鬱鬱鬱鬱 ;;:;;:;;:;;:;;:;;:;;:;;:;;:;;:;;:;;:;;
 ↓䨻䨻䨻䨻䨻䨻䨻 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 濃
", 24 | "aa": true, 25 | "margin": 25 26 | }, 27 | { 28 | "body": "

Let’sEncryptを使っ'てLINE Botからのcallbackを受けるサーバを作ったがダメで,さらにAWS API GatewayもLet’s Encrypt SSLを信用してなくて,大変だったというお話.

Let’s Encryptは,無料で使えるSSLの証明書取得サービスである.自動取得/更新がサーバに実装されており,それのためのサーバ側の更新スクリプトも配布されている.DNSをハックされる危険性や平文をネットワークに流す危険性が危惧される昨今,無料でSSLの証明書を利用できる趣味でサービスを開発したりするエンジニアの強い味方となっている.

", 29 | "aa": false, 30 | "margin": 5 31 | }, 32 | { 33 | "body": "

Let’sEncryptを使っ'てLINE Botからのcallbackを受けるサーバを作ったがダメで,さらにAWS API GatewayもLet’s Encrypt SSLを信用してなくて,大変だったというお話.

Let’s Encryptは,無料で使えるSSLの証明書取得サービスである.自動取得/更新がサーバに実装されており,それのためのサーバ側の更新スクリプトも配布されている.DNSをハックされる危険性や平文をネットワークに流す危険性が危惧される昨今,無料でSSLの証明書を利用できる趣味でサービスを開発したりするエンジニアの強い味方となっている.

", 34 | "aa": false, 35 | "margin": 0 36 | }, 37 | { 38 | "body": "

Let’sEncryptを使っ'てLINE Botからのcallbackを受けるサーバを作ったがダメで,さらにAWS API GatewayもLet’s Encrypt SSLを信用してなくて,大変だったというお話.

Let’s Encryptは,無料で使えるSSLの証明書取得サービスである.自動取得/更新がサーバに実装されており,それのためのサーバ側の更新スクリプトも配布されている.DNSをハックされる危険性や平文をネットワークに流す危険性が危惧される昨今,無料でSSLの証明書を利用できる趣味でサービスを開発したりするエンジニアの強い味方となっている.

", 39 | "aa": false, 40 | "margin": 30 41 | }, 42 | { 43 | "body": "    , -.―――--.、
   ,イ,,i、リ,,リ,,ノノ,,;;;;;;;;ヽ
  .i;}'       \"ミ;;;;:}
  |} ,,..、_、  , _,,,..、  |;;;:|
  |} ,_tュ,〈  ヒ''tュ_  i;;;;|
  |  ー' | ` -     ト'{
 .「|   イ_i _ >、     }〉}
 `{| _.ノ;;/;;/,ゞ;ヽ、  .!-'
   |    ='\"     |
    i゙ 、_  ゙,,,  ,, ' {
  丿\  ̄ ̄  _,,-\"ヽ
''\"~ヽ  \、_;;,..-\" _ ,i`ー-
   ヽ、oヽ/ \  /o/  |



https://www.google.com
", 44 | "aa": true, 45 | "margin": 10 46 | }, 47 | { 48 | "body": "                 __|__     -┼-
         七_      ,-|ナ、    ,.-┼ト、
   あ    (乂 )    し'ヽ ノ   ヽ__ レノ
 小←──────────────────────→大

 薄
 ↑米米米米米米米 : : : : : : : : : : : : : : :
 |髟髟髟髟髟髟髟 :..:..:..:..:..:..:.:..:..:..:..:.:..:
 |面面面面面面面 :.:.:.:.:.:.:.:.:.:.::.:.:.:.:.:.:.:.:
 |鼎鼎鼎鼎鼎鼎鼎 :.::.::.::.::.::.::.::.::.::.::.::.:::
 |蠻蠻蠻蠻蠻蠻蠻 ::::::::::::::::::::::::::::::::::::::
 |鬣鬣鬣鬣鬣鬣鬣 ::::::::::::::::::::::::::::::::::::::
 |麌麌麌麌麌麌麌 ;:;::;::;::;::;::;::;::;::;::;::;::;::
 |黌黌黌黌黌黌黌 :;:;:;:;:;:;:;:;:;:;::;:;:;:;:;:;:;:;:
 |鬱鬱鬱鬱鬱鬱鬱 ;;:;;:;;:;;:;;:;;:;;:;;:;;:;;:;;:;;:;;
 ↓䨻䨻䨻䨻䨻䨻䨻 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 濃
", 49 | "aa": true, 50 | "margin": 25 51 | } 52 | ] 53 | -------------------------------------------------------------------------------- /UZTextViewSample/trash/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UZTextViewSample 4 | // 5 | // Created by sonson on 2017/06/26. 6 | // Copyright © 2017年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // 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. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /UZTextViewSample/trash/Assets.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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /UZTextViewSample/trash/Base.lproj/LaunchScreen.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 | -------------------------------------------------------------------------------- /UZTextViewSample/trash/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 | -------------------------------------------------------------------------------- /UZTextViewSample/trash/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /UZTextViewSample/trash/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // UZTextViewSample 4 | // 5 | // Created by sonson on 2017/06/26. 6 | // Copyright © 2017年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import UZTextView 11 | 12 | class ViewController: UIViewController { 13 | let textView = UZTextView(frame: .zero) 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | // Do any additional setup after loading the view, typically from a nib. 18 | } 19 | 20 | override func didReceiveMemoryWarning() { 21 | super.didReceiveMemoryWarning() 22 | // Dispose of any resources that can be recreated. 23 | } 24 | 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | xcodebuild -sdk iphoneos -arch armv7 -arch armv7s -arch arm64 clean build 2 | xcodebuild -sdk iphonesimulator -arch i386 -arch x86_64 clean build 3 | 4 | xcrun lipo -create build/Release-iphonesimulator/libUZTextView.a build/Release-iphoneos/libUZTextView.a -output build/libUZTextView.a 5 | cp ./UZTextView/UZTextView.h ./build/ 6 | -------------------------------------------------------------------------------- /html/Categories/UIGestureRecognizer+UZTextView.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIGestureRecognizer(UZTextView) Category Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

UZTextView

15 | sonson 16 |
17 | 18 | 21 | 55 |
56 | 87 |
88 |
89 | 90 | 96 | 101 |
102 | 103 |
104 | 105 | 106 | 107 | 108 |
Declared inUZTextView.m
109 | 110 | 111 | 112 | 113 |
114 | 115 |

Overview

116 |

To be written

117 |
118 | 119 | 120 | 121 | 122 | 123 |
124 | 125 |

Tasks

126 | 127 | 128 | 129 | 130 | 131 | 146 | 147 |
148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 |
158 | 159 |

Instance Methods

160 | 161 |
162 | 163 |

locationInView:margin:

164 | 165 | 166 | 167 |
168 |

To be written

169 |
170 | 171 | 172 | 173 |
- (CGPoint)locationInView:(UIView *)view margin:(UIEdgeInsets)margin
174 | 175 | 176 | 177 |
178 |

Parameters

179 | 180 |
181 |
view
182 |

To be written

183 |
184 | 185 |
186 |
margin
187 |

To be written

188 |
189 | 190 |
191 | 192 | 193 | 194 |
195 |

Return Value

196 |

To be written

197 |
198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 |
210 |

Declared In

211 | UZTextView.m
212 |
213 | 214 | 215 |
216 | 217 |
218 | 219 |

stateDescription

220 | 221 | 222 | 223 |
224 |

To be written

225 |
226 | 227 | 228 | 229 |
- (NSString *)stateDescription
230 | 231 | 232 | 233 | 234 | 235 |
236 |

Return Value

237 |

To be written

238 |
239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 |
251 |

Declared In

252 | UZTextView.m
253 |
254 | 255 | 256 |
257 | 258 |
259 | 260 | 261 | 262 | 263 |
264 | 270 | 279 |
280 |
281 | 372 | 373 | -------------------------------------------------------------------------------- /html/Categories/UITouch+UZTextView.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UITouch(UZTextView) Category Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

UZTextView

15 | sonson 16 |
17 | 18 | 21 | 53 |
54 | 83 |
84 |
85 | 86 | 92 | 97 |
98 | 99 |
100 | 101 | 102 | 103 | 104 |
Declared inUZTextView.m
105 | 106 | 107 | 108 | 109 |
110 | 111 |

Overview

112 |

To be written

113 |
114 | 115 | 116 | 117 | 118 | 119 |
120 | 121 |

Tasks

122 | 123 | 124 | 125 | 126 | 127 | 136 | 137 |
138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 |
148 | 149 |

Instance Methods

150 | 151 |
152 | 153 |

locationInView:margin:

154 | 155 | 156 | 157 |
158 |

To be written

159 |
160 | 161 | 162 | 163 |
- (CGPoint)locationInView:(UIView *)view margin:(UIEdgeInsets)margin
164 | 165 | 166 | 167 |
168 |

Parameters

169 | 170 |
171 |
view
172 |

To be written

173 |
174 | 175 |
176 |
margin
177 |

To be written

178 |
179 | 180 |
181 | 182 | 183 | 184 |
185 |

Return Value

186 |

To be written

187 |
188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 |
200 |

Declared In

201 | UZTextView.m
202 |
203 | 204 | 205 |
206 | 207 |
208 | 209 | 210 | 211 | 212 |
213 | 219 | 228 |
229 |
230 | 321 | 322 | -------------------------------------------------------------------------------- /html/Constants/UZTextViewGlyphEdgeType.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UZTextViewGlyphEdgeType Constants Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

UZTextView

15 | sonson 16 |
17 | 18 | 21 | 36 |
37 | 46 |
47 |
48 | 49 | 55 | 60 |
61 | 62 |
63 | 64 | 65 | 66 | 67 |
Declared inUZTextView.h
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 |

UZTextViewGlyphEdgeType

78 | 79 | 80 |
81 |

Type of cursor view’s direction.

82 |
83 | 84 | 85 |
86 | 87 | 88 |

Definition

89 | typedef NS_ENUM(NSUInteger, UZTextViewGlyphEdgeType ) {
90 | 91 |    UZTextViewLeftEdge = 0,
92 | 93 |    UZTextViewRightEdge = 1,
94 | 95 | };
96 | 97 |
98 | 99 |
100 |

Constants

101 |
102 | 103 |
UZTextViewLeftEdge
104 |
105 | 106 | 107 |

The cursor is at the left edge of a selected range.

108 | 109 | 110 | 111 | 112 | 113 | 114 |

115 | Declared In UZTextView.h. 116 |

117 | 118 |
119 | 120 |
UZTextViewRightEdge
121 |
122 | 123 | 124 |

The cursor is at the right edge of a selected range.

125 | 126 | 127 | 128 | 129 | 130 | 131 |

132 | Declared In UZTextView.h. 133 |

134 | 135 |
136 | 137 |
138 |
139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 |
148 |

Declared In

149 | UZTextView.h
150 |
151 | 152 | 153 | 154 |
155 | 161 | 170 |
171 |
172 | 263 | 264 | -------------------------------------------------------------------------------- /html/Constants/UZTextViewStatus.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UZTextViewStatus Constants Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

UZTextView

15 | sonson 16 |
17 | 18 | 21 | 36 |
37 | 46 |
47 |
48 | 49 | 55 | 60 |
61 | 62 |
63 | 64 | 65 | 66 | 67 |
Declared inUZTextView.h
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 |

UZTextViewStatus

78 | 79 | 80 |
81 |

Status of the current selection range of UZTextView class.

82 |
83 | 84 | 85 |
86 | 87 | 88 |

Definition

89 | typedef NS_ENUM(NSUInteger, UZTextViewStatus ) {
90 | 91 |    UZTextViewNoSelection = 0,
92 | 93 |    UZTextViewSelected = 1,
94 | 95 |    UZTextViewEditingFromSelection = 2,
96 | 97 |    UZTextViewEditingToSelection = 3,
98 | 99 | };
100 | 101 |
102 | 103 |
104 |

Constants

105 |
106 | 107 |
UZTextViewNoSelection
108 |
109 | 110 | 111 |

User does not select any text.

112 | 113 | 114 | 115 | 116 | 117 | 118 |

119 | Declared In UZTextView.h. 120 |

121 | 122 |
123 | 124 |
UZTextViewSelected
125 |
126 | 127 | 128 |

User selects some text.

129 | 130 | 131 | 132 | 133 | 134 | 135 |

136 | Declared In UZTextView.h. 137 |

138 | 139 |
140 | 141 |
UZTextViewEditingFromSelection
142 |
143 | 144 | 145 |

User is moving the left cursor of a selected range.

146 | 147 | 148 | 149 | 150 | 151 | 152 |

153 | Declared In UZTextView.h. 154 |

155 | 156 |
157 | 158 |
UZTextViewEditingToSelection
159 |
160 | 161 | 162 |

User is moving the right cursor of a selected range.

163 | 164 | 165 | 166 | 167 | 168 | 169 |

170 | Declared In UZTextView.h. 171 |

172 | 173 |
174 | 175 |
176 |
177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 |
186 |

Declared In

187 | UZTextView.h
188 |
189 | 190 | 191 | 192 |
193 | 199 | 208 |
209 |
210 | 301 | 302 | -------------------------------------------------------------------------------- /html/Protocols/UZTextViewDelegate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UZTextViewDelegate Protocol Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

UZTextView

15 | sonson 16 |
17 | 18 | 21 | 59 |
60 | 95 |
96 |
97 | 98 | 104 | 109 |
110 | 111 |
112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 |
Conforms toNSObject
Declared inUZTextView.h
120 | 121 | 122 | 123 | 124 |
125 | 126 |

Overview

127 |

UZTextViewDelegate protocol is order to receive selecting, scrolling-related messages for UZTextView objcects. 128 | All of the methods in this protocol are optional. 129 | You can use the methods in order to lock parent view’s scroll while user selects text on UZTextView object.

130 |
131 | 132 | 133 | 134 | 135 | 136 |
137 | 138 |

Tasks

139 | 140 | 141 | 142 | 143 | 144 | 171 | 172 |
173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 |
183 | 184 |

Instance Methods

185 | 186 |
187 | 188 |

didTapTextDoesNotIncludeLinkTextView:

189 | 190 | 191 | 192 |
193 |

Tells the delegate that tap an area which does not include any links.

194 |
195 | 196 | 197 | 198 |
- (void)didTapTextDoesNotIncludeLinkTextView:(UZTextView *)textView
199 | 200 | 201 | 202 |
203 |

Parameters

204 | 205 |
206 |
textView
207 |

The text view in which is tapped.

208 |
209 | 210 |
211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 |
219 |

Discussion

220 |

You can use this delegate method to pass this event to parent views. 221 | For example, you can select/deselect the UITableViewCell object whose UZTextView is tapped by an user.

222 |
223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 |
231 |

Declared In

232 | UZTextView.h
233 |
234 | 235 | 236 |
237 | 238 |
239 | 240 |

selectionDidBeginTextView:

241 | 242 | 243 | 244 |
245 |

Tells the delegate that selecting of the specified text view has begun.

246 |
247 | 248 | 249 | 250 |
- (void)selectionDidBeginTextView:(UZTextView *)textView
251 | 252 | 253 | 254 |
255 |

Parameters

256 | 257 |
258 |
textView
259 |

The text view in which selecting began.

260 |
261 | 262 |
263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 |
271 |

Discussion

272 |

You can use this delegate method in order to make its parent view disabled scrolling.

273 |
274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 |
282 |

Declared In

283 | UZTextView.h
284 |
285 | 286 | 287 |
288 | 289 |
290 | 291 |

selectionDidEndTextView:

292 | 293 | 294 | 295 |
296 |

Tells the delegate that selecting of the specified text view has ended.

297 |
298 | 299 | 300 | 301 |
- (void)selectionDidEndTextView:(UZTextView *)textView
302 | 303 | 304 | 305 |
306 |

Parameters

307 | 308 |
309 |
textView
310 |

The text view in which selecting ended.

311 |
312 | 313 |
314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 |
322 |

Discussion

323 |

You can use this delegate method in order to make its parent view enabled scrolling.

324 |
325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 |
333 |

Declared In

334 | UZTextView.h
335 |
336 | 337 | 338 |
339 | 340 |
341 | 342 |

textView:didClickLinkAttribute:

343 | 344 | 345 | 346 |
347 |

Tells the delegate that a link attribute has been tapped.

348 |
349 | 350 | 351 | 352 |
- (void)textView:(UZTextView *)textView didClickLinkAttribute:(id)value
353 | 354 | 355 | 356 |
357 |

Parameters

358 | 359 |
360 |
textView
361 |

The text view in which the link is tapped.

362 |
363 | 364 |
365 |
value
366 |

The link attribute data which is specified as NSAttributedString’s methods.

367 |
368 | 369 |
370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 |
384 |

Declared In

385 | UZTextView.h
386 |
387 | 388 | 389 |
390 | 391 |
392 | 393 | 394 | 395 | 396 |
397 | 403 | 412 |
413 |
414 | 505 | 506 | -------------------------------------------------------------------------------- /html/css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 3 | font-size: 13px; 4 | } 5 | 6 | code { 7 | font-family: Courier, Consolas, monospace; 8 | font-size: 13px; 9 | color: #666; 10 | } 11 | 12 | pre { 13 | font-family: Courier, Consolas, monospace; 14 | font-size: 13px; 15 | line-height: 18px; 16 | tab-interval: 0.5em; 17 | border: 1px solid #C7CFD5; 18 | background-color: #F1F5F9; 19 | color: #666; 20 | padding: 0.3em 1em; 21 | } 22 | 23 | ul { 24 | list-style-type: square; 25 | } 26 | 27 | li { 28 | margin-bottom: 10px; 29 | } 30 | 31 | a, a code { 32 | text-decoration: none; 33 | color: #36C; 34 | } 35 | 36 | a:hover, a:hover code { 37 | text-decoration: underline; 38 | color: #36C; 39 | } 40 | 41 | h2 { 42 | border-bottom: 1px solid #8391A8; 43 | color: #3C4C6C; 44 | font-size: 187%; 45 | font-weight: normal; 46 | margin-top: 1.75em; 47 | padding-bottom: 2px; 48 | } 49 | 50 | table { 51 | margin-bottom: 4em; 52 | border-collapse:collapse; 53 | vertical-align: middle; 54 | } 55 | 56 | td { 57 | border: 1px solid #9BB3CD; 58 | padding: .667em; 59 | font-size: 100%; 60 | } 61 | 62 | th { 63 | border: 1px solid #9BB3CD; 64 | padding: .3em .667em .3em .667em; 65 | background: #93A5BB; 66 | font-size: 103%; 67 | font-weight: bold; 68 | color: white; 69 | text-align: left; 70 | } 71 | 72 | /* @group Common page elements */ 73 | 74 | #top_header { 75 | height: 91px; 76 | left: 0; 77 | min-width: 598px; 78 | position: absolute; 79 | right: 0; 80 | top: 0; 81 | z-index: 900; 82 | } 83 | 84 | #footer { 85 | clear: both; 86 | padding-top: 20px; 87 | text-align: center; 88 | } 89 | 90 | #contents, #overview_contents { 91 | -webkit-overflow-scrolling: touch; 92 | border-top: 1px solid #A9A9A9; 93 | position: absolute; 94 | top: 90px; 95 | left: 0; 96 | right: 0; 97 | bottom: 0; 98 | overflow-x: hidden; 99 | overflow-y: auto; 100 | padding-left: 2em; 101 | padding-right: 2em; 102 | padding-top: 1em; 103 | min-width: 550px; 104 | } 105 | 106 | #contents.isShowingTOC { 107 | left: 230px; 108 | min-width: 320px; 109 | } 110 | 111 | .copyright { 112 | font-size: 12px; 113 | } 114 | 115 | .generator { 116 | font-size: 11px; 117 | } 118 | 119 | .main-navigation ul li { 120 | display: inline; 121 | margin-left: 15px; 122 | list-style: none; 123 | } 124 | 125 | .navigation-top { 126 | clear: both; 127 | float: right; 128 | } 129 | 130 | .navigation-bottom { 131 | clear: both; 132 | float: right; 133 | margin-top: 20px; 134 | margin-bottom: -10px; 135 | } 136 | 137 | .open > .disclosure { 138 | background-image: url("../img/disclosure_open.png"); 139 | } 140 | 141 | .disclosure { 142 | background: url("../img/disclosure.png") no-repeat scroll 0 0; 143 | } 144 | 145 | .disclosure, .nodisclosure { 146 | display: inline-block; 147 | height: 8px; 148 | margin-right: 5px; 149 | position: relative; 150 | width: 9px; 151 | } 152 | 153 | /* @end */ 154 | 155 | /* @group Header */ 156 | 157 | #top_header #library { 158 | background: url("../img/library_background.png") repeat-x 0 0 #485E78; 159 | background-color: #ccc; 160 | height: 35px; 161 | font-size: 115%; 162 | } 163 | 164 | #top_header #library #libraryTitle { 165 | color: #FFFFFF; 166 | margin-left: 15px; 167 | text-shadow: 0 -1px 0 #485E78; 168 | top: 8px; 169 | position: absolute; 170 | } 171 | 172 | #libraryTitle { 173 | left: 0; 174 | } 175 | 176 | #top_header #library #developerHome { 177 | color: #92979E; 178 | right: 15px; 179 | top: 8px; 180 | position: absolute; 181 | } 182 | 183 | #top_header #library a:hover { 184 | text-decoration: none; 185 | } 186 | 187 | #top_header #title { 188 | background: url("../img/title_background.png") repeat-x 0 0 #8A98A9; 189 | border-bottom: 1px solid #757575; 190 | height: 25px; 191 | overflow: hidden; 192 | } 193 | 194 | #top_header h1 { 195 | font-size: 105%; 196 | font-weight: normal; 197 | margin: 0; 198 | padding: 3px 0 2px; 199 | text-align: center; 200 | /*text-shadow: 0 1px 0 #D5D5D5;*/ 201 | white-space: nowrap; 202 | } 203 | 204 | #headerButtons { 205 | background-color: #D8D8D8; 206 | background-image: url("../img/button_bar_background.png"); 207 | border-bottom: 0px solid #EDEDED; 208 | border-top: 0px solid #a8a8a8; 209 | font-size: 8pt; 210 | height: 28px; 211 | left: 0; 212 | list-style: none outside none; 213 | margin: 0; 214 | overflow: hidden; 215 | padding: 0; 216 | position: absolute; 217 | right: 0; 218 | top: 61px; 219 | } 220 | 221 | #headerButtons li { 222 | background-repeat: no-repeat; 223 | display: inline; 224 | margin-top: 0; 225 | margin-bottom: 0; 226 | padding: 0; 227 | } 228 | 229 | #toc_button button { 230 | background-color: #EBEEF1; 231 | border-color: #ACACAC; 232 | border-style: none solid none none; 233 | border-width: 0 1px 0 0; 234 | height: 28px; 235 | margin: 0; 236 | padding-left: 30px; 237 | text-align: left; 238 | width: 230px; 239 | } 240 | 241 | li#jumpto_button { 242 | left: 230px; 243 | margin-left: 0; 244 | position: absolute; 245 | } 246 | 247 | li#jumpto_button select { 248 | height: 22px; 249 | margin: 5px 2px 0 10px; 250 | max-width: 300px; 251 | } 252 | 253 | /* @end */ 254 | 255 | /* @group Table of contents */ 256 | 257 | #tocContainer.isShowingTOC { 258 | border-right: 1px solid #ACACAC; 259 | display: block; 260 | overflow-x: hidden; 261 | overflow-y: auto; 262 | padding: 0; 263 | } 264 | 265 | #tocContainer { 266 | background-color: #EBEEF1; 267 | border-top: 1px solid #ACACAC; 268 | bottom: 0; 269 | display: none; 270 | left: 0; 271 | overflow: hidden; 272 | position: absolute; 273 | top: 90px; 274 | width: 229px; 275 | } 276 | 277 | #tocContainer > ul#toc { 278 | font-size: 11px; 279 | margin: 0; 280 | padding: 12px 0 18px; 281 | width: 209px; 282 | -moz-user-select: none; 283 | -webkit-user-select: none; 284 | user-select: none; 285 | } 286 | 287 | #tocContainer > ul#toc > li { 288 | margin: 0; 289 | padding: 0 0 7px 30px; 290 | text-indent: -15px; 291 | } 292 | 293 | #tocContainer > ul#toc > li > .sectionName a { 294 | color: #000000; 295 | font-weight: bold; 296 | } 297 | 298 | #tocContainer > ul#toc > li > .sectionName a:hover { 299 | text-decoration: none; 300 | } 301 | 302 | #tocContainer > ul#toc li.children > ul { 303 | display: none; 304 | height: 0; 305 | } 306 | 307 | #tocContainer > ul#toc > li > ul { 308 | margin: 0; 309 | padding: 0; 310 | } 311 | 312 | #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li { 313 | margin-left: 0; 314 | margin-bottom: 0; 315 | padding-left: 15px; 316 | } 317 | 318 | #tocContainer > ul#toc > li ul { 319 | list-style: none; 320 | margin-right: 0; 321 | padding-right: 0; 322 | } 323 | 324 | #tocContainer > ul#toc li.children.open > ul { 325 | display: block; 326 | height: auto; 327 | margin-left: -15px; 328 | padding-left: 0; 329 | } 330 | 331 | #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li { 332 | margin-left: 0; 333 | padding-left: 15px; 334 | } 335 | 336 | #tocContainer li ul li { 337 | margin-top: 0.583em; 338 | overflow: hidden; 339 | text-overflow: ellipsis; 340 | white-space: nowrap; 341 | } 342 | 343 | #tocContainer li ul li span.sectionName { 344 | white-space: normal; 345 | } 346 | 347 | #tocContainer > ul#toc > li > ul > li > .sectionName a { 348 | font-weight: bold; 349 | } 350 | 351 | #tocContainer > ul#toc > li > ul a { 352 | color: #4F4F4F; 353 | } 354 | 355 | /* @end */ 356 | 357 | /* @group Index formatting */ 358 | 359 | .index-title { 360 | font-size: 13px; 361 | font-weight: normal; 362 | } 363 | 364 | .index-column { 365 | float: left; 366 | width: 30%; 367 | min-width: 200px; 368 | font-size: 11px; 369 | } 370 | 371 | .index-column ul { 372 | margin: 8px 0 0 0; 373 | padding: 0; 374 | list-style: none; 375 | } 376 | 377 | .index-column ul li { 378 | margin: 0 0 3px 0; 379 | padding: 0; 380 | } 381 | 382 | .hierarchy-column { 383 | min-width: 400px; 384 | } 385 | 386 | .hierarchy-column ul { 387 | margin: 3px 0 0 15px; 388 | } 389 | 390 | .hierarchy-column ul li { 391 | list-style-type: square; 392 | } 393 | 394 | /* @end */ 395 | 396 | /* @group Common formatting elements */ 397 | 398 | .title { 399 | font-weight: normal; 400 | font-size: 215%; 401 | margin-top:0; 402 | } 403 | 404 | .subtitle { 405 | font-weight: normal; 406 | font-size: 180%; 407 | color: #3C4C6C; 408 | border-bottom: 1px solid #5088C5; 409 | } 410 | 411 | .subsubtitle { 412 | font-weight: normal; 413 | font-size: 145%; 414 | height: 0.7em; 415 | } 416 | 417 | .note { 418 | border: 1px solid #5088C5; 419 | background-color: white; 420 | margin: 1.667em 0 1.75em 0; 421 | padding: 0 .667em .083em .750em; 422 | } 423 | 424 | .warning { 425 | border: 1px solid #5088C5; 426 | background-color: #F0F3F7; 427 | margin-bottom: 0.5em; 428 | padding: 0.3em 0.8em; 429 | } 430 | 431 | .bug { 432 | border: 1px solid #000; 433 | background-color: #ffffcc; 434 | margin-bottom: 0.5em; 435 | padding: 0.3em 0.8em; 436 | } 437 | 438 | .deprecated { 439 | color: #F60425; 440 | } 441 | 442 | /* @end */ 443 | 444 | /* @group Common layout */ 445 | 446 | .section { 447 | margin-top: 3em; 448 | } 449 | 450 | /* @end */ 451 | 452 | /* @group Object specification section */ 453 | 454 | .section-specification { 455 | margin-left: 2.5em; 456 | margin-right: 2.5em; 457 | font-size: 12px; 458 | } 459 | 460 | .section-specification table { 461 | margin-bottom: 0em; 462 | border-top: 1px solid #d6e0e5; 463 | } 464 | 465 | .section-specification td { 466 | vertical-align: top; 467 | border-bottom: 1px solid #d6e0e5; 468 | border-left-width: 0px; 469 | border-right-width: 0px; 470 | border-top-width: 0px; 471 | padding: .6em; 472 | } 473 | 474 | .section-specification .specification-title { 475 | font-weight: bold; 476 | } 477 | 478 | /* @end */ 479 | 480 | /* @group Tasks section */ 481 | 482 | .task-list { 483 | list-style-type: none; 484 | padding-left: 0px; 485 | } 486 | 487 | .task-list li { 488 | margin-bottom: 3px; 489 | } 490 | 491 | .task-item-suffix { 492 | color: #996; 493 | font-size: 12px; 494 | font-style: italic; 495 | margin-left: 0.5em; 496 | } 497 | 498 | span.tooltip span.tooltip { 499 | font-size: 1.0em; 500 | display: none; 501 | padding: 0.3em; 502 | border: 1px solid #aaa; 503 | background-color: #fdfec8; 504 | color: #000; 505 | text-align: left; 506 | } 507 | 508 | span.tooltip:hover span.tooltip { 509 | display: block; 510 | position: absolute; 511 | margin-left: 2em; 512 | } 513 | 514 | /* @end */ 515 | 516 | /* @group Method section */ 517 | 518 | .section-method { 519 | margin-top: 2.3em; 520 | } 521 | 522 | .method-title { 523 | margin-bottom: 1.5em; 524 | } 525 | 526 | .method-subtitle { 527 | margin-top: 0.7em; 528 | margin-bottom: 0.2em; 529 | } 530 | 531 | .method-subsection p { 532 | margin-top: 0.4em; 533 | margin-bottom: 0.8em; 534 | } 535 | 536 | .method-declaration { 537 | margin-top:1.182em; 538 | margin-bottom:.909em; 539 | } 540 | 541 | .method-declaration code { 542 | font:14px Courier, Consolas, monospace; 543 | color:#000; 544 | } 545 | 546 | .declaration { 547 | color: #000; 548 | } 549 | 550 | .termdef { 551 | margin-bottom: 10px; 552 | margin-left: 0px; 553 | margin-right: 0px; 554 | margin-top: 0px; 555 | } 556 | 557 | .termdef dt { 558 | margin: 0; 559 | padding: 0; 560 | } 561 | 562 | .termdef dd { 563 | margin-bottom: 6px; 564 | margin-left: 16px; 565 | margin-right: 0px; 566 | margin-top: 1px; 567 | } 568 | 569 | .termdef dd p { 570 | margin-bottom: 6px; 571 | margin-left: 0px; 572 | margin-right: 0px; 573 | margin-top: -1px; 574 | } 575 | 576 | .argument-def { 577 | margin-top: 0.3em; 578 | margin-bottom: 0.3em; 579 | } 580 | 581 | .argument-def dd { 582 | margin-left: 1.25em; 583 | } 584 | 585 | .see-also-section ul { 586 | list-style-type: none; 587 | padding-left: 0px; 588 | margin-top: 0; 589 | } 590 | 591 | .see-also-section li { 592 | margin-bottom: 3px; 593 | } 594 | 595 | .declared-in-ref { 596 | color: #666; 597 | } 598 | 599 | #tocContainer.hideInXcode { 600 | display: none; 601 | border: 0px solid black; 602 | } 603 | 604 | #top_header.hideInXcode { 605 | display: none; 606 | } 607 | 608 | #contents.hideInXcode { 609 | border: 0px solid black; 610 | top: 0px; 611 | left: 0px; 612 | } 613 | 614 | /* @end */ 615 | 616 | -------------------------------------------------------------------------------- /html/css/stylesPrint.css: -------------------------------------------------------------------------------- 1 | 2 | header { 3 | display: none; 4 | } 5 | 6 | div.main-navigation, div.navigation-top { 7 | display: none; 8 | } 9 | 10 | div#overview_contents, div#contents.isShowingTOC, div#contents { 11 | overflow: visible; 12 | position: relative; 13 | top: 0px; 14 | border: none; 15 | left: 0; 16 | } 17 | #tocContainer.isShowingTOC { 18 | display: none; 19 | } 20 | nav { 21 | display: none; 22 | } -------------------------------------------------------------------------------- /html/hierarchy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UZTextView Hierarchy 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

UZTextView

14 | sonson 15 |
16 | 17 | 20 | 21 |
22 |
23 |
24 | 27 | 32 |
33 | 34 |
35 |

Class Hierarchy

36 | 37 |
    38 | 39 |
  • UIView 40 | 45 |
  • 46 | 47 |
48 | 49 |
50 | 51 | 52 | 53 |
54 | 55 |

Protocol References

56 | 61 | 62 | 63 |

Constant References

64 | 71 | 72 | 73 |

Category References

74 | 81 | 82 |
83 | 84 |
85 | 88 | 98 |
99 |
100 | 101 | -------------------------------------------------------------------------------- /html/img/button_bar_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/UZTextView/53ff6ecd0ee017b4d6a4e8d454fddd78b150a31b/html/img/button_bar_background.png -------------------------------------------------------------------------------- /html/img/disclosure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/UZTextView/53ff6ecd0ee017b4d6a4e8d454fddd78b150a31b/html/img/disclosure.png -------------------------------------------------------------------------------- /html/img/disclosure_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/UZTextView/53ff6ecd0ee017b4d6a4e8d454fddd78b150a31b/html/img/disclosure_open.png -------------------------------------------------------------------------------- /html/img/library_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/UZTextView/53ff6ecd0ee017b4d6a4e8d454fddd78b150a31b/html/img/library_background.png -------------------------------------------------------------------------------- /html/img/title_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/UZTextView/53ff6ecd0ee017b4d6a4e8d454fddd78b150a31b/html/img/title_background.png -------------------------------------------------------------------------------- /html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UZTextView Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

UZTextView

14 | sonson 15 |
16 | 17 | 20 | 21 |
22 |
23 |
24 | 27 | 32 |
33 | 34 | 35 | 36 | 37 | 38 |
39 |

Class References

40 | 45 |
46 | 47 | 48 | 49 |
50 | 51 |

Protocol References

52 | 57 | 58 | 59 |

Constant References

60 | 67 | 68 | 69 |

Category References

70 | 77 | 78 |
79 | 80 |
81 | 84 | 94 |
95 |
96 | 97 | -------------------------------------------------------------------------------- /screenshot/UZTextView.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/UZTextView/53ff6ecd0ee017b4d6a4e8d454fddd78b150a31b/screenshot/UZTextView.gif -------------------------------------------------------------------------------- /screenshot/sample01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/UZTextView/53ff6ecd0ee017b4d6a4e8d454fddd78b150a31b/screenshot/sample01.jpg --------------------------------------------------------------------------------