From cc911bfec81f5ef4b48a92f28a855b440a7c80db Mon Sep 17 00:00:00 2001 From: Almas Sapargali Date: Wed, 21 Sep 2016 15:54:53 +0600 Subject: [PATCH] Swift 3 on lib --- LocationPicker.xcodeproj/project.pbxproj | 12 +- .../xcschemes/LocationPicker.xcscheme | 2 +- LocationPicker/Location.swift | 4 +- .../LocationPickerViewController.swift | 105 +++++++++--------- .../LocationSearchResultsViewController.swift | 18 +-- LocationPicker/SearchHistoryManager.swift | 40 ++++--- 6 files changed, 93 insertions(+), 88 deletions(-) diff --git a/LocationPicker.xcodeproj/project.pbxproj b/LocationPicker.xcodeproj/project.pbxproj index 67242ff..0200940 100644 --- a/LocationPicker.xcodeproj/project.pbxproj +++ b/LocationPicker.xcodeproj/project.pbxproj @@ -115,11 +115,12 @@ attributes = { LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = almassapargali; TargetAttributes = { B62462FE1B68A4DE00646DE2 = { CreatedOnToolsVersion = 6.4; + LastSwiftMigration = 0800; }; }; }; @@ -179,8 +180,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -228,8 +231,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -249,6 +254,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -260,6 +266,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -272,6 +279,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -279,6 +287,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -290,6 +299,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.almassapargali.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/LocationPicker.xcodeproj/xcshareddata/xcschemes/LocationPicker.xcscheme b/LocationPicker.xcodeproj/xcshareddata/xcschemes/LocationPicker.xcscheme index 9797983..121324a 100644 --- a/LocationPicker.xcodeproj/xcshareddata/xcschemes/LocationPicker.xcscheme +++ b/LocationPicker.xcodeproj/xcshareddata/xcschemes/LocationPicker.xcscheme @@ -1,6 +1,6 @@ () } - public var completion: (Location? -> ())? + public var completion: ((Location?) -> ())? // region distance to be used for creation region when user selects place from search results public var resultRegionDistance: CLLocationDistance = 600 @@ -42,20 +42,20 @@ public class LocationPickerViewController: UIViewController { lazy public var currentLocationButtonBackground: UIColor = { if let navigationBar = self.navigationController?.navigationBar, - barTintColor = navigationBar.barTintColor { + let barTintColor = navigationBar.barTintColor { return barTintColor - } else { return .whiteColor() } + } else { return .white } }() /// default: .Minimal - public var searchBarStyle: UISearchBarStyle = .Minimal + public var searchBarStyle: UISearchBarStyle = .minimal /// default: .Default - public var statusBarStyle: UIStatusBarStyle = .Default + public var statusBarStyle: UIStatusBarStyle = .default - public var mapType: MKMapType = .Hybrid { + public var mapType: MKMapType = .hybrid { didSet { - if isViewLoaded() { + if isViewLoaded { mapView.mapType = mapType } } @@ -63,7 +63,7 @@ public class LocationPickerViewController: UIViewController { public var location: Location? { didSet { - if isViewLoaded() { + if isViewLoaded { searchBar.text = location.flatMap({ $0.title }) ?? "" updateAnnotation() } @@ -76,7 +76,7 @@ public class LocationPickerViewController: UIViewController { let locationManager = CLLocationManager() let geocoder = CLGeocoder() var localSearch: MKLocalSearch? - var searchTimer: NSTimer? + var searchTimer: Timer? var currentLocationListeners: [CurrentLocationListener] = [] @@ -113,7 +113,7 @@ public class LocationPickerViewController: UIViewController { } public override func loadView() { - mapView = MKMapView(frame: UIScreen.mainScreen().bounds) + mapView = MKMapView(frame: UIScreen.main.bounds) mapView.mapType = mapType view = mapView @@ -122,10 +122,10 @@ public class LocationPickerViewController: UIViewController { button.backgroundColor = currentLocationButtonBackground button.layer.masksToBounds = true button.layer.cornerRadius = 16 - let bundle = NSBundle(forClass: LocationPickerViewController.self) - button.setImage(UIImage(named: "geolocation", inBundle: bundle, compatibleWithTraitCollection: nil), forState: .Normal) + let bundle = Bundle(for: LocationPickerViewController.self) + button.setImage(UIImage(named: "geolocation", in: bundle, compatibleWith: nil), for: UIControlState()) button.addTarget(self, action: #selector(LocationPickerViewController.currentLocationPressed), - forControlEvents: .TouchUpInside) + for: .touchUpInside) view.addSubview(button) locationButton = button } @@ -147,7 +147,7 @@ public class LocationPickerViewController: UIViewController { definesPresentationContext = true // user location - mapView.userTrackingMode = .None + mapView.userTrackingMode = .none mapView.showsUserLocation = showCurrentLocationInitially || showCurrentLocationButton if useCurrentLocationAsHint { @@ -155,7 +155,7 @@ public class LocationPickerViewController: UIViewController { } } - public override func preferredStatusBarStyle() -> UIStatusBarStyle { + public override var preferredStatusBarStyle : UIStatusBarStyle { return statusBarStyle } @@ -196,7 +196,7 @@ public class LocationPickerViewController: UIViewController { showCurrentLocation() } - func showCurrentLocation(animated: Bool = true) { + func showCurrentLocation(_ animated: Bool = true) { let listener = CurrentLocationListener(once: true) { [weak self] location in self?.showCoordinates(location.coordinate, animated: animated) } @@ -212,18 +212,16 @@ public class LocationPickerViewController: UIViewController { } } - func showCoordinates(coordinate: CLLocationCoordinate2D, animated: Bool = true) { + func showCoordinates(_ coordinate: CLLocationCoordinate2D, animated: Bool = true) { let region = MKCoordinateRegionMakeWithDistance(coordinate, resultRegionDistance, resultRegionDistance) mapView.setRegion(region, animated: animated) } } extension LocationPickerViewController: CLLocationManagerDelegate { - public func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.first else { return } - for listener in currentLocationListeners { - listener.action(location) - } + currentLocationListeners.forEach { $0.action(location) } currentLocationListeners = currentLocationListeners.filter { !$0.once } manager.stopUpdatingLocation() } @@ -232,13 +230,12 @@ extension LocationPickerViewController: CLLocationManagerDelegate { // MARK: Searching extension LocationPickerViewController: UISearchResultsUpdating { - public func updateSearchResultsForSearchController(searchController: UISearchController) { + public func updateSearchResults(for searchController: UISearchController) { guard let term = searchController.searchBar.text else { return } searchTimer?.invalidate() - - let whitespaces = NSCharacterSet.whitespaceCharacterSet() - let searchTerm = term.stringByTrimmingCharactersInSet(whitespaces) + + let searchTerm = term.trimmingCharacters(in: CharacterSet.whitespaces) if searchTerm.isEmpty { results.locations = historyManager.history() @@ -248,42 +245,42 @@ extension LocationPickerViewController: UISearchResultsUpdating { // clear old results showItemsForSearchResult(nil) - searchTimer = NSTimer.scheduledTimerWithTimeInterval(0.2, + searchTimer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(LocationPickerViewController.searchFromTimer(_:)), userInfo: [LocationPickerViewController.SearchTermKey: searchTerm], repeats: false) } } - func searchFromTimer(timer: NSTimer) { + func searchFromTimer(_ timer: Timer) { guard let userInfo = timer.userInfo as? [String: AnyObject], - term = userInfo[LocationPickerViewController.SearchTermKey] as? String + let term = userInfo[LocationPickerViewController.SearchTermKey] as? String else { return } let request = MKLocalSearchRequest() request.naturalLanguageQuery = term - if let location = locationManager.location where useCurrentLocationAsHint { + if let location = locationManager.location, useCurrentLocationAsHint { request.region = MKCoordinateRegion(center: location.coordinate, span: MKCoordinateSpan(latitudeDelta: 2, longitudeDelta: 2)) } localSearch?.cancel() localSearch = MKLocalSearch(request: request) - localSearch!.startWithCompletionHandler { response, error in + localSearch!.start { response, _ in self.showItemsForSearchResult(response) } } - func showItemsForSearchResult(searchResult: MKLocalSearchResponse?) { + func showItemsForSearchResult(_ searchResult: MKLocalSearchResponse?) { results.locations = searchResult?.mapItems.map { Location(name: $0.name, placemark: $0.placemark) } ?? [] results.isShowingHistory = false results.tableView.reloadData() } - func selectedLocation(location: Location) { + func selectedLocation(_ location: Location) { // dismiss search results - dismissViewControllerAnimated(true) { + dismiss(animated: true) { // set location, this also adds annotation self.location = location self.showCoordinates(location.coordinate) @@ -296,10 +293,10 @@ extension LocationPickerViewController: UISearchResultsUpdating { // MARK: Selecting location with gesture extension LocationPickerViewController { - func addLocation(gestureRecognizer: UIGestureRecognizer) { - if gestureRecognizer.state == .Began { - let point = gestureRecognizer.locationInView(mapView) - let coordinates = mapView.convertPoint(point, toCoordinateFromView: mapView) + func addLocation(_ gestureRecognizer: UIGestureRecognizer) { + if gestureRecognizer.state == .began { + let point = gestureRecognizer.location(in: mapView) + let coordinates = mapView.convert(point, toCoordinateFrom: mapView) let location = CLLocation(latitude: coordinates.latitude, longitude: coordinates.longitude) // clean location, cleans out old annotation too @@ -314,9 +311,9 @@ extension LocationPickerViewController { geocoder.reverseGeocodeLocation(location) { response, error in if let error = error { // show error and remove annotation - let alert = UIAlertController(title: nil, message: error.localizedDescription, preferredStyle: .Alert) - alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: { _ in })) - self.presentViewController(alert, animated: true) { + let alert = UIAlertController(title: nil, message: error.localizedDescription, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: { _ in })) + self.present(alert, animated: true) { self.mapView.removeAnnotation(annotation) } } else if let placemark = response?.first { @@ -334,11 +331,11 @@ extension LocationPickerViewController { // MARK: MKMapViewDelegate extension LocationPickerViewController: MKMapViewDelegate { - public func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? { + public func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { if annotation is MKUserLocation { return nil } let pin = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "annotation") - pin.pinColor = .Green + pin.pinColor = .green // drop only on long press gesture let fromLongPress = annotation is MKPointAnnotation pin.animatesDrop = fromLongPress @@ -349,25 +346,25 @@ extension LocationPickerViewController: MKMapViewDelegate { func selectLocationButton() -> UIButton { let button = UIButton(frame: CGRect(x: 0, y: 0, width: 70, height: 30)) - button.setTitle(selectButtonTitle, forState: .Normal) + button.setTitle(selectButtonTitle, for: UIControlState()) if let titleLabel = button.titleLabel { - let width = titleLabel.textRectForBounds(CGRect(x: 0, y: 0, width: Int.max, height: 30), limitedToNumberOfLines: 1).width + let width = titleLabel.textRect(forBounds: CGRect(x: 0, y: 0, width: Int.max, height: 30), limitedToNumberOfLines: 1).width button.frame.size = CGSize(width: width, height: 30.0) } - button.setTitleColor(view.tintColor, forState: .Normal) + button.setTitleColor(view.tintColor, for: UIControlState()) return button } - public func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { + public func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { completion?(location) - if let navigation = navigationController where navigation.viewControllers.count > 1 { - navigation.popViewControllerAnimated(true) + if let navigation = navigationController, navigation.viewControllers.count > 1 { + navigation.popViewController(animated: true) } else { - presentingViewController?.dismissViewControllerAnimated(true, completion: nil) + presentingViewController?.dismiss(animated: true, completion: nil) } } - public func mapView(mapView: MKMapView, didAddAnnotationViews views: [MKAnnotationView]) { + public func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) { let pins = mapView.annotations.filter { $0 is MKPinAnnotationView } assert(pins.count <= 1, "Only 1 pin annotation should be on map at a time") } @@ -376,19 +373,19 @@ extension LocationPickerViewController: MKMapViewDelegate { // MARK: UISearchBarDelegate extension LocationPickerViewController: UISearchBarDelegate { - public func searchBarTextDidBeginEditing(searchBar: UISearchBar) { + public func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) { // dirty hack to show history when there is no text in search bar // to be replaced later (hopefully) - if let text = searchBar.text where text.isEmpty { + if let text = searchBar.text, text.isEmpty { searchBar.text = " " } } - public func searchBar(searchBar: UISearchBar, textDidChange searchText: String) { + public func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { // remove location if user presses clear or removes text if searchText.isEmpty { location = nil searchBar.text = " " } } -} \ No newline at end of file +} diff --git a/LocationPicker/LocationSearchResultsViewController.swift b/LocationPicker/LocationSearchResultsViewController.swift index e629868..4b972fd 100644 --- a/LocationPicker/LocationSearchResultsViewController.swift +++ b/LocationPicker/LocationSearchResultsViewController.swift @@ -11,7 +11,7 @@ import MapKit class LocationSearchResultsViewController: UITableViewController { var locations: [Location] = [] - var onSelectLocation: (Location -> ())? + var onSelectLocation: ((Location) -> ())? var isShowingHistory = false var searchHistoryLabel: String? @@ -20,18 +20,18 @@ class LocationSearchResultsViewController: UITableViewController { extendedLayoutIncludesOpaqueBars = true } - override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return isShowingHistory ? searchHistoryLabel : nil } - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return locations.count } - - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCellWithIdentifier("LocationCell") - ?? UITableViewCell(style: .Subtitle, reuseIdentifier: "LocationCell") - + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "LocationCell") + ?? UITableViewCell(style: .subtitle, reuseIdentifier: "LocationCell") + let location = locations[indexPath.row] cell.textLabel?.text = location.name cell.detailTextLabel?.text = location.address @@ -39,7 +39,7 @@ class LocationSearchResultsViewController: UITableViewController { return cell } - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { onSelectLocation?(locations[indexPath.row]) } } diff --git a/LocationPicker/SearchHistoryManager.swift b/LocationPicker/SearchHistoryManager.swift index 5e6d3ee..faec73f 100644 --- a/LocationPicker/SearchHistoryManager.swift +++ b/LocationPicker/SearchHistoryManager.swift @@ -10,26 +10,24 @@ import UIKit import MapKit struct SearchHistoryManager { - private let HistoryKey = "RecentLocationsKey" + fileprivate let HistoryKey = "RecentLocationsKey" - private var defaults: NSUserDefaults { - return NSUserDefaults.standardUserDefaults() - } + fileprivate var defaults = UserDefaults.standard func history() -> [Location] { - let history = defaults.objectForKey(HistoryKey) as? [NSDictionary] ?? [] + let history = defaults.object(forKey: HistoryKey) as? [NSDictionary] ?? [] return history.flatMap(Location.fromDefaultsDic) } - func addToHistory(location: Location) { + func addToHistory(_ location: Location) { guard let dic = location.toDefaultsDic() else { return } - var history = defaults.objectForKey(HistoryKey) as? [NSDictionary] ?? [] + var history = defaults.object(forKey: HistoryKey) as? [NSDictionary] ?? [] let historyNames = history.flatMap { $0[LocationDicKeys.name] as? String } let alreadyInHistory = location.name.flatMap(historyNames.contains) ?? false if !alreadyInHistory { - history.insert(dic, atIndex: 0) - defaults.setObject(history, forKey: HistoryKey) + history.insert(dic, at: 0) + defaults.set(history, forKey: HistoryKey) } } } @@ -51,9 +49,9 @@ extension CLLocationCoordinate2D { return [CoordinateDicKeys.latitude: latitude, CoordinateDicKeys.longitude: longitude] } - static func fromDefaultsDic(dic: NSDictionary) -> CLLocationCoordinate2D? { + static func fromDefaultsDic(_ dic: NSDictionary) -> CLLocationCoordinate2D? { guard let latitude = dic[CoordinateDicKeys.latitude] as? NSNumber, - longitude = dic[CoordinateDicKeys.longitude] as? NSNumber else { return nil } + let longitude = dic[CoordinateDicKeys.longitude] as? NSNumber else { return nil } return CLLocationCoordinate2D(latitude: latitude.doubleValue, longitude: longitude.doubleValue) } } @@ -61,22 +59,22 @@ extension CLLocationCoordinate2D { extension Location { func toDefaultsDic() -> NSDictionary? { guard let addressDic = placemark.addressDictionary, - placemarkCoordinatesDic = placemark.location?.coordinate.toDefaultsDic() + let placemarkCoordinatesDic = placemark.location?.coordinate.toDefaultsDic() else { return nil } var dic: [String: AnyObject] = [ LocationDicKeys.locationCoordinates: location.coordinate.toDefaultsDic(), - LocationDicKeys.placemarkAddressDic: addressDic, + LocationDicKeys.placemarkAddressDic: addressDic as AnyObject, LocationDicKeys.placemarkCoordinates: placemarkCoordinatesDic ] - if let name = name { dic[LocationDicKeys.name] = name } - return dic + if let name = name { dic[LocationDicKeys.name] = name as AnyObject? } + return dic as NSDictionary? } - class func fromDefaultsDic(dic: NSDictionary) -> Location? { + class func fromDefaultsDic(_ dic: NSDictionary) -> Location? { guard let placemarkCoordinatesDic = dic[LocationDicKeys.placemarkCoordinates] as? NSDictionary, - placemarkCoordinates = CLLocationCoordinate2D.fromDefaultsDic(placemarkCoordinatesDic), - placemarkAddressDic = dic[LocationDicKeys.placemarkAddressDic] as? [String: AnyObject] + let placemarkCoordinates = CLLocationCoordinate2D.fromDefaultsDic(placemarkCoordinatesDic), + let placemarkAddressDic = dic[LocationDicKeys.placemarkAddressDic] as? [String: AnyObject] else { return nil } let coordinatesDic = dic[LocationDicKeys.locationCoordinates] as? NSDictionary @@ -84,7 +82,7 @@ extension Location { let location = coordinate.flatMap { CLLocation(latitude: $0.latitude, longitude: $0.longitude) } return Location(name: dic[LocationDicKeys.name] as? String, - location: location, - placemark: MKPlacemark(coordinate: placemarkCoordinates, addressDictionary: placemarkAddressDic)) + location: location, placemark: MKPlacemark( + coordinate: placemarkCoordinates, addressDictionary: placemarkAddressDic)) } -} \ No newline at end of file +}