diff --git a/HandyUIKit.podspec b/HandyUIKit.podspec index 047de5d..fd2dfe8 100644 --- a/HandyUIKit.podspec +++ b/HandyUIKit.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "HandyUIKit" - s.version = "1.3.0" + s.version = "1.4.0" s.summary = "Handy UI features that should have been part of UIKit in the first place." s.description = <<-DESC diff --git a/HandyUIKit.xcodeproj/project.pbxproj b/HandyUIKit.xcodeproj/project.pbxproj index 3315207..178e5bb 100644 --- a/HandyUIKit.xcodeproj/project.pbxproj +++ b/HandyUIKit.xcodeproj/project.pbxproj @@ -15,6 +15,8 @@ A14E0AE41E1F987C00DFC788 /* HandyUIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A14E0ADB1E1F987C00DFC788 /* HandyUIKit.framework */; }; A14E0B111E1F9B3100DFC788 /* UIViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A14E0B0E1E1F9B3100DFC788 /* UIViewExtension.swift */; }; A14E0B121E1F9B3100DFC788 /* UIViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A14E0B0E1E1F9B3100DFC788 /* UIViewExtension.swift */; }; + A1D4453C1E59C9370014A250 /* NSAttributedStringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1D4453B1E59C9370014A250 /* NSAttributedStringExtension.swift */; }; + A1D4453D1E59C9370014A250 /* NSAttributedStringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1D4453B1E59C9370014A250 /* NSAttributedStringExtension.swift */; }; A1F221681E3E07DD00419B06 /* UIColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1F221671E3E07DD00419B06 /* UIColorExtension.swift */; }; A1F221691E3E07DD00419B06 /* UIColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1F221671E3E07DD00419B06 /* UIColorExtension.swift */; }; A1F2216B1E3E08AF00419B06 /* CoreGraphicsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1F2216A1E3E08AE00419B06 /* CoreGraphicsExtension.swift */; }; @@ -54,6 +56,7 @@ A14E0AF61E1F98E400DFC788 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A14E0AFB1E1F98E400DFC788 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A14E0B0E1E1F9B3100DFC788 /* UIViewExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewExtension.swift; sourceTree = ""; }; + A1D4453B1E59C9370014A250 /* NSAttributedStringExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSAttributedStringExtension.swift; sourceTree = ""; }; A1F221671E3E07DD00419B06 /* UIColorExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColorExtension.swift; sourceTree = ""; }; A1F2216A1E3E08AE00419B06 /* CoreGraphicsExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreGraphicsExtension.swift; sourceTree = ""; }; A1F2216D1E3E0B7700419B06 /* CoreExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreExtensionTests.swift; sourceTree = ""; }; @@ -182,6 +185,7 @@ A1F221671E3E07DD00419B06 /* UIColorExtension.swift */, A1F2216A1E3E08AE00419B06 /* CoreGraphicsExtension.swift */, A11830F21E5996FD00CBE087 /* StringExtension.swift */, + A1D4453B1E59C9370014A250 /* NSAttributedStringExtension.swift */, ); path = Extensions; sourceTree = ""; @@ -423,6 +427,7 @@ A1F221801E3E778F00419B06 /* ColorSpaces.swift in Sources */, A1F221681E3E07DD00419B06 /* UIColorExtension.swift in Sources */, A11830F31E5996FD00CBE087 /* StringExtension.swift in Sources */, + A1D4453C1E59C9370014A250 /* NSAttributedStringExtension.swift in Sources */, A1F2216B1E3E08AF00419B06 /* CoreGraphicsExtension.swift in Sources */, A14E0B111E1F9B3100DFC788 /* UIViewExtension.swift in Sources */, ); @@ -445,6 +450,7 @@ A1F221811E3E778F00419B06 /* ColorSpaces.swift in Sources */, A1F221691E3E07DD00419B06 /* UIColorExtension.swift in Sources */, A11830F41E5996FD00CBE087 /* StringExtension.swift in Sources */, + A1D4453D1E59C9370014A250 /* NSAttributedStringExtension.swift in Sources */, A1F2216C1E3E08AF00419B06 /* CoreGraphicsExtension.swift in Sources */, A14E0B121E1F9B3100DFC788 /* UIViewExtension.swift in Sources */, ); diff --git a/README.md b/README.md index 99b51ae..804bad3 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ alt="Build Status"> alt="codebeat badge"> - + Swift: 3.0 @@ -53,7 +53,7 @@ You can of course also just include this framework manually into your project by Place the following line to your Cartfile: ``` Swift -github "Flinesoft/HandyUIKit" ~> 1.3 +github "Flinesoft/HandyUIKit" ~> 1.4 ``` Now run `carthage update`. Then drag & drop the HandyUIKit.framework in the Carthage/build folder to your project. Now you can `import HandyUIKit` in each class you want to use its features. Refer to the [Carthage README](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) for detailed / updated instructions. @@ -68,7 +68,7 @@ platform :ios, '8.0' use_frameworks! target 'MyAppTarget' do - pod 'HandyUIKit', '~> 1.3' + pod 'HandyUIKit', '~> 1.4' end ``` @@ -88,6 +88,7 @@ Open the Playground from within the `.xcworkspace` in order for it to work. - [UIColor](#uicolorextension) - [UIView](#uiviewextension) - [CoreGraphics](#coregraphicsextensions) + - [StringExtension](#stringextension) --- @@ -250,6 +251,13 @@ loremIpsum.width(forFixedHeight: 21, font: UIFont.systemFont(ofSize: 12, weight: // => 2351.0390625 ``` +#### .hyphenated() +A hyphenated NSAttributedString with justified alignment and word wrapping line break mode. + +``` Swift +loremIpsum.hyphenated() // => a justified & hyphenated NSAttributedString object +``` + ## Contributing diff --git a/Sources/Code/Extensions/NSAttributedStringExtension.swift b/Sources/Code/Extensions/NSAttributedStringExtension.swift new file mode 100644 index 0000000..5becd6e --- /dev/null +++ b/Sources/Code/Extensions/NSAttributedStringExtension.swift @@ -0,0 +1,39 @@ +// +// NSAttributedStringExtension.swift +// HandyUIKit +// +// Created by Cihat Gündüz on 19.02.17. +// Copyright © 2017 Flinesoft. All rights reserved. +// + +import UIKit + +extension NSAttributedString { + /// Calculates and returns the height needed to fit the text into a width-constrained rect. + /// + /// - Parameters: + /// - fixedWidth: The fixed width of the rect. + /// - font: The font of the text to calculate for. + /// - Returns: The height needed to fit the text into a width-constrained rect. + public func height(forFixedWidth fixedWidth: CGFloat, font: UIFont) -> CGFloat { + let constraintSize = CGSize(width: fixedWidth, height: .greatestFiniteMagnitude) + return rect(for: constraintSize, font: font).height + } + + /// Calculates and returns the width needed to fit the text into a height-constrained rect. + /// + /// - Parameters: + /// - fixedHeight: The fixed height of the rect. + /// - font: The font of the text to calculate for. + /// - Returns: The width needed to fit the text into a height-constrained rect. + public func width(forFixedHeight fixedHeight: CGFloat, font: UIFont) -> CGFloat { + let constraintSize = CGSize(width: .greatestFiniteMagnitude, height: fixedHeight) + return rect(for: constraintSize, font: font).width + } + + private func rect(for constraintSize: CGSize, font: UIFont) -> CGRect { + let copy = mutableCopy() as! NSMutableAttributedString + copy.addAttribute(NSFontAttributeName, value: font, range: NSMakeRange(0, length)) + return copy.boundingRect(with: constraintSize, options: .usesLineFragmentOrigin, context: nil) + } +} diff --git a/Sources/Code/Extensions/StringExtension.swift b/Sources/Code/Extensions/StringExtension.swift index 35aa219..b5b3347 100644 --- a/Sources/Code/Extensions/StringExtension.swift +++ b/Sources/Code/Extensions/StringExtension.swift @@ -35,4 +35,14 @@ extension String { let attributes = [NSFontAttributeName: font] return (self as NSString).boundingRect(with: constraintSize, options: .usesLineFragmentOrigin, attributes: attributes, context: nil) } + + /// - Returns: A hyphenated NSAttributedString with justified alignment and word wrapping line break mode. + public func hyphenated() -> NSAttributedString { + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.hyphenationFactor = 1.0 + paragraphStyle.alignment = .justified + paragraphStyle.lineBreakMode = .byWordWrapping + + return NSAttributedString(string: self, attributes: [NSParagraphStyleAttributeName: paragraphStyle]) + } } diff --git a/Sources/Supporting Files/Info.plist b/Sources/Supporting Files/Info.plist index 18065b5..5385f16 100644 --- a/Sources/Supporting Files/Info.plist +++ b/Sources/Supporting Files/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.3.0 + 1.4.0 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/UsageExamples.playground/Contents.swift b/UsageExamples.playground/Contents.swift index 133d97e..b79ac3a 100644 --- a/UsageExamples.playground/Contents.swift +++ b/UsageExamples.playground/Contents.swift @@ -121,3 +121,8 @@ loremIpsum.height(forFixedWidth: 300, font: UIFont.systemFont(ofSize: 14, weight //: Calculates and returns the width needed to fit the text into a height-constrained rect. loremIpsum.width(forFixedHeight: 21, font: UIFont.systemFont(ofSize: 12, weight: UIFontWeightUltraLight)) + +//: ### .hyphenated() +//: A hyphenated NSAttributedString with justified alignment and word wrapping line break mode. + +loremIpsum.hyphenated()