diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-1024.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-1024.png new file mode 100644 index 00000000..f7fd7301 Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-1024.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-20.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-20.png similarity index 61% rename from Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-20.png rename to Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-20.png index 02749dcb..82104c36 100644 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-20.png and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-20.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-20@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-20@2x.png new file mode 100644 index 00000000..a509ef3e Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-20@2x.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-20@3x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-20@3x.png new file mode 100644 index 00000000..941606e2 Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-20@3x.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-29.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-29.png similarity index 52% rename from Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-29.png rename to Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-29.png index 9df340d8..a13ff072 100644 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-29.png and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-29.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-29@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-29@2x.png new file mode 100644 index 00000000..c0edd8d3 Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-29@2x.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-29@3x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-29@3x.png new file mode 100644 index 00000000..6eef5cfe Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-29@3x.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-40.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-40.png new file mode 100644 index 00000000..a509ef3e Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-40.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-40@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-40@2x.png new file mode 100644 index 00000000..f0976b0d Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-40@2x.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-40@3x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-40@3x.png new file mode 100644 index 00000000..5641866b Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-40@3x.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-60@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-60@2x.png new file mode 100644 index 00000000..5641866b Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-60@2x.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-60@3x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-60@3x.png new file mode 100644 index 00000000..0fa9f8b8 Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-60@3x.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-76.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-76.png new file mode 100644 index 00000000..ae3e3afa Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-76.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-76@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-76@2x.png new file mode 100644 index 00000000..193d3bd1 Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-76@2x.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-83.5@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-83.5@2x.png new file mode 100644 index 00000000..ec9de5b8 Binary files /dev/null and b/Example/Sources/Assets.xcassets/AppIcon.appiconset/30243544-83.5@2x.png differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example/Sources/Assets.xcassets/AppIcon.appiconset/Contents.json index 7e029107..fc0dbb74 100644 --- a/Example/Sources/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Example/Sources/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -3,109 +3,109 @@ { "size" : "20x20", "idiom" : "iphone", - "filename" : "mklogo-20@2x.png", + "filename" : "30243544-20@2x.png", "scale" : "2x" }, { "size" : "20x20", "idiom" : "iphone", - "filename" : "mklogo-20@3x.png", + "filename" : "30243544-20@3x.png", "scale" : "3x" }, { "size" : "29x29", "idiom" : "iphone", - "filename" : "mklogo-29@2x.png", + "filename" : "30243544-29@2x.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "iphone", - "filename" : "mklogo-29@3x.png", + "filename" : "30243544-29@3x.png", "scale" : "3x" }, { "size" : "40x40", "idiom" : "iphone", - "filename" : "mklogo-40@2x.png", + "filename" : "30243544-40@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "iphone", - "filename" : "mklogo-40@3x.png", + "filename" : "30243544-40@3x.png", "scale" : "3x" }, { "size" : "60x60", "idiom" : "iphone", - "filename" : "mklogo-60@2x.png", + "filename" : "30243544-60@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", - "filename" : "mklogo-60@3x.png", + "filename" : "30243544-60@3x.png", "scale" : "3x" }, { "size" : "20x20", "idiom" : "ipad", - "filename" : "mklogo-20.png", + "filename" : "30243544-20.png", "scale" : "1x" }, { "size" : "20x20", "idiom" : "ipad", - "filename" : "mklogo-20@2x.png", + "filename" : "30243544-20@2x.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "ipad", - "filename" : "mklogo-29.png", + "filename" : "30243544-29.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "ipad", - "filename" : "mklogo-29@2x.png", + "filename" : "30243544-29@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "ipad", - "filename" : "mklogo-40.png", + "filename" : "30243544-40.png", "scale" : "1x" }, { "size" : "40x40", "idiom" : "ipad", - "filename" : "mklogo-40@2x.png", + "filename" : "30243544-40@2x.png", "scale" : "2x" }, { "size" : "76x76", "idiom" : "ipad", - "filename" : "mklogo-76.png", + "filename" : "30243544-76.png", "scale" : "1x" }, { "size" : "76x76", "idiom" : "ipad", - "filename" : "mklogo-76@2x.png", + "filename" : "30243544-76@2x.png", "scale" : "2x" }, { "size" : "83.5x83.5", "idiom" : "ipad", - "filename" : "mklogo-83.5@2x.png", + "filename" : "30243544-83.5@2x.png", "scale" : "2x" }, { "size" : "1024x1024", "idiom" : "ios-marketing", - "filename" : "mklogo-1024.png", + "filename" : "30243544-1024.png", "scale" : "1x" } ], diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-1024.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-1024.png deleted file mode 100644 index 86f5cce5..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-1024.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-20@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-20@2x.png deleted file mode 100644 index fc483239..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-20@2x.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-20@3x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-20@3x.png deleted file mode 100644 index 29715453..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-20@3x.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-29@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-29@2x.png deleted file mode 100644 index 4d3e1ce1..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-29@2x.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-29@3x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-29@3x.png deleted file mode 100644 index 5c0880fe..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-29@3x.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-40.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-40.png deleted file mode 100644 index fc483239..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-40.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-40@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-40@2x.png deleted file mode 100644 index 8f713f6d..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-40@2x.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-40@3x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-40@3x.png deleted file mode 100644 index fb0b222b..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-40@3x.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-60@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-60@2x.png deleted file mode 100644 index fb0b222b..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-60@2x.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-60@3x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-60@3x.png deleted file mode 100644 index 85de19c2..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-60@3x.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-76.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-76.png deleted file mode 100644 index 36196c27..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-76.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-76@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-76@2x.png deleted file mode 100644 index 1b866dfa..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-76@2x.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-83.5@2x.png b/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-83.5@2x.png deleted file mode 100644 index 0a721944..00000000 Binary files a/Example/Sources/Assets.xcassets/AppIcon.appiconset/mklogo-83.5@2x.png and /dev/null differ diff --git a/Example/Sources/Assets.xcassets/mkorglogo.imageset/30243544.png b/Example/Sources/Assets.xcassets/mkorglogo.imageset/30243544.png new file mode 100644 index 00000000..0ae8e9a0 Binary files /dev/null and b/Example/Sources/Assets.xcassets/mkorglogo.imageset/30243544.png differ diff --git a/Example/Sources/Assets.xcassets/mkorglogo.imageset/Contents.json b/Example/Sources/Assets.xcassets/mkorglogo.imageset/Contents.json new file mode 100644 index 00000000..29ddfbef --- /dev/null +++ b/Example/Sources/Assets.xcassets/mkorglogo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "30243544.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Sources/Base.lproj/LaunchScreen.storyboard b/Example/Sources/Base.lproj/LaunchScreen.storyboard index ae101f4b..a61d0841 100644 --- a/Example/Sources/Base.lproj/LaunchScreen.storyboard +++ b/Example/Sources/Base.lproj/LaunchScreen.storyboard @@ -1,11 +1,11 @@ - + - + @@ -26,7 +26,7 @@ - + diff --git a/Example/Sources/SampleData.swift b/Example/Sources/SampleData.swift index 786524b4..e0944fa9 100644 --- a/Example/Sources/SampleData.swift +++ b/Example/Sources/SampleData.swift @@ -176,7 +176,7 @@ final class SampleData { func getMessages(count: Int, completion: ([MockMessage]) -> Void) { var messages: [MockMessage] = [] - for _ in 0...count { + for _ in 0.. CGSize { + guard let messagesCollectionView = collectionView as? MessagesCollectionView else { return .zero } + guard let messagesDataSource = messagesCollectionView.messagesDataSource else { return .zero } + guard let messagesLayoutDelegate = messagesCollectionView.messagesLayoutDelegate else { return .zero } + // Could pose a problem if subclass behaviors allows more than one item per section + let indexPath = IndexPath(item: 0, section: section) + let message = messagesDataSource.messageForItem(at: indexPath, in: messagesCollectionView) + return messagesLayoutDelegate.headerViewSize(for: message, at: indexPath, in: messagesCollectionView) + } + + open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { + guard let messagesCollectionView = collectionView as? MessagesCollectionView else { return .zero } + guard let messagesDataSource = messagesCollectionView.messagesDataSource else { return .zero } + guard let messagesLayoutDelegate = messagesCollectionView.messagesLayoutDelegate else { return .zero } + // Could pose a problem if subclass behaviors allows more than one item per section + let indexPath = IndexPath(item: 0, section: section) + let message = messagesDataSource.messageForItem(at: indexPath, in: messagesCollectionView) + return messagesLayoutDelegate.footerViewSize(for: message, at: indexPath, in: messagesCollectionView) + } } @@ -230,27 +250,7 @@ extension MessagesViewController: UICollectionViewDataSource { } } - - open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - guard let messagesCollectionView = collectionView as? MessagesCollectionView else { return .zero } - guard let messagesDataSource = messagesCollectionView.messagesDataSource else { return .zero } - guard let messagesLayoutDelegate = messagesCollectionView.messagesLayoutDelegate else { return .zero } - // Could pose a problem if subclass behaviors allows more than one item per section - let indexPath = IndexPath(item: 0, section: section) - let message = messagesDataSource.messageForItem(at: indexPath, in: messagesCollectionView) - return messagesLayoutDelegate.headerViewSize(for: message, at: indexPath, in: messagesCollectionView) - } - - open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { - guard let messagesCollectionView = collectionView as? MessagesCollectionView else { return .zero } - guard let messagesDataSource = messagesCollectionView.messagesDataSource else { return .zero } - guard let messagesLayoutDelegate = messagesCollectionView.messagesLayoutDelegate else { return .zero } - // Could pose a problem if subclass behaviors allows more than one item per section - let indexPath = IndexPath(item: 0, section: section) - let message = messagesDataSource.messageForItem(at: indexPath, in: messagesCollectionView) - return messagesLayoutDelegate.footerViewSize(for: message, at: indexPath, in: messagesCollectionView) - } - + } // MARK: - Keyboard Handling diff --git a/Sources/Views/InputBarItem.swift b/Sources/Views/InputBarItem.swift index 7406d19b..77491ac2 100644 --- a/Sources/Views/InputBarItem.swift +++ b/Sources/Views/InputBarItem.swift @@ -183,8 +183,8 @@ open class InputBarButtonItem: UIButton { open func setSize(_ newValue: CGSize?, animated: Bool) { size = newValue if animated, let position = parentStackViewPosition { - messageInputBar?.performLayout(animated) { - self.messageInputBar?.layoutStackViews([position]) + messageInputBar?.performLayout(animated) { [weak self] in + self?.messageInputBar?.layoutStackViews([position]) } } } diff --git a/Sources/Views/MessageLabel.swift b/Sources/Views/MessageLabel.swift index 2d48ab12..37cc5b0a 100644 --- a/Sources/Views/MessageLabel.swift +++ b/Sources/Views/MessageLabel.swift @@ -49,7 +49,7 @@ open class MessageLabel: UILabel, UIGestureRecognizerDelegate { return textStorage }() - private lazy var rangesForDetectors: [DetectorType: [(NSRange, Any?)]] = [:] + private lazy var rangesForDetectors: [DetectorType: [(NSRange, MessageTextCheckingType)]] = [:] // MARK: - Public Properties @@ -321,13 +321,13 @@ open class MessageLabel: UILabel, UIGestureRecognizerDelegate { private func detectorAttributes(for checkingResultType: NSTextCheckingResult.CheckingType) -> [NSAttributedStringKey: Any] { switch checkingResultType { - case NSTextCheckingResult.CheckingType.address: + case .address: return addressAttributes - case NSTextCheckingResult.CheckingType.date: + case .date: return dateAttributes - case NSTextCheckingResult.CheckingType.phoneNumber: + case .phoneNumber: return phoneNumberAttributes - case NSTextCheckingResult.CheckingType.link: + case .link: return urlAttributes default: fatalError("Received an unrecognized NSTextCheckingResult.CheckingType") @@ -349,24 +349,24 @@ open class MessageLabel: UILabel, UIGestureRecognizerDelegate { for result in checkingResults { switch result.resultType { - case NSTextCheckingResult.CheckingType.address: + case .address: var ranges = rangesForDetectors[.address] ?? [] - let tuple = (result.range, result.addressComponents) as (NSRange, Any?) + let tuple: (NSRange, MessageTextCheckingType) = (result.range, .addressComponents(result.addressComponents)) ranges.append(tuple) rangesForDetectors.updateValue(ranges, forKey: .address) - case NSTextCheckingResult.CheckingType.date: + case .date: var ranges = rangesForDetectors[.date] ?? [] - let tuple = (result.range, result.date) as (NSRange, Any?) + let tuple: (NSRange, MessageTextCheckingType) = (result.range, .date(result.date)) ranges.append(tuple) rangesForDetectors.updateValue(ranges, forKey: .date) - case NSTextCheckingResult.CheckingType.phoneNumber: + case .phoneNumber: var ranges = rangesForDetectors[.phoneNumber] ?? [] - let tuple = (result.range, result.phoneNumber) as (NSRange, Any?) + let tuple: (NSRange, MessageTextCheckingType) = (result.range, .phoneNumber(result.phoneNumber)) ranges.append(tuple) rangesForDetectors.updateValue(ranges, forKey: .phoneNumber) - case NSTextCheckingResult.CheckingType.link: + case .link: var ranges = rangesForDetectors[.url] ?? [] - let tuple = (result.range, result.url) as (NSRange, Any?) + let tuple: (NSRange, MessageTextCheckingType) = (result.range, .link(result.url)) ranges.append(tuple) rangesForDetectors.updateValue(ranges, forKey: .url) default: @@ -428,20 +428,24 @@ open class MessageLabel: UILabel, UIGestureRecognizerDelegate { } } - private func handleGesture(for detectorType: DetectorType, value: Any?) { - - switch detectorType { - case .address: - guard let addressComponents = value as? [String: String] else { return } - handleAddress(addressComponents) - case .phoneNumber: - guard let phoneNumber = value as? String else { return } + private func handleGesture(for detectorType: DetectorType, value: MessageTextCheckingType) { + + switch value { + case let .addressComponents(addressComponents): + var transformedAddressComponents = [String: String]() + guard let addressComponents = addressComponents else { return } + addressComponents.forEach { (key, value) in + transformedAddressComponents[key.rawValue] = value + } + handleAddress(transformedAddressComponents) + case let .phoneNumber(phoneNumber): + guard let phoneNumber = phoneNumber else { return } handlePhoneNumber(phoneNumber) - case .date: - guard let date = value as? Date else { return } + case let .date(date): + guard let date = date else { return } handleDate(date) - case .url: - guard let url = value as? URL else { return } + case let .link(url): + guard let url = url else { return } handleURL(url) } } @@ -463,3 +467,10 @@ open class MessageLabel: UILabel, UIGestureRecognizerDelegate { } } + +fileprivate enum MessageTextCheckingType { + case addressComponents([NSTextCheckingKey: String]?) + case date(Date?) + case phoneNumber(String?) + case link(URL?) +}