diff --git a/CriticalMaps.xcodeproj/project.pbxproj b/CriticalMaps.xcodeproj/project.pbxproj index f39d5ef91..62af5cb84 100644 --- a/CriticalMaps.xcodeproj/project.pbxproj +++ b/CriticalMaps.xcodeproj/project.pbxproj @@ -1035,7 +1035,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ $CONFIGURATION = \"Debug\" ]; then\n $SOURCE_ROOT/bin/license-plist --output-path ./Settings.bundle\nfi\n"; + shellScript = "if [ $CONFIGURATION = \"Debug\" ]; then\n $SOURCE_ROOT/bin/swiftformat .\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/CriticalMapsMocksForTests/MockNetworkDataProvider.swift b/CriticalMapsMocksForTests/MockNetworkDataProvider.swift index b0a597473..cd373e8a6 100644 --- a/CriticalMapsMocksForTests/MockNetworkDataProvider.swift +++ b/CriticalMapsMocksForTests/MockNetworkDataProvider.swift @@ -13,10 +13,10 @@ struct MockNetworkDataProvider: NetworkDataProvider { var data: Data? var response: URLResponse? var error: Error? - - func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) { + + func dataTask(with _: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) { completionHandler(data, response, error) } - + func invalidateAndCancel() {} } diff --git a/CriticalMapsMocksForTests/MockThemeController.swift b/CriticalMapsMocksForTests/MockThemeController.swift index 8c6ff3c82..713a86ec3 100644 --- a/CriticalMapsMocksForTests/MockThemeController.swift +++ b/CriticalMapsMocksForTests/MockThemeController.swift @@ -10,7 +10,7 @@ class MockThemeController: ThemeController { static let shared = MockThemeController() - + private init() { let store = MockThemeStore() super.init(store: store) diff --git a/CriticalMapsSnapshotTests/RulesDetailViewControllerSnapshotTests.swift b/CriticalMapsSnapshotTests/RulesDetailViewControllerSnapshotTests.swift index c5f845986..0081d715b 100644 --- a/CriticalMapsSnapshotTests/RulesDetailViewControllerSnapshotTests.swift +++ b/CriticalMapsSnapshotTests/RulesDetailViewControllerSnapshotTests.swift @@ -10,7 +10,6 @@ import XCTest class RulesDetailViewControllerSnapshotTests: XCTestCase { - func testGeneralAppearance() { // Given let viewController = RulesDetailViewController(rule: Rule.cork) diff --git a/CriticalMapsSnapshotTests/TweetTableViewCellSnapshotTests.swift b/CriticalMapsSnapshotTests/TweetTableViewCellSnapshotTests.swift index 5661de24f..e0deaffb7 100644 --- a/CriticalMapsSnapshotTests/TweetTableViewCellSnapshotTests.swift +++ b/CriticalMapsSnapshotTests/TweetTableViewCellSnapshotTests.swift @@ -12,11 +12,11 @@ import XCTest class TweetTableViewCellSnapshotTests: XCTestCase { private let size = CGSize(width: 320, height: 100) // use constant date in the past - private let tweetDate = Date(timeIntervalSince1970: 1530230956) - + private let tweetDate = Date(timeIntervalSince1970: 1_530_230_956) + override func setUp() { // use constant date in the past - FormatDisplay.currentDate = Date(timeIntervalSince1970: 1530240956) + FormatDisplay.currentDate = Date(timeIntervalSince1970: 1_530_240_956) } func testTweetTableViewCell() { @@ -28,10 +28,10 @@ class TweetTableViewCellSnapshotTests: XCTestCase { profile_image_url_https: "haa"), id_str: "test_id") let cell = TweetTableViewCell.fromNib() - + // when cell.setup(for: tweet) - + // then assertViewSnapshot(matching: cell, with: size) } diff --git a/CriticalMapsSnapshotTests/XCTestCase+SnapshotTests.swift b/CriticalMapsSnapshotTests/XCTestCase+SnapshotTests.swift index b02b5f9bb..29dcffd36 100644 --- a/CriticalMapsSnapshotTests/XCTestCase+SnapshotTests.swift +++ b/CriticalMapsSnapshotTests/XCTestCase+SnapshotTests.swift @@ -12,14 +12,14 @@ import XCTest extension XCTestCase { func assertViewSnapshot(for themes: [Theme] = [.light, .dark], - matching value: UIView, - with size: CGSize? = nil, - file: StaticString = #file, - testName: String = #function, - line: UInt = #line) { + matching value: UIView, + with size: CGSize? = nil, + file: StaticString = #file, + testName: String = #function, + line: UInt = #line) { themes.forEach { theme in MockThemeController.shared.changeTheme(to: theme) - MockThemeController.shared.applyTheme() + MockThemeController.shared.applyTheme() assertSnapshot(matching: value, as: .image(size: size), named: theme.displayName, diff --git a/CriticalMapsUITests/CriticalMapsUITests.swift b/CriticalMapsUITests/CriticalMapsUITests.swift index e5e8b6b07..b49c1e949 100644 --- a/CriticalMapsUITests/CriticalMapsUITests.swift +++ b/CriticalMapsUITests/CriticalMapsUITests.swift @@ -9,14 +9,13 @@ import XCTest class CriticalMapsUITests: XCTestCase { - override func setUp() { super.setUp() continueAfterFailure = false let app = XCUIApplication() app.launchArguments += [ - "SKIP_ANIMATIONS" + "SKIP_ANIMATIONS", ] setupSnapshot(app, waitForAnimations: false) app.launch() diff --git a/CriticalMapsUITests/SnapshotHelper.swift b/CriticalMapsUITests/SnapshotHelper.swift index aaa2a9a92..619b7d048 100644 --- a/CriticalMapsUITests/SnapshotHelper.swift +++ b/CriticalMapsUITests/SnapshotHelper.swift @@ -52,7 +52,7 @@ enum SnapshotError: Error, CustomDebugStringConvertible { return "Couldn't find Snapshot configuration files - can't detect `Users` dir" case .cannotFindSimulatorHomeDirectory: return "Couldn't find simulator home location. Please, check SIMULATOR_HOST_HOME env variable." - case .cannotAccessSimulatorHomeDirectory(let simulatorHostHome): + case let .cannotAccessSimulatorHomeDirectory(simulatorHostHome): return "Can't prepare environment. Simulator home location is inaccessible. Does \(simulatorHostHome) exist?" case .cannotRunOnPhysicalDevice: return "Can't use Snapshot on a physical device." @@ -70,7 +70,6 @@ open class Snapshot: NSObject { } open class func setupSnapshot(_ app: XCUIApplication, waitForAnimations: Bool = true) { - Snapshot.app = app Snapshot.waitForAnimations = waitForAnimations @@ -80,7 +79,7 @@ open class Snapshot: NSObject { setLanguage(app) setLocale(app) setLaunchArguments(app) - } catch let error { + } catch { NSLog(error.localizedDescription) } } @@ -117,7 +116,7 @@ open class Snapshot: NSObject { NSLog("Couldn't detect/set locale...") } - if locale.isEmpty && !deviceLanguage.isEmpty { + if locale.isEmpty, !deviceLanguage.isEmpty { locale = Locale(identifier: deviceLanguage).identifier } @@ -184,7 +183,7 @@ open class Snapshot: NSObject { let path = screenshotsDir.appendingPathComponent("\(simulator)-\(name).png") try screenshot.pngRepresentation.write(to: path) - } catch let error { + } catch { NSLog("Problem writing screenshot: \(name) to \(screenshotsDir)/\(simulator)-\(name).png") NSLog(error.localizedDescription) } @@ -266,13 +265,13 @@ private extension XCUIElementAttributes { private extension XCUIElementQuery { var networkLoadingIndicators: XCUIElementQuery { - let isNetworkLoadingIndicator = NSPredicate { (evaluatedObject, _) in + let isNetworkLoadingIndicator = NSPredicate { evaluatedObject, _ in guard let element = evaluatedObject as? XCUIElementAttributes else { return false } return element.isNetworkLoadingIndicator } - return self.containing(isNetworkLoadingIndicator) + return containing(isNetworkLoadingIndicator) } var deviceStatusBars: XCUIElementQuery { @@ -282,19 +281,19 @@ private extension XCUIElementQuery { let deviceWidth = app.windows.firstMatch.frame.width - let isStatusBar = NSPredicate { (evaluatedObject, _) in + let isStatusBar = NSPredicate { evaluatedObject, _ in guard let element = evaluatedObject as? XCUIElementAttributes else { return false } return element.isStatusBar(deviceWidth) } - return self.containing(isStatusBar) + return containing(isStatusBar) } } private extension CGFloat { func isBetween(_ numberA: CGFloat, and numberB: CGFloat) -> Bool { - return numberA...numberB ~= self + return numberA ... numberB ~= self } } diff --git a/CriticalMass/AnnotationController.swift b/CriticalMass/AnnotationController.swift index 9ab4da60a..422d13c88 100644 --- a/CriticalMass/AnnotationController.swift +++ b/CriticalMass/AnnotationController.swift @@ -17,6 +17,6 @@ class AnnotationController { self.mapView = mapView setup() } - + open func setup() {} } diff --git a/CriticalMass/AppController.swift b/CriticalMass/AppController.swift index 0a1038a4b..7ff1f0d57 100644 --- a/CriticalMass/AppController.swift +++ b/CriticalMass/AppController.swift @@ -24,7 +24,7 @@ class AppController { let networkDataProvider: NetworkDataProvider if simulationModeEnabled { - networkDataProvider = SimulationNetworkDataProvider(realNetworkDataProvider: session) + networkDataProvider = SimulationNetworkDataProvider(realNetworkDataProvider: session) } else { networkDataProvider = session } @@ -44,7 +44,7 @@ class AppController { private lazy var twitterManager: TwitterManager = { TwitterManager(networkLayer: networkOperator, request: TwitterRequest()) }() - + lazy var rootViewController: UIViewController = { let rootViewController = MapViewController(themeController: self.themeController) let navigationOverlay = NavigationOverlayViewController(navigationItems: [ @@ -75,7 +75,7 @@ class AppController { RatingHelper().onLaunch() } } - + public func onWillEnterForeground() { if #available(iOS 10.3, *) { RatingHelper().onEnterForeground() @@ -85,7 +85,7 @@ class AppController { public func enableSimulationMode() { simulationModeEnabled = true } - + private func getRulesViewController() -> RulesViewController { return RulesViewController() } diff --git a/CriticalMass/AppDelegate.swift b/CriticalMass/AppDelegate.swift index 31cdd7de2..b4de9fda1 100644 --- a/CriticalMass/AppDelegate.swift +++ b/CriticalMass/AppDelegate.swift @@ -13,7 +13,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { lazy var appController = AppController() func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Test Configuration if let shouldEarlyExitForTests = configureAppForTests() { return shouldEarlyExitForTests @@ -41,7 +40,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { if ProcessInfo.processInfo.arguments.contains("SKIP_ANIMATIONS") { UIView.setAnimationsEnabled(false) } - + if ProcessInfo.processInfo.arguments.contains("SIMULATION_MODE") { appController.enableSimulationMode() } diff --git a/CriticalMass/CMLogoActivityView.swift b/CriticalMass/CMLogoActivityView.swift index dedd833d6..2bcbbdff3 100644 --- a/CriticalMass/CMLogoActivityView.swift +++ b/CriticalMass/CMLogoActivityView.swift @@ -12,7 +12,7 @@ import UIKit @IBDesignable public class CMLogoActivityView: UIView, IBConstructable { private var angle: CGFloat = 0 private lazy var displayLink: CADisplayLink = { - return CADisplayLink(target: self, selector: #selector(updateViewParameter)) + CADisplayLink(target: self, selector: #selector(updateViewParameter)) }() public override func draw(_: CGRect) { @@ -105,7 +105,7 @@ public struct CriticalMapsLoader { //// gear context.saveGState() context.translateBy(x: 50, y: 50) - context.rotate(by: -angle * CGFloat.pi/180) + context.rotate(by: -angle * CGFloat.pi / 180) //// Bezier 4 Drawing context.saveGState() diff --git a/CriticalMass/ChatInputView.swift b/CriticalMass/ChatInputView.swift index 79521817c..26f240367 100644 --- a/CriticalMass/ChatInputView.swift +++ b/CriticalMass/ChatInputView.swift @@ -136,6 +136,6 @@ class ChatInputView: UIView { private extension String { var canBeSent: Bool { - !self.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + !trimmingCharacters(in: .whitespacesAndNewlines).isEmpty } } diff --git a/CriticalMass/ChatManager.swift b/CriticalMass/ChatManager.swift index a472055da..06ba18bbd 100644 --- a/CriticalMass/ChatManager.swift +++ b/CriticalMass/ChatManager.swift @@ -5,8 +5,8 @@ // Created by Leonard Thomas on 1/26/19. // -import Foundation import Crypto +import Foundation class ChatManager { private var cachedMessages: [ChatMessage]? diff --git a/CriticalMass/ChatViewController.swift b/CriticalMass/ChatViewController.swift index 91f6a255c..9ce9d7dc4 100644 --- a/CriticalMass/ChatViewController.swift +++ b/CriticalMass/ChatViewController.swift @@ -11,6 +11,7 @@ class ChatViewController: UIViewController, ChatInputDelegate { private enum Constants { static let chatInputHeight: CGFloat = 64 } + private let chatInput = ChatInputView(frame: .zero) private let messagesTableViewController = MessagesTableViewController(style: .plain) private let chatManager: ChatManager diff --git a/CriticalMass/Constants.swift b/CriticalMass/Constants.swift index ba79549ef..3ab48418b 100644 --- a/CriticalMass/Constants.swift +++ b/CriticalMass/Constants.swift @@ -7,7 +7,6 @@ import Foundation - public enum Constants { static let apiEndpoint = URL(string: "https://api.criticalmaps.net/")! static let criticalMapsiOSGitHubEndpoint = URL(string: "https://github.com/criticalmaps/criticalmaps-ios")! diff --git a/CriticalMass/ErrorStateViewController.swift b/CriticalMass/ErrorStateViewController.swift index 70e3aa4cd..dda6da900 100644 --- a/CriticalMass/ErrorStateViewController.swift +++ b/CriticalMass/ErrorStateViewController.swift @@ -11,9 +11,9 @@ import UIKit typealias ReloadHandler = () -> Void class ErrorStateViewController: UIViewController, IBConstructable { - @IBOutlet private weak var errorTitle: UILabel! - @IBOutlet private weak var errorMessage: UILabel! - @IBOutlet private weak var retryButton: UIButton! + @IBOutlet private var errorTitle: UILabel! + @IBOutlet private var errorMessage: UILabel! + @IBOutlet private var retryButton: UIButton! var reloadHandler: ReloadHandler? var errorStateModel: ErrorStateModel! @@ -28,7 +28,7 @@ class ErrorStateViewController: UIViewController, IBConstructable { errorMessage.text = errorStateModel.errorMessage } - @IBAction func reload(_ sender: Any) { + @IBAction func reload(_: Any) { reloadHandler?() } } diff --git a/CriticalMass/FormatDisplay.swift b/CriticalMass/FormatDisplay.swift index 83cb04de5..4b8acd194 100644 --- a/CriticalMass/FormatDisplay.swift +++ b/CriticalMass/FormatDisplay.swift @@ -31,7 +31,7 @@ private extension DateComponents { enum FormatDisplay { // inject current date to be able to keep the same time difference between tweet date and current date static var currentDate = Date() - + static func dateString(for tweet: Tweet) -> String? { let components = Calendar.current.dateComponents([.minute, .hour, .day, .month], from: tweet.created_at, to: currentDate).dateomponentFromBiggestComponent let formatter = DateComponentsFormatter() diff --git a/CriticalMass/IDProvider.swift b/CriticalMass/IDProvider.swift index ef387dad3..b802bc6f4 100644 --- a/CriticalMass/IDProvider.swift +++ b/CriticalMass/IDProvider.swift @@ -10,6 +10,6 @@ import Foundation public protocol IDProvider { var id: String { get } var token: String { get } - + static func hash(id: String, currentDate: Date) -> String } diff --git a/CriticalMass/IDStore.swift b/CriticalMass/IDStore.swift index 30fc06f86..a760bfb26 100644 --- a/CriticalMass/IDStore.swift +++ b/CriticalMass/IDStore.swift @@ -5,14 +5,13 @@ // Created by Leonard Thomas on 5/2/19. // -import UIKit import Crypto +import UIKit public class IDStore: IDProvider { - public let id: String public let token: String - + public init(currentDate: Date = Date()) { let deviceID = UIDevice.current.identifierForVendor?.uuidString ?? UUID().uuidString @@ -20,11 +19,11 @@ public class IDStore: IDProvider { token = deviceID } - static public func hash(id: String, currentDate: Date = Date()) -> String { + public static func hash(id: String, currentDate: Date = Date()) -> String { let format = DateFormatter() format.dateFormat = "yyyy-MM-dd" let dateString = format.string(from: currentDate) - + return String(id + dateString).md5! } } diff --git a/CriticalMass/KeychainHelper.swift b/CriticalMass/KeychainHelper.swift index d125ab99e..ea35fbde2 100644 --- a/CriticalMass/KeychainHelper.swift +++ b/CriticalMass/KeychainHelper.swift @@ -14,35 +14,35 @@ public class KeychainHelper { case storeKeyFailed case deletionFailed } - + public class func save(keyData: Data, with keyReference: String) throws { let addquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: keyReference, kSecValueData as String: keyData] - + SecItemDelete(addquery as CFDictionary) let status = SecItemAdd(addquery as CFDictionary, nil) guard status == errSecSuccess else { throw KeychainError.storeKeyFailed } } - + public class func load(with keyReference: String) throws -> Data { let getquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: keyReference, - kSecReturnData as String : kCFBooleanTrue!, - kSecMatchLimit as String : kSecMatchLimitOne] + kSecReturnData as String: kCFBooleanTrue!, + kSecMatchLimit as String: kSecMatchLimitOne] var item: CFTypeRef? let status = SecItemCopyMatching(getquery as CFDictionary, &item) guard status == errSecSuccess else { throw KeychainError.cantFindMatchingKey } - + return item as! Data } - + public class func delete(with keyReference: String) throws { let deleteQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: keyReference] - + let status = SecItemDelete(deleteQuery as CFDictionary) guard status == errSecSuccess || status == errSecItemNotFound else { throw KeychainError.deletionFailed diff --git a/CriticalMass/LinkResponsiveTextView.swift b/CriticalMass/LinkResponsiveTextView.swift index fb9ee95e5..d9f907854 100644 --- a/CriticalMass/LinkResponsiveTextView.swift +++ b/CriticalMass/LinkResponsiveTextView.swift @@ -9,41 +9,40 @@ import UIKit class LinkResponsiveTextView: UITextView { - override init(frame: CGRect, textContainer: NSTextContainer?) { super.init(frame: frame, textContainer: textContainer) - self.initialize() + initialize() } - + required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - self.initialize() + initialize() } - + private func initialize() { - self.delaysContentTouches = false + delaysContentTouches = false // required for tap to pass through on to superview & for links to work - self.isScrollEnabled = false - self.isEditable = false - self.isUserInteractionEnabled = true - self.isSelectable = true + isScrollEnabled = false + isEditable = false + isUserInteractionEnabled = true + isSelectable = true } - - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + + override func hitTest(_ point: CGPoint, with _: UIEvent?) -> UIView? { // location of the tap var location = point - location.x -= self.textContainerInset.left - location.y -= self.textContainerInset.top - + location.x -= textContainerInset.left + location.y -= textContainerInset.top + // find the character that's been tapped - let characterIndex = self.layoutManager.characterIndex(for: location, in: self.textContainer, fractionOfDistanceBetweenInsertionPoints: nil) - if characterIndex < self.textStorage.length { + let characterIndex = layoutManager.characterIndex(for: location, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil) + if characterIndex < textStorage.length { // if the character is a link, handle the tap as UITextView normally would - if (self.textStorage.attribute(NSAttributedString.Key.link, at: characterIndex, effectiveRange: nil) != nil) { + if textStorage.attribute(NSAttributedString.Key.link, at: characterIndex, effectiveRange: nil) != nil { return self } } - + // otherwise return nil so the tap goes on to the next receiver return nil } diff --git a/CriticalMass/Logger.swift b/CriticalMass/Logger.swift index 62281f5df..8e3760c4f 100644 --- a/CriticalMass/Logger.swift +++ b/CriticalMass/Logger.swift @@ -14,7 +14,7 @@ extension OSLog { @available(OSX 10.12, *) static let viewManagement = OSLog(subsystem: subsystem, category: "viewManagement") - + @available(OSX 10.12, *) static let map = OSLog(subsystem: subsystem, category: "Map") } diff --git a/CriticalMass/MKMapView+Register.swift b/CriticalMass/MKMapView+Register.swift index 5f5989d56..7fa6fc750 100644 --- a/CriticalMass/MKMapView+Register.swift +++ b/CriticalMass/MKMapView+Register.swift @@ -21,7 +21,7 @@ extension MKMapView { } } - func dequeueReusableAnnotationView(ofType annotationType: T.Type, for indexPath: IndexPath? = nil, with annotation: MKAnnotation) -> T { + func dequeueReusableAnnotationView(ofType annotationType: T.Type, for _: IndexPath? = nil, with annotation: MKAnnotation) -> T { let annotationView: T if #available(iOS 11.0, *) { annotationView = dequeueReusableAnnotationView(withIdentifier: annotationType.reuseIdentifier, for: annotation) as! T diff --git a/CriticalMass/MapViewController.swift b/CriticalMass/MapViewController.swift index eaaa97476..29adb8f6a 100644 --- a/CriticalMass/MapViewController.swift +++ b/CriticalMass/MapViewController.swift @@ -11,58 +11,58 @@ import UIKit class MapViewController: UIViewController { private let themeController: ThemeController! private var tileRenderer: MKTileOverlayRenderer? - + init(themeController: ThemeController) { self.themeController = themeController super.init(nibName: nil, bundle: nil) } - + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + // MARK: Properties - + private lazy var annotationController: [AnnotationController] = { [BikeAnnotationController(mapView: self.mapView)] }() - + private let nightThemeOverlay = DarkModeMapOverlay() public lazy var followMeButton: UserTrackingButton = { let button = UserTrackingButton(mapView: mapView) return button }() - + public var bottomContentOffset: CGFloat = 0 { didSet { mapView.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: bottomContentOffset, right: 0) } } - + private var mapView = MKMapView(frame: .zero) - + private let gpsDisabledOverlayView: BlurryOverlayView = { let view = BlurryOverlayView.fromNib() view.translatesAutoresizingMaskIntoConstraints = false return view }() - + override func viewDidLoad() { super.viewDidLoad() - + title = String.mapTitle configureNotifications() configureTileRenderer() configureMapView() condfigureGPSDisabledOverlayView() - + annotationController - .map{ $0.annotationViewType } + .map { $0.annotationViewType } .forEach(mapView.register) - + setNeedsStatusBarAppearanceUpdate() } - + private func configureTileRenderer() { guard themeController.currentTheme == .dark else { if #available(iOS 13.0, *) { @@ -70,14 +70,14 @@ class MapViewController: UIViewController { } return } - + if #available(iOS 13.0, *) { overrideUserInterfaceStyle = .dark } else { addTileRenderer() } } - + private func condfigureGPSDisabledOverlayView() { let gpsDisabledOverlayView = self.gpsDisabledOverlayView gpsDisabledOverlayView.set(title: String.mapLayerInfoTitle, message: String.mapLayerInfo) @@ -87,16 +87,16 @@ class MapViewController: UIViewController { gpsDisabledOverlayView.heightAnchor.constraint(equalTo: view.heightAnchor), gpsDisabledOverlayView.widthAnchor.constraint(equalTo: view.widthAnchor), ]) - + updateGPSDisabledOverlayVisibility() } - + private func configureNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(didReceiveInitialLocation(notification:)), name: Notification.initialGpsDataReceived, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(updateGPSDisabledOverlayVisibility), name: Notification.observationModeChanged, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: Notification.themeDidChange, object: nil) } - + private func configureMapView() { view.addSubview(mapView) mapView.addLayoutsSameSizeAndOrigin(in: view) @@ -104,23 +104,23 @@ class MapViewController: UIViewController { mapView.delegate = self mapView.showsUserLocation = true } - + // GPS Disabled Overlay - + @objc func didTapGPSDisabledOverlayButton() { UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!) } - + @objc func updateGPSDisabledOverlayVisibility() { gpsDisabledOverlayView.isHidden = LocationManager.accessPermission != .denied } - + // MARK: Notifications - + override var preferredStatusBarStyle: UIStatusBarStyle { return themeController.currentTheme.style.statusBarStyle } - + @objc private func themeDidChange() { let theme = themeController.currentTheme guard theme == .dark else { @@ -133,17 +133,17 @@ class MapViewController: UIViewController { } configureTileRenderer() } - + private func removeTileRenderer() { tileRenderer = nil mapView.removeOverlay(nightThemeOverlay) } - + private func addTileRenderer() { tileRenderer = MKTileOverlayRenderer(tileOverlay: nightThemeOverlay) mapView.addOverlay(nightThemeOverlay, level: .aboveRoads) } - + @objc func didReceiveInitialLocation(notification: Notification) { guard let location = notification.object as? Location else { return } let region = MKCoordinateRegion(center: CLLocationCoordinate2D(location), latitudinalMeters: 10000, longitudinalMeters: 10000) @@ -154,23 +154,23 @@ class MapViewController: UIViewController { extension MapViewController: MKMapViewDelegate { // MARK: MKMapViewDelegate - + func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { guard annotation is MKUserLocation == false else { return nil } - + guard let matchingController = annotationController.first(where: { type(of: annotation) == $0.annotationType }) else { return nil } - + return mapView.dequeueReusableAnnotationView(ofType: matchingController.annotationViewType, with: annotation) } - + func mapView(_: MKMapView, didChange mode: MKUserTrackingMode, animated _: Bool) { followMeButton.currentMode = UserTrackingButton.Mode(mode) } - + func mapView(_: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { guard let renderer = self.tileRenderer else { return MKOverlayRenderer(overlay: overlay) diff --git a/CriticalMass/MessagesTableViewController.swift b/CriticalMass/MessagesTableViewController.swift index 97dc93368..a4bfa8006 100644 --- a/CriticalMass/MessagesTableViewController.swift +++ b/CriticalMass/MessagesTableViewController.swift @@ -31,7 +31,7 @@ class MessagesTableViewController: UITab updateNoMessageCountIfNeeded() } } - + var selectMessageTrigger: ((T.Model) -> Void)? override func viewDidLoad() { @@ -84,9 +84,9 @@ class MessagesTableViewController: UITab cell.setup(for: messages[indexPath.row]) return cell } - + // MARK: - Table view delegate - + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) selectMessageTrigger?(messages[indexPath.row]) diff --git a/CriticalMass/NetworkActivityIndicatorHelper.swift b/CriticalMass/NetworkActivityIndicatorHelper.swift index 0c7fed24b..e1f6bdac7 100644 --- a/CriticalMass/NetworkActivityIndicatorHelper.swift +++ b/CriticalMass/NetworkActivityIndicatorHelper.swift @@ -6,7 +6,7 @@ // #if canImport(UIKit) -import UIKit + import UIKit #endif class NetworkActivityIndicatorHelper { diff --git a/CriticalMass/NetworkOperator.swift b/CriticalMass/NetworkOperator.swift index 94605499e..8fcf53e5c 100644 --- a/CriticalMass/NetworkOperator.swift +++ b/CriticalMass/NetworkOperator.swift @@ -16,7 +16,7 @@ public struct NetworkOperator: NetworkLayer { self.dataProvider = dataProvider self.networkIndicatorHelper = networkIndicatorHelper } - + public init(dataProvider: NetworkDataProvider) { self.dataProvider = dataProvider } @@ -30,8 +30,8 @@ public struct NetworkOperator: NetworkLayer { urlRequest.httpBody = bodyData dataTaskHandler(request: request, urlRequest: urlRequest, completion: completion) } - - private func dataTaskHandler(request: T,urlRequest: URLRequest, completion: @escaping ResultCallback) { + + private func dataTaskHandler(request: T, urlRequest: URLRequest, completion: @escaping ResultCallback) { dataTask(with: urlRequest) { result in switch result { case let .failure(error): diff --git a/CriticalMass/RequestManager.swift b/CriticalMass/RequestManager.swift index f68e88369..cb205692d 100644 --- a/CriticalMass/RequestManager.swift +++ b/CriticalMass/RequestManager.swift @@ -99,10 +99,10 @@ public class RequestManager { func send(messages: [SendChatMessage], completion: @escaping ResultCallback<[String: ChatMessage]>) { #if canImport(UIKit) - let backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask { - completion(.failure(NetworkError.unknownError(message: "Send message: backgroundTask failed"))) - self.networkLayer.cancelActiveRequestsIfNeeded() - } + let backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask { + completion(.failure(NetworkError.unknownError(message: "Send message: backgroundTask failed"))) + self.networkLayer.cancelActiveRequestsIfNeeded() + } #endif let body = SendMessagePostBody(device: idProvider.id, messages: messages) guard let bodyData = try? body.encoded() else { @@ -114,9 +114,9 @@ public class RequestManager { guard let self = self else { return } self.defaultCompletion(for: result) onMain { - #if canImport(UIKit) - UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier) - + #if canImport(UIKit) + UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier) + #endif switch result { case let .success(messages): diff --git a/CriticalMass/RulesDetailViewController.swift b/CriticalMass/RulesDetailViewController.swift index ec9ff9e6e..cc2a38f14 100644 --- a/CriticalMass/RulesDetailViewController.swift +++ b/CriticalMass/RulesDetailViewController.swift @@ -53,28 +53,29 @@ class RulesDetailViewController: UIViewController { toItem: ruleImageView, attribute: .width, multiplier: aspectRatio, - constant: 0) + constant: 0 + ) }() init(rule: Rule) { self.rule = rule super.init(nibName: nil, bundle: nil) } - + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() - + title = rule.title if #available(iOS 11.0, *) { navigationItem.largeTitleDisplayMode = .never } configureConstraints() } - + private func configureConstraints() { view.addSubview(scrollView) scrollView.translatesAutoresizingMaskIntoConstraints = false @@ -84,7 +85,7 @@ class RulesDetailViewController: UIViewController { scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor), scrollView.topAnchor.constraint(equalTo: view.topAnchor), scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - scrollView.bottomAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor) + scrollView.bottomAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor), ]) ruleImageView.translatesAutoresizingMaskIntoConstraints = false @@ -99,7 +100,7 @@ class RulesDetailViewController: UIViewController { ruleStack.leadingAnchor.constraint(greaterThanOrEqualTo: scrollView.leadingAnchor, constant: spacing), ruleStack.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: spacing), scrollView.bottomAnchor.constraint(greaterThanOrEqualTo: ruleStack.bottomAnchor, constant: spacing), - ruleStack.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: spacing) + ruleStack.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: spacing), ]) } diff --git a/CriticalMass/SimulationNetworkDataProvider.swift b/CriticalMass/SimulationNetworkDataProvider.swift index c5bef108c..7cc3718a7 100644 --- a/CriticalMass/SimulationNetworkDataProvider.swift +++ b/CriticalMass/SimulationNetworkDataProvider.swift @@ -11,20 +11,20 @@ import UIKit class SimulationNetworkDataProvider: NetworkDataProvider { private var currentFrame = 0 private var realNetworkDataProvider: NetworkDataProvider - + init(realNetworkDataProvider: NetworkDataProvider) { self.realNetworkDataProvider = realNetworkDataProvider } - + func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) { guard let url = request.url, url == Constants.apiEndpoint else { - // only the base API is supported - // We are falling back to the real NetworkDataProvider - realNetworkDataProvider.dataTask(with: request, completionHandler: completionHandler) - return + // only the base API is supported + // We are falling back to the real NetworkDataProvider + realNetworkDataProvider.dataTask(with: request, completionHandler: completionHandler) + return } - + if let asset = NSDataAsset(name: "snapshot_\(currentFrame)") { currentFrame += 1 let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: nil, headerFields: nil) @@ -34,7 +34,7 @@ class SimulationNetworkDataProvider: NetworkDataProvider { completionHandler(nil, nil, nil) } } - + func invalidateAndCancel() { realNetworkDataProvider.invalidateAndCancel() } diff --git a/CriticalMass/TwitterViewController.swift b/CriticalMass/TwitterViewController.swift index af8c9fe68..f6798e30c 100644 --- a/CriticalMass/TwitterViewController.swift +++ b/CriticalMass/TwitterViewController.swift @@ -72,8 +72,8 @@ private extension TwitterViewController { if let webURL = tweet.webURL, UIApplication.shared.canOpenURL(webURL) { UIApplication.shared.open(webURL, options: [:], completionHandler: nil) } else { - //Do nothing - } + // Do nothing + } } } diff --git a/CriticalMass/UITableViewHeaderFooterView+BackgroundColor.swift b/CriticalMass/UITableViewHeaderFooterView+BackgroundColor.swift index c1ca00548..eb7464fa5 100644 --- a/CriticalMass/UITableViewHeaderFooterView+BackgroundColor.swift +++ b/CriticalMass/UITableViewHeaderFooterView+BackgroundColor.swift @@ -17,7 +17,7 @@ extension UITableViewHeaderFooterView { customBackgroundView.backgroundColor = newValue } } - + private var customBackgroundView: UIView { guard let backgroundView = self.backgroundView else { let customView = UIView() diff --git a/CriticalMass/UIView+Autolayout.swift b/CriticalMass/UIView+Autolayout.swift index 5021d6881..78e565d46 100644 --- a/CriticalMass/UIView+Autolayout.swift +++ b/CriticalMass/UIView+Autolayout.swift @@ -14,23 +14,23 @@ extension UIView { view.addConstraints([ centerXAnchor.constraint(equalTo: view.centerXAnchor), - centerYAnchor.constraint(equalTo: view.centerYAnchor) + centerYAnchor.constraint(equalTo: view.centerYAnchor), ]) - + addConstraints([ heightAnchor.constraint(equalToConstant: size.height), - widthAnchor.constraint(equalToConstant: size.width) + widthAnchor.constraint(equalToConstant: size.width), ]) } - + func addLayoutsSameSizeAndOrigin(in view: UIView) { translatesAutoresizingMaskIntoConstraints = false - + view.addConstraints([ heightAnchor.constraint(equalTo: view.heightAnchor), widthAnchor.constraint(equalTo: view.widthAnchor), leadingAnchor.constraint(equalTo: view.leadingAnchor), - topAnchor.constraint(equalTo: view.topAnchor) + topAnchor.constraint(equalTo: view.topAnchor), ]) } } diff --git a/CriticalMassTests/KeychainHelperTests.swift b/CriticalMassTests/KeychainHelperTests.swift index ee5cc968b..de08a8b16 100644 --- a/CriticalMassTests/KeychainHelperTests.swift +++ b/CriticalMassTests/KeychainHelperTests.swift @@ -12,7 +12,7 @@ import XCTest class KeychainHelperTests: XCTestCase { var keychainReference = "SomeKey" var testData = "RandomKey".data(using: .utf8)! - + override func tearDown() { try? KeychainHelper.delete(with: keychainReference) } diff --git a/CriticalMassTests/NetworkOperatorTests.swift b/CriticalMassTests/NetworkOperatorTests.swift index 17cb07c50..567a06be9 100644 --- a/CriticalMassTests/NetworkOperatorTests.swift +++ b/CriticalMassTests/NetworkOperatorTests.swift @@ -10,66 +10,64 @@ import XCTest class NetworkOperatorTests: XCTestCase { - struct ResponseData: Codable, Equatable { var content: String } - + struct TestRequest: APIRequestDefining { var endpoint: Endpoint = .default var httpMethod: HTTPMethod = .get - var headers: HTTPHeaders? = nil + var headers: HTTPHeaders? typealias ResponseDataType = ResponseData } - + func testNoData() { XCTAssertRequest(dataProvider: mockDataProvider(statusCode: 201), expectedResult: .failure(.noData(nil))) } - + func testInvalidStatusCode() { XCTAssertRequest(dataProvider: mockDataProvider(data: "foo", statusCode: 404), expectedResult: .failure(.invalidResponse)) } - + func testDecodingError() { - enum FooError: Error { + enum FooError: Error { case f } - + XCTAssertRequest(dataProvider: mockDataProvider(rawData: "foo".data(using: .utf8), statusCode: 201), expectedResult: .failure(.decodingError(FooError.f))) } - + func testSuccess() { - XCTAssertRequest(dataProvider: mockDataProvider(data: "foo", statusCode: 201), expectedResult: .success(ResponseData(content:"foo"))) + XCTAssertRequest(dataProvider: mockDataProvider(data: "foo", statusCode: 201), expectedResult: .success(ResponseData(content: "foo"))) } - - private func XCTAssertRequest(dataProvider: MockNetworkDataProvider , expectedResult: Result, line: UInt = #line) { - + + private func XCTAssertRequest(dataProvider: MockNetworkDataProvider, expectedResult: Result, line: UInt = #line) { let exp = expectation(description: "wait for response") exp.expectedFulfillmentCount = 2 - + let networkOperator = NetworkOperator(networkIndicatorHelper: NetworkActivityIndicatorHelper(), dataProvider: dataProvider) - + let resultCallback: ResultCallback = { result in switch (result, expectedResult) { - case (.failure(let lhsError), .failure(let rhsError)): + case let (.failure(lhsError), .failure(rhsError)): XCTAssert(lhsError == rhsError, line: line) - case (.success(let lhsResponse), .success(let rhsResponse)): + case let (.success(lhsResponse), .success(rhsResponse)): XCTAssert(lhsResponse == rhsResponse, line: line) default: XCTAssert(false, line: line) } exp.fulfill() } - + // GET networkOperator.get(request: TestRequest(), completion: resultCallback) - + // Post networkOperator.post(request: TestRequest(), bodyData: "Foo".data(using: .utf8)!, completion: resultCallback) - + wait(for: [exp], timeout: 1) } - + private func mockDataProvider(data: String? = nil, rawData: Data? = nil, statusCode: Int = 200) -> MockNetworkDataProvider { let responseData: Data? = data != nil ? try! ResponseData(content: data!).encoded() : nil return MockNetworkDataProvider(data: responseData ?? rawData, diff --git a/CriticalMassTests/TestHelper.swift b/CriticalMassTests/TestHelper.swift index 8fb9dc93b..3e1b91e2a 100644 --- a/CriticalMassTests/TestHelper.swift +++ b/CriticalMassTests/TestHelper.swift @@ -67,8 +67,8 @@ class MockIDProvider: IDProvider { return UUID().uuidString } } - - static func hash(id: String, currentDate: Date) -> String { + + static func hash(id: String, currentDate _: Date) -> String { return id } } diff --git a/CriticalMassTests/TwitterManagerTests.swift b/CriticalMassTests/TwitterManagerTests.swift index 73cbd9222..79085e88c 100644 --- a/CriticalMassTests/TwitterManagerTests.swift +++ b/CriticalMassTests/TwitterManagerTests.swift @@ -154,7 +154,7 @@ private extension Tweet { enum TestData { static let fakeTweets: [Tweet] = [ Tweet(text: "Hello World", created_at: Date(), user: TwitterUser(name: "Test", screen_name: "Foo", profile_image_url_https: "haa"), id_str: "12345"), - Tweet(text: "Test Test", created_at: Date(), user: TwitterUser(name: "Hello World", screen_name: "Bar", profile_image_url_https: "differentURL"), id_str: "67890") + Tweet(text: "Test Test", created_at: Date(), user: TwitterUser(name: "Hello World", screen_name: "Bar", profile_image_url_https: "differentURL"), id_str: "67890"), ] } } diff --git a/Package.swift b/Package.swift index 6d35dd91f..02702d904 100644 --- a/Package.swift +++ b/Package.swift @@ -9,7 +9,8 @@ let package = Package( // Products define the executables and libraries produced by a package, and make them visible to other packages. .library( name: "CriticalMapsKit", - targets: ["CriticalMapsKit"]), + targets: ["CriticalMapsKit"] + ), ], dependencies: [ // Dependencies declare other packages that this package depends on. @@ -44,6 +45,7 @@ let package = Package( "PostChatMessagesRequest.swift", "PostLocationRequest.swift", "RequestManager.swift", - "SendChatMessage.swift"]) + "SendChatMessage.swift"] + ), ] )