diff --git a/Atributika.podspec b/Atributika.podspec index 865a5a5..9c5b9bd 100644 --- a/Atributika.podspec +++ b/Atributika.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Atributika" - s.version = "4.7.2" + s.version = "4.7.3" s.summary = "Convert text with HTML tags, hashtags, mentions, links into NSAttributedString. Make them clickable with UILabel drop-in replacement." s.description = <<-DESC `Atributika` is an easy and painless way to build NSAttributedString. It is able to detect HTML-like tags, links, phone numbers, hashtags, any regex or even standard ios data detectors and style them with various attributes like font, color, etc. `Atributika` comes with drop-in label replacement `AttributedLabel` which is able to make any detection clickable. diff --git a/Atributika.xcodeproj/project.pbxproj b/Atributika.xcodeproj/project.pbxproj index 4b130b1..af2a2c0 100644 --- a/Atributika.xcodeproj/project.pbxproj +++ b/Atributika.xcodeproj/project.pbxproj @@ -18,6 +18,9 @@ 1B2F839F1E5C98F0009AFBCA /* Atributika.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D97C1BEFF229002C0205 /* Atributika.framework */; }; 1B2F83A01E5C98F0009AFBCA /* Atributika.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D97C1BEFF229002C0205 /* Atributika.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1B3836A01F97C224001DB333 /* AttributedLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B38369F1F97C224001DB333 /* AttributedLabel.swift */; }; + 1B4638582259FFE400ED5BA9 /* AttributedLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B38369F1F97C224001DB333 /* AttributedLabel.swift */; }; + 1B4638592259FFE400ED5BA9 /* AttributedLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B38369F1F97C224001DB333 /* AttributedLabel.swift */; }; + 1B46385A2259FFE400ED5BA9 /* AttributedLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B38369F1F97C224001DB333 /* AttributedLabel.swift */; }; 1BB55AD11E5C73EF00CE6EAD /* AttributedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BB55ACC1E5C73EF00CE6EAD /* AttributedText.swift */; }; 1BB55AD21E5C73EF00CE6EAD /* AttributedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BB55ACC1E5C73EF00CE6EAD /* AttributedText.swift */; }; 1BB55AD31E5C73F000CE6EAD /* AttributedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BB55ACC1E5C73EF00CE6EAD /* AttributedText.swift */; }; @@ -627,6 +630,7 @@ 1BB55AD31E5C73F000CE6EAD /* AttributedText.swift in Sources */, 1B2E55DB219321FB00D2B934 /* HTMLSpecials.swift in Sources */, 1BB55ADF1E5C73F000CE6EAD /* String+Detection.swift in Sources */, + 1B4638592259FFE400ED5BA9 /* AttributedLabel.swift in Sources */, 1BB55AD71E5C73F000CE6EAD /* NSAttributedString+Utils.swift in Sources */, 1BB55AE31E5C73F000CE6EAD /* Style.swift in Sources */, ); @@ -640,6 +644,7 @@ 1BB55AD41E5C73F000CE6EAD /* AttributedText.swift in Sources */, 1B2E55DC219321FB00D2B934 /* HTMLSpecials.swift in Sources */, 1BB55AE01E5C73F000CE6EAD /* String+Detection.swift in Sources */, + 1B46385A2259FFE400ED5BA9 /* AttributedLabel.swift in Sources */, 1BB55AD81E5C73F000CE6EAD /* NSAttributedString+Utils.swift in Sources */, 1BB55AE41E5C73F000CE6EAD /* Style.swift in Sources */, ); @@ -653,6 +658,7 @@ 1BB55AD21E5C73EF00CE6EAD /* AttributedText.swift in Sources */, 1B2E55DA219321FB00D2B934 /* HTMLSpecials.swift in Sources */, 1BB55ADE1E5C73F000CE6EAD /* String+Detection.swift in Sources */, + 1B4638582259FFE400ED5BA9 /* AttributedLabel.swift in Sources */, 1BB55AD61E5C73F000CE6EAD /* NSAttributedString+Utils.swift in Sources */, 1BB55AE21E5C73F000CE6EAD /* Style.swift in Sources */, ); diff --git a/Demo/AttributedLabelDemoViewController.swift b/Demo/AttributedLabelDemoViewController.swift index dee12c6..e592cfa 100644 --- a/Demo/AttributedLabelDemoViewController.swift +++ b/Demo/AttributedLabelDemoViewController.swift @@ -30,6 +30,7 @@ class AttributedLabelDemoViewController: UIViewController { private var tweets: [String] = [ "@e2F If only Bradley's arm was longer. Best photo ever. 😊 #oscars https://pic.twitter.com/C9U5NOtGap
Check this link", + "@e2F If only Bradley's arm was longer. Best photo ever. 😊 #oscars https://pic.twitter.com/C9U5NOtGap
Check this link that won't detect click here", "For every retweet this gets, Pedigree will donate one bowl of dog food to dogs in need! 😊 #tweetforbowls", "All the love as always. H", "We got kicked out of a @Delta airplane because I spoke Arabic to my mom on the phone and with my friend slim... WTFFFFFFFF please spread", diff --git a/Sources/AttributedLabel.swift b/Sources/AttributedLabel.swift index 418f4d7..eb2c6bd 100644 --- a/Sources/AttributedLabel.swift +++ b/Sources/AttributedLabel.swift @@ -29,7 +29,7 @@ open class AttributedLabel: UIView { open var attributedText: AttributedText? { set { - state.attributedTextAndString = newValue.map { ($0, $0.attributedString) } + state = State(attributedTextAndString: newValue.map { ($0, $0.attributedString) }, isEnabled: state.isEnabled, detection: nil) setNeedsLayout() } get { @@ -245,7 +245,16 @@ extension NSAttributedString { paragraphStyle.alignment = textAlignment let inheritedAttributes = [AttributedStringKey.font: font as Any, AttributedStringKey.paragraphStyle: paragraphStyle as Any] - let result = NSMutableAttributedString(string: string, attributes: inheritedAttributes) + + var s = string + + //since iOS 11, UILabel line break logic was changed. It tries to avoid orphaned words on last line. To mimic this we can replace last space with non-breaking space + let version = OperatingSystemVersion(majorVersion: 11, minorVersion: 0, patchVersion: 0) + if ProcessInfo.processInfo.isOperatingSystemAtLeast(version) { + s = s.replacingLastOccurrenceOfString(" ", with: "\u{a0}") + } + + let result = NSMutableAttributedString(string: s, attributes: inheritedAttributes) result.beginEditing() enumerateAttributes(in: NSMakeRange(0, length), options: .longestEffectiveRangeNotRequired, using: { (attributes, range, _) in @@ -257,4 +266,20 @@ extension NSAttributedString { } } +extension String +{ + func replacingLastOccurrenceOfString(_ searchString: String, + with replacementString: String) -> String + { + if let range = range(of: searchString, + options: [.backwards], + range: nil, + locale: nil) { + + return replacingCharacters(in: range, with: replacementString) + } + return self + } +} + #endif