From f46cb24d0774d353d272f8d15c3bdf12b99cf1ef Mon Sep 17 00:00:00 2001 From: Sash Zats Date: Fri, 2 Mar 2018 05:04:47 +0900 Subject: [PATCH 1/4] Replace @twitter handler label with a button --- trySwift/SpeakerTableViewCell.xib | 35 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/trySwift/SpeakerTableViewCell.xib b/trySwift/SpeakerTableViewCell.xib index 245cf37..1d21317 100644 --- a/trySwift/SpeakerTableViewCell.xib +++ b/trySwift/SpeakerTableViewCell.xib @@ -1,11 +1,10 @@ - + - - + @@ -16,46 +15,46 @@ - + - + - + - - - + + - + From 8028a0c4320e37a13ffc10c22dff2b0aca2e84c1 Mon Sep 17 00:00:00 2001 From: Sash Zats Date: Fri, 2 Mar 2018 05:05:32 +0900 Subject: [PATCH 2/4] Handle @twitter handler tap by calling TwitterFollowDelegate delegate --- .../OfficeHoursDetailViewController.swift | 2 +- trySwift/SessionDetailsViewController.swift | 2 +- trySwift/SpeakerDetailViewController.swift | 2 +- trySwift/SpeakerTableViewCell.swift | 26 ++++++++++++++----- trySwift/SpeakersViewController.swift | 2 +- trySwift/WorkshopDetailViewController.swift | 2 +- 6 files changed, 24 insertions(+), 12 deletions(-) diff --git a/trySwift/OfficeHoursDetailViewController.swift b/trySwift/OfficeHoursDetailViewController.swift index 95bfaa8..b379e5c 100644 --- a/trySwift/OfficeHoursDetailViewController.swift +++ b/trySwift/OfficeHoursDetailViewController.swift @@ -47,7 +47,7 @@ extension OfficeHoursDetailViewController { return cell case .speakerInfo: let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as SpeakerTableViewCell - cell.configure(withSpeaker: speaker, selectionEnabled: false, accessoryEnabled: false) + cell.configure(withSpeaker: speaker, selectionEnabled: false, accessoryEnabled: false, delegate: self) return cell case .bio: let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as TextTableViewCell diff --git a/trySwift/SessionDetailsViewController.swift b/trySwift/SessionDetailsViewController.swift index c9fa3a5..dce3bfc 100644 --- a/trySwift/SessionDetailsViewController.swift +++ b/trySwift/SessionDetailsViewController.swift @@ -49,7 +49,7 @@ extension SessionDetailsViewController { return cell case .speakerInfo: let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as SpeakerTableViewCell - cell.configure(withSpeaker: presentation.speaker!, selectionEnabled: false, accessoryEnabled: false) + cell.configure(withSpeaker: presentation.speaker!, selectionEnabled: false, accessoryEnabled: false, delegate: self) return cell case .summary: let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as TextTableViewCell diff --git a/trySwift/SpeakerDetailViewController.swift b/trySwift/SpeakerDetailViewController.swift index dff7949..bcd91cc 100644 --- a/trySwift/SpeakerDetailViewController.swift +++ b/trySwift/SpeakerDetailViewController.swift @@ -43,7 +43,7 @@ extension SpeakerDetailViewController { switch SpeakerDetail(rawValue: indexPath.row)! { case .header: let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as SpeakerTableViewCell - cell.configure(withSpeaker: speaker, selectionEnabled: false, accessoryEnabled: false) + cell.configure(withSpeaker: speaker, selectionEnabled: false, accessoryEnabled: false, delegate: self) return cell case .bio: let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as TextTableViewCell diff --git a/trySwift/SpeakerTableViewCell.swift b/trySwift/SpeakerTableViewCell.swift index 40c8b0d..b7a16c2 100644 --- a/trySwift/SpeakerTableViewCell.swift +++ b/trySwift/SpeakerTableViewCell.swift @@ -14,22 +14,31 @@ class SpeakerTableViewCell: UITableViewCell { @IBOutlet weak var speakerImageView: UIImageView! @IBOutlet weak var speakerNameLabel: UILabel! - @IBOutlet weak var speakerTwitterLabel: UILabel! - + @IBOutlet weak var speakerTwitterButton: UIButton! + + fileprivate var speaker: Speaker? + fileprivate weak var delegate: TwitterFollowDelegate? + override func awakeFromNib() { super.awakeFromNib() - - speakerTwitterLabel.textColor = .trySwiftAccentColor() + speakerTwitterButton.setTitleColor(.trySwiftAccentColor(), for: .normal) } - func configure(withSpeaker speaker: Speaker, selectionEnabled: Bool = true, accessoryEnabled: Bool = true) { + @IBAction func speakerTwitterButtonDidTap(_ sender: Any) { + guard let speaker = speaker else { + assertionFailure("Speaker is not set") + return + } + self.delegate?.followUser(speaker.twitter) + } + + func configure(withSpeaker speaker: Speaker, selectionEnabled: Bool = true, accessoryEnabled: Bool = true, delegate: TwitterFollowDelegate) { let scale = UIScreen.main.scale let processor = RoundCornerImageProcessor(cornerRadius: 34, targetSize: CGSize(width: 67, height: 67)) speakerImageView.kf.setImage(with: speaker.imageURL, placeholder: nil, options: [.processor(processor), .scaleFactor(scale)]) speakerNameLabel.text = speaker.localizedName - speakerTwitterLabel.text = "@\(speaker.twitter)" - + speakerTwitterButton.setTitle("@\(speaker.twitter)", for: .normal) if !selectionEnabled { selectionStyle = .none } @@ -40,5 +49,8 @@ class SpeakerTableViewCell: UITableViewCell { setNeedsUpdateConstraints() layoutIfNeeded() + + self.speaker = speaker + self.delegate = delegate } } diff --git a/trySwift/SpeakersViewController.swift b/trySwift/SpeakersViewController.swift index 766fe4c..086f5e7 100644 --- a/trySwift/SpeakersViewController.swift +++ b/trySwift/SpeakersViewController.swift @@ -72,7 +72,7 @@ extension SpeakersViewController { override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as SpeakerTableViewCell - cell.configure(withSpeaker: speakers[indexPath.row]) + cell.configure(withSpeaker: speakers[indexPath.row], delegate: self) return cell } diff --git a/trySwift/WorkshopDetailViewController.swift b/trySwift/WorkshopDetailViewController.swift index a531305..55c021b 100644 --- a/trySwift/WorkshopDetailViewController.swift +++ b/trySwift/WorkshopDetailViewController.swift @@ -56,7 +56,7 @@ extension WorkshopDetailViewController { return cell case .speakerInfo: let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as SpeakerTableViewCell - cell.configure(withSpeaker: presentation.speaker!, selectionEnabled: false, accessoryEnabled: false) + cell.configure(withSpeaker: presentation.speaker!, selectionEnabled: false, accessoryEnabled: false, delegate: self) return cell case .summary: let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as TextTableViewCell From cc957c22b91ac92fbfda7355059487c21691c46f Mon Sep 17 00:00:00 2001 From: Sash Zats Date: Fri, 2 Mar 2018 05:05:54 +0900 Subject: [PATCH 3/4] Change twitter url from http to https --- trySwift/UIViewControllerExtension.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trySwift/UIViewControllerExtension.swift b/trySwift/UIViewControllerExtension.swift index f440812..0de1acd 100644 --- a/trySwift/UIViewControllerExtension.swift +++ b/trySwift/UIViewControllerExtension.swift @@ -37,7 +37,7 @@ extension UIViewController: TwitterFollowDelegate { } if !applicationOpened { - if let twitterURL = URL(string: "http://twitter.com/\(username)") { + if let twitterURL = URL(string: "https://twitter.com/\(username)") { openSafariViewController(withURL: twitterURL) } } From f3dc8048dcc67e6574365e5a92f1d49bd3c2f573 Mon Sep 17 00:00:00 2001 From: Sash Zats Date: Fri, 2 Mar 2018 05:11:23 +0900 Subject: [PATCH 4/4] Extract twitter delegate into a separate file since this is a shared functionality now --- trySwift.xcodeproj/project.pbxproj | 12 +++++++ trySwift/Twitter/TwitterFollowDelegate.swift | 35 ++++++++++++++++++++ trySwift/TwitterFollowTableViewCell.swift | 4 --- trySwift/UIViewControllerExtension.swift | 21 ------------ 4 files changed, 47 insertions(+), 25 deletions(-) create mode 100644 trySwift/Twitter/TwitterFollowDelegate.swift diff --git a/trySwift.xcodeproj/project.pbxproj b/trySwift.xcodeproj/project.pbxproj index b270d9a..143a0b0 100644 --- a/trySwift.xcodeproj/project.pbxproj +++ b/trySwift.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ 499CCFF21CC2E0F4007A5BBB /* UIViewControllerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 499CCFF11CC2E0F4007A5BBB /* UIViewControllerExtension.swift */; }; 49F7B2811E8475F900F09768 /* SplitViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49F7B2801E8475F900F09768 /* SplitViewController.swift */; }; 4D498DB1B98D4B496FDBB7AA /* Pods_try__Extension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD2E9D5733A6E1B6E10AFEEF /* Pods_try__Extension.framework */; }; + 5CDB20792048952A00C3E0D3 /* TwitterFollowDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDB20782048952A00C3E0D3 /* TwitterFollowDelegate.swift */; }; 7AD1E19C80B78BB08E3DF079 /* Pods_trySwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 620220ABCCCDF47FDAF48B67 /* Pods_trySwift.framework */; }; EAFE1C26E49EFABF83487BDC /* Pods_try__Today.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24718BF11477753FCD47A7A8 /* Pods_try__Today.framework */; }; FA0E2B4F1E63B90400B40814 /* SessionDetailInterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA0E2B4E1E63B90400B40814 /* SessionDetailInterfaceController.swift */; }; @@ -193,6 +194,7 @@ 499CCFF11CC2E0F4007A5BBB /* UIViewControllerExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewControllerExtension.swift; sourceTree = ""; }; 49F7B2801E8475F900F09768 /* SplitViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SplitViewController.swift; sourceTree = ""; }; 58F81AD508535BD405F98215 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + 5CDB20782048952A00C3E0D3 /* TwitterFollowDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwitterFollowDelegate.swift; sourceTree = ""; }; 5FA07FBC036240AEF8B7C739 /* Pods-trySwift.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-trySwift.release.xcconfig"; path = "Pods/Target Support Files/Pods-trySwift/Pods-trySwift.release.xcconfig"; sourceTree = ""; }; 620220ABCCCDF47FDAF48B67 /* Pods_trySwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_trySwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6C1F9C27BCD8099DCA758F7A /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; @@ -381,6 +383,14 @@ name = Frameworks; sourceTree = ""; }; + 5CDB20772048951F00C3E0D3 /* Twitter */ = { + isa = PBXGroup; + children = ( + 5CDB20782048952A00C3E0D3 /* TwitterFollowDelegate.swift */, + ); + path = Twitter; + sourceTree = ""; + }; F413680C9BA29129B4319377 /* Pods */ = { isa = PBXGroup; children = ( @@ -449,6 +459,7 @@ FA39E8CB1C6AF89D0074B6BE /* Utilities */ = { isa = PBXGroup; children = ( + 5CDB20772048951F00C3E0D3 /* Twitter */, FA39E8ED1C6C034B0074B6BE /* UIColorExtension.swift */, 499CCFF11CC2E0F4007A5BBB /* UIViewControllerExtension.swift */, FA3A1CB51D68E1950042F8DD /* WatchSessionManager.swift */, @@ -1123,6 +1134,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5CDB20792048952A00C3E0D3 /* TwitterFollowDelegate.swift in Sources */, 499BD62A1D05910200E74061 /* Twitter.swift in Sources */, FA39E90F1C6C81870074B6BE /* SponsorsViewController.swift in Sources */, FA36B7071E5DA3970022E6A9 /* DateFormatterExtension.swift in Sources */, diff --git a/trySwift/Twitter/TwitterFollowDelegate.swift b/trySwift/Twitter/TwitterFollowDelegate.swift new file mode 100644 index 0000000..25e069f --- /dev/null +++ b/trySwift/Twitter/TwitterFollowDelegate.swift @@ -0,0 +1,35 @@ +// +// TwitterFollowDelegate.swift +// trySwift +// +// Created by Sash Zats on 3/2/18. +// Copyright © 2018 NatashaTheRobot. All rights reserved. +// + +import UIKit + +protocol TwitterFollowDelegate: class { + func followUser(_ username: String) +} + +extension UIViewController: TwitterFollowDelegate { + + func followUser(_ username: String) { + var applicationOpened = false + let application = UIApplication.shared + for twitterURL in Twitter.urls(forUsername: username) { + if let url = URL(string: twitterURL) , application.canOpenURL(url) && !applicationOpened { + application.open(url, options: [String:Any](), completionHandler: nil) + applicationOpened = true + break + } + } + + if !applicationOpened { + if let twitterURL = URL(string: "https://twitter.com/\(username)") { + openSafariViewController(withURL: twitterURL) + } + } + } +} + diff --git a/trySwift/TwitterFollowTableViewCell.swift b/trySwift/TwitterFollowTableViewCell.swift index bf068ed..b8e2579 100644 --- a/trySwift/TwitterFollowTableViewCell.swift +++ b/trySwift/TwitterFollowTableViewCell.swift @@ -8,10 +8,6 @@ import UIKit -protocol TwitterFollowDelegate: class { - func followUser(_ username: String) -} - class TwitterFollowTableViewCell: UITableViewCell { @IBOutlet weak var followButton: UIButton! diff --git a/trySwift/UIViewControllerExtension.swift b/trySwift/UIViewControllerExtension.swift index 0de1acd..d4881e7 100644 --- a/trySwift/UIViewControllerExtension.swift +++ b/trySwift/UIViewControllerExtension.swift @@ -23,27 +23,6 @@ extension UIViewController: SFSafariViewControllerDelegate { } } -extension UIViewController: TwitterFollowDelegate { - - func followUser(_ username: String) { - var applicationOpened = false - let application = UIApplication.shared - for twitterURL in Twitter.urls(forUsername: username) { - if let url = URL(string: twitterURL) , application.canOpenURL(url) && !applicationOpened { - application.open(url, options: [String:Any](), completionHandler: nil) - applicationOpened = true - break - } - } - - if !applicationOpened { - if let twitterURL = URL(string: "https://twitter.com/\(username)") { - openSafariViewController(withURL: twitterURL) - } - } - } -} - extension UIViewController: MFMailComposeViewControllerDelegate { func sendMail(withConfiguration configuration: MailConfiguration) {