diff --git a/LocationPicker.xcodeproj/project.pbxproj b/LocationPicker.xcodeproj/project.pbxproj index bcd341f..354467e 100644 --- a/LocationPicker.xcodeproj/project.pbxproj +++ b/LocationPicker.xcodeproj/project.pbxproj @@ -272,7 +272,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0.1; }; name = Debug; }; @@ -294,7 +294,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0.1; }; name = Release; }; diff --git a/LocationPicker.xcodeproj/xcshareddata/xcschemes/LocationPicker.xcscheme b/LocationPicker.xcodeproj/xcshareddata/xcschemes/LocationPicker.xcscheme index dca8896..e39ac10 100644 --- a/LocationPicker.xcodeproj/xcshareddata/xcschemes/LocationPicker.xcscheme +++ b/LocationPicker.xcodeproj/xcshareddata/xcschemes/LocationPicker.xcscheme @@ -1,6 +1,6 @@ + + + + + + diff --git a/LocationPicker/Helpers.swift b/LocationPicker/Helpers.swift index 170e530..218004d 100644 --- a/LocationPicker/Helpers.swift +++ b/LocationPicker/Helpers.swift @@ -29,30 +29,17 @@ import Foundation import MapKit -@objc public enum LocationType: Int { - case CurrentLocation - case SearchLocation - case AlternativeLocation -} - -@objc public enum NavigationItemOrientation: Int { - case Left - case Right -} - - -func coordinateObjectFromTuple(coordinateTuple: (latitude: Double, longitude: Double)) -> CLLocationCoordinate2D { +func coordinateObject(fromTuple coordinateTuple: (latitude: Double, longitude: Double)) -> CLLocationCoordinate2D { return CLLocationCoordinate2D(latitude: coordinateTuple.latitude, longitude: coordinateTuple.longitude) } -func coordinateTupleFromObject(coordinateObject: CLLocationCoordinate2D) -> (latitude: Double, longitude: Double) { +func coordinateTuple(fromObject coordinateObject: CLLocationCoordinate2D) -> (latitude: Double, longitude: Double) { return (latitude: coordinateObject.latitude, longitude: coordinateObject.longitude) } - -private func isCoordinateOutOfChina(coordinate: CLLocationCoordinate2D) -> Bool { +private func isOutsideChina(coordinate: CLLocationCoordinate2D) -> Bool { if coordinate.longitude < 72.004 || coordinate.longitude > 137.8347 { return true } @@ -62,25 +49,29 @@ private func isCoordinateOutOfChina(coordinate: CLLocationCoordinate2D) -> Bool return false } -private func transformLatitude(x x: Double, y: Double) -> Double { +private func transformLatitude(x: Double, y: Double) -> Double { + let a = sin(6.0 * x * M_PI), b = sin(2.0 * x * M_PI), c = sin(y * M_PI), d = sin(y / 3.0 * M_PI), e = sin(y / 12.0 * M_PI), f = sin(y * M_PI / 30.0) + var deltaLatitude = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y deltaLatitude += 0.1 * x * y + 0.2 * sqrt(abs(x)) - deltaLatitude += (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0 - deltaLatitude += (20.0 * sin(y * M_PI) + 40.0 * sin(y / 3.0 * M_PI)) * 2.0 / 3.0 - deltaLatitude += (160.0 * sin(y / 12.0 * M_PI) + 320 * sin(y * M_PI / 30.0)) * 2.0 / 3.0 + deltaLatitude += (20.0 * a + 20.0 * b) * 2.0 / 3.0 + deltaLatitude += (20.0 * c + 40.0 * d) * 2.0 / 3.0 + deltaLatitude += (160.0 * e + 320 * f) * 2.0 / 3.0 return deltaLatitude } -private func transformLongitude(x x: Double, y: Double) -> Double { +private func transformLongitude(x: Double, y: Double) -> Double { + let a = sin(6.0 * x * M_PI), b = sin(2.0 * x * M_PI), c = sin(x * M_PI), d = sin(x / 3.0 * M_PI), e = sin(x / 12.0 * M_PI), f = sin(x / 30.0 * M_PI) + var deltaLongitude = 300.0 + x + 2.0 * y + 0.1 * x * x deltaLongitude += 0.1 * x * y + 0.1 * sqrt(abs(x)) - deltaLongitude += (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0 - deltaLongitude += (20.0 * sin(x * M_PI) + 40.0 * sin(x / 3.0 * M_PI)) * 2.0 / 3.0 - deltaLongitude += (150.0 * sin(x / 12.0 * M_PI) + 300.0 * sin(x / 30.0 * M_PI)) * 2.0 / 3.0 + deltaLongitude += (20.0 * a + 20.0 * b) * 2.0 / 3.0 + deltaLongitude += (20.0 * c + 40.0 * d) * 2.0 / 3.0 + deltaLongitude += (150.0 * e + 300.0 * f) * 2.0 / 3.0 return deltaLongitude } -private func delta(latitude latitude: Double, longitude: Double) -> (Double, Double) { +private func delta(latitude: Double, longitude: Double) -> (Double, Double) { let r = 6378245.0 let ee = 0.00669342162296594323 let radLatitude = latitude / 180.0 * M_PI @@ -94,8 +85,8 @@ private func delta(latitude latitude: Double, longitude: Double) -> (Double, Dou return (deltaLatitude, deltaLongitude) } -func wgs2gcj(coordinate: CLLocationCoordinate2D) -> CLLocationCoordinate2D { - if isCoordinateOutOfChina(coordinate) { +func wgsToGcj(coordinate: CLLocationCoordinate2D) -> CLLocationCoordinate2D { + if isOutsideChina(coordinate: coordinate) { return coordinate } @@ -104,8 +95,8 @@ func wgs2gcj(coordinate: CLLocationCoordinate2D) -> CLLocationCoordinate2D { return revisedCoordinate } -func gcj2wgs(coordinate: CLLocationCoordinate2D) -> CLLocationCoordinate2D { - if isCoordinateOutOfChina(coordinate) { +func gcjToWgs(coordinate: CLLocationCoordinate2D) -> CLLocationCoordinate2D { + if isOutsideChina(coordinate: coordinate) { return coordinate } @@ -115,9 +106,8 @@ func gcj2wgs(coordinate: CLLocationCoordinate2D) -> CLLocationCoordinate2D { } - -func longitudinalDistanceFromMapRect(mapRect: MKMapRect) -> Double { +func getLongitudinalDistance(fromMapRect mapRect: MKMapRect) -> Double { let westMapPoint = MKMapPointMake(MKMapRectGetMaxX(mapRect), MKMapRectGetMidY(mapRect)) let eastMapPoint = MKMapPointMake(MKMapRectGetMinX(mapRect), MKMapRectGetMidY(mapRect)) return MKMetersBetweenMapPoints(westMapPoint, eastMapPoint) -} \ No newline at end of file +} diff --git a/LocationPicker/LocationCell.swift b/LocationPicker/LocationCell.swift index a985555..46820c2 100644 --- a/LocationPicker/LocationCell.swift +++ b/LocationPicker/LocationCell.swift @@ -31,14 +31,14 @@ import UIKit public class LocationCell: UITableViewCell { public var locationItem: LocationItem? - public var locationType: LocationType! + public var locationType: LocationPicker.LocationType! public let iconView = UIImageView() public let locationNameLabel = UILabel() public let locationAddressLabel = UILabel() public let containerView = UIView() - public convenience init(locationType: LocationType, locationItem: LocationItem?) { + public convenience init(locationType: LocationPicker.LocationType, locationItem: LocationItem?) { self.init() self.locationType = locationType self.locationItem = locationItem @@ -50,22 +50,22 @@ public class LocationCell: UITableViewCell { private func setupViews() { let length = contentView.bounds.height - backgroundColor = UIColor.clearColor() + backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0) separatorInset.left = length iconView.frame = CGRect(x: 0, y: 0, width: length, height: length) if let locationItem = locationItem { - locationNameLabel.font = UIFont.systemFontOfSize(16) + locationNameLabel.font = UIFont.systemFont(ofSize: 16) locationNameLabel.text = locationItem.name - locationAddressLabel.font = UIFont.systemFontOfSize(11) + locationAddressLabel.font = UIFont.systemFont(ofSize: 11) locationAddressLabel.text = locationItem.formattedAddressString } contentView.addSubview(iconView) containerView.addSubview(locationNameLabel) - if locationType! != .CurrentLocation { + if locationType! != .currentLocation { containerView.addSubview(locationAddressLabel) } contentView.addSubview(containerView) @@ -79,39 +79,39 @@ public class LocationCell: UITableViewCell { if #available(iOS 9.0, *) { let margins = contentView.layoutMarginsGuide - containerView.centerYAnchor.constraintEqualToAnchor(margins.centerYAnchor).active = true - containerView.leadingAnchor.constraintEqualToAnchor(iconView.trailingAnchor).active = true - containerView.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor).active = true + containerView.centerYAnchor.constraint(equalTo: margins.centerYAnchor).isActive = true + containerView.leadingAnchor.constraint(equalTo: iconView.trailingAnchor).isActive = true + containerView.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true - locationNameLabel.leadingAnchor.constraintEqualToAnchor(containerView.leadingAnchor).active = true - locationNameLabel.trailingAnchor.constraintEqualToAnchor(containerView.trailingAnchor).active = true - if locationType! == .CurrentLocation { - locationNameLabel.centerYAnchor.constraintEqualToAnchor(containerView.centerYAnchor).active = true + locationNameLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true + locationNameLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true + if locationType! == .currentLocation { + locationNameLabel.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true } else { - locationNameLabel.topAnchor.constraintEqualToAnchor(containerView.topAnchor).active = true + locationNameLabel.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true - locationAddressLabel.topAnchor.constraintEqualToAnchor(locationNameLabel.bottomAnchor).active = true - locationAddressLabel.leadingAnchor.constraintEqualToAnchor(containerView.leadingAnchor).active = true - locationAddressLabel.trailingAnchor.constraintEqualToAnchor(containerView.trailingAnchor).active = true - locationAddressLabel.bottomAnchor.constraintEqualToAnchor(containerView.bottomAnchor).active = true + locationAddressLabel.topAnchor.constraint(equalTo: locationNameLabel.bottomAnchor).isActive = true + locationAddressLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true + locationAddressLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true + locationAddressLabel.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true } } else { - NSLayoutConstraint(item: containerView, attribute: .CenterY, relatedBy: .Equal, toItem: contentView, attribute: .CenterY, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: containerView, attribute: .Leading, relatedBy: .Equal, toItem: iconView, attribute: .Trailing, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: containerView, attribute: .Trailing, relatedBy: .Equal, toItem: contentView, attribute: .Trailing, multiplier: 1, constant: 0).active = true + NSLayoutConstraint(item: containerView, attribute: .centerY, relatedBy: .equal, toItem: contentView, attribute: .centerY, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: containerView, attribute: .leading, relatedBy: .equal, toItem: iconView, attribute: .trailing, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: containerView, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: 0).isActive = true - NSLayoutConstraint(item: locationNameLabel, attribute: .Leading, relatedBy: .Equal, toItem: containerView, attribute: .Leading, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: locationNameLabel, attribute: .Trailing, relatedBy: .Equal, toItem: containerView, attribute: .Trailing, multiplier: 1, constant: 0).active = true + NSLayoutConstraint(item: locationNameLabel, attribute: .leading, relatedBy: .equal, toItem: containerView, attribute: .leading, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: locationNameLabel, attribute: .trailing, relatedBy: .equal, toItem: containerView, attribute: .trailing, multiplier: 1, constant: 0).isActive = true - if locationType! == .CurrentLocation { - NSLayoutConstraint(item: locationNameLabel, attribute: .CenterY, relatedBy: .Equal, toItem: containerView, attribute: .CenterY, multiplier: 1, constant: 0).active = true + if locationType! == .currentLocation { + NSLayoutConstraint(item: locationNameLabel, attribute: .centerY, relatedBy: .equal, toItem: containerView, attribute: .centerY, multiplier: 1, constant: 0).isActive = true } else { - NSLayoutConstraint(item: locationNameLabel, attribute: .Top, relatedBy: .Equal, toItem: containerView, attribute: .Top, multiplier: 1, constant: 0).active = true + NSLayoutConstraint(item: locationNameLabel, attribute: .top, relatedBy: .equal, toItem: containerView, attribute: .top, multiplier: 1, constant: 0).isActive = true - NSLayoutConstraint(item: locationAddressLabel, attribute: .Top, relatedBy: .Equal, toItem: locationNameLabel, attribute: .Bottom, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: locationAddressLabel, attribute: .Leading, relatedBy: .Equal, toItem: containerView, attribute: .Leading, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: locationAddressLabel, attribute: .Trailing, relatedBy: .Equal, toItem: containerView, attribute: .Trailing, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: locationAddressLabel, attribute: .Bottom, relatedBy: .Equal, toItem: containerView, attribute: .Bottom, multiplier: 1, constant: 0).active = true + NSLayoutConstraint(item: locationAddressLabel, attribute: .top, relatedBy: .equal, toItem: locationNameLabel, attribute: .bottom, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: locationAddressLabel, attribute: .leading, relatedBy: .equal, toItem: containerView, attribute: .leading, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: locationAddressLabel, attribute: .trailing, relatedBy: .equal, toItem: containerView, attribute: .trailing, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: locationAddressLabel, attribute: .bottom, relatedBy: .equal, toItem: containerView, attribute: .bottom, multiplier: 1, constant: 0).isActive = true } } diff --git a/LocationPicker/LocationItem.swift b/LocationPicker/LocationItem.swift index f7c6d0f..3011aae 100644 --- a/LocationPicker/LocationItem.swift +++ b/LocationPicker/LocationItem.swift @@ -58,45 +58,44 @@ public class LocationItem: NSObject, NSCoding { public let mapItem: MKMapItem - - /// The name of the location. A reference to `MKMapItem` object's property `name`. + /// The name of the location. A reference to `MKMapItem` object's property `name`. public var name: String { get { return mapItem.name ?? "" } } - /// The coordinate of the location. A reference to `MKMapItem` object's property `placemark.coordinate` and converted to tuple. Only when the `allowArbitraryLocation` property of `LocationPicker` class is set to `true`, can this property be `nil`. + /// The coordinate of the location. A reference to `MKMapItem` object's property `placemark.coordinate` and converted to tuple. Only when the `allowArbitraryLocation` property of `LocationPicker` class is set to `true`, can this property be `nil`. public var coordinate: (latitude: Double, longitude: Double)? { get { let coordinate = mapItem.placemark.coordinate if CLLocationCoordinate2DIsValid(coordinate) { - return coordinateTupleFromObject(coordinate) + return coordinateTuple(fromObject: coordinate) } else { return nil } } } - /// The address dictionary of the location. A reference to `MKMapItem` object's property `placemark.addressDictionary` - /// - Note: This dictionary along with a coordinate can be used to create a `MKPlacemark` object which can create a `MKMapItem` object. - public var addressDictionary: [NSObject: AnyObject]? { + /// The address dictionary of the location. A reference to `MKMapItem` object's property `placemark.addressDictionary` + /// - Note: This dictionary along with a coordinate can be used to create a `MKPlacemark` object which can create a `MKMapItem` object. + public var addressDictionary: [AnyHashable: Any]? { get { return mapItem.placemark.addressDictionary } } - /// The address of the location. This is the value to the key _"FormattedAddressLines"_ in `addressDictionary`. It is the address text formatted according to user's region. - /// - Note: If you would like to format the address yourself, you can use `addressDictionary` property to create one. + /// The address of the location. This is the value to the key _"FormattedAddressLines"_ in `addressDictionary`. It is the address text formatted according to user's region. + /// - Note: If you would like to format the address yourself, you can use `addressDictionary` property to create one. + public var formattedAddressString: String? { get { - let addressParts = (addressDictionary?["FormattedAddressLines"] as? [String]) - return addressParts?.count > 1 ? addressParts?[1] : addressParts?[0] + guard let addressParts = (addressDictionary?["FormattedAddressLines"] as? [String]) else { return nil } + return addressParts.count > 1 ? addressParts[1] : addressParts[0] } } - public override var hashValue: Int { get { if let coordinate = coordinate { @@ -114,14 +113,12 @@ public class LocationItem: NSObject, NSCoding { } - public init(mapItem: MKMapItem) { self.mapItem = mapItem } public init(coordinate: (latitude: Double, longitude: Double), addressDictionary: [String: AnyObject]) { - let coordinateObject = coordinateObjectFromTuple(coordinate) - let placeMark = MKPlacemark(coordinate: coordinateObject, addressDictionary: addressDictionary) + let placeMark = MKPlacemark(coordinate: coordinateObject(fromTuple: coordinate), addressDictionary: addressDictionary) self.mapItem = MKMapItem(placemark: placeMark) } @@ -132,23 +129,23 @@ public class LocationItem: NSObject, NSCoding { self.mapItem.name = locationName } - public override func isEqual(object: AnyObject?) -> Bool { - return object?.hashValue == hashValue + public override func isEqual(_ object: Any?) -> Bool { + guard let object = object else { return false } + return (object as AnyObject).hashValue == hashValue } - - public required convenience init(coder decoder: NSCoder) { - let latitude = decoder.decodeDoubleForKey("latitude") - let longitude = decoder.decodeDoubleForKey("longitude") - let addressDictionary = decoder.decodeObjectForKey("addressDictionary") as! [String: AnyObject] + public required convenience init(coder aDecoder: NSCoder) { + let latitude = aDecoder.decodeDouble(forKey: "latitude") + let longitude = aDecoder.decodeDouble(forKey: "longitude") + let addressDictionary = aDecoder.decodeObject(forKey: "addressDictionary") as! [String: AnyObject] self.init(coordinate: (latitude, longitude), addressDictionary: addressDictionary) } - public func encodeWithCoder(coder: NSCoder) { - coder.encodeDouble(mapItem.placemark.coordinate.latitude, forKey: "latitude") - coder.encodeDouble(mapItem.placemark.coordinate.longitude, forKey: "longitude") - coder.encodeObject(addressDictionary, forKey: "addressDictionary") + public func encode(with aCoder: NSCoder) { + aCoder.encode(mapItem.placemark.coordinate.latitude, forKey: "latitude") + aCoder.encode(mapItem.placemark.coordinate.longitude, forKey: "longitude") + aCoder.encode(addressDictionary, forKey: "addressDictionary") } } diff --git a/LocationPicker/LocationPicker.swift b/LocationPicker/LocationPicker.swift index 46380aa..4996c7e 100644 --- a/LocationPicker/LocationPicker.swift +++ b/LocationPicker/LocationPicker.swift @@ -29,9 +29,23 @@ import UIKit import MapKit -public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { +open class LocationPicker: UIViewController, UIGestureRecognizerDelegate { - // MARK: Completion closures + // MARK: Types + + public enum NavigationItemOrientation { + case left + case right + } + + public enum LocationType: Int { + case currentLocation + case searchLocation + case alternativeLocation + } + + + // MARK: - Completion closures /** Completion closure executed after everytime user select a location. @@ -149,13 +163,12 @@ public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { public var locationDeniedHandler: ((LocationPicker) -> Void)? - // MARK: Optional varaiables - /// Delegate of `protocol LocationPickerDelegate` + /// Delegate of `protocol LocationPickerDelegate` public var delegate: LocationPickerDelegate? - /// DataSource of `protocol LocationPickerDataSource` + /// DataSource of `protocol LocationPickerDataSource` public var dataSource: LocationPickerDataSource? /** @@ -206,51 +219,48 @@ public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { - Note: If an arbitrary location is selected, its coordinate in `LocationItem` will be `nil`. __Default__ is __`false`__. */ - public var allowArbitraryLocation = false - + public var isAllowArbitraryLocation = false // MARK: UI Customizations - /// Text that indicates user's current location. __Default__ is __`"Current Location"`__. + /// Text that indicates user's current location. __Default__ is __`"Current Location"`__. public var currentLocationText = "Current Location" - /// Text of search bar's placeholder. __Default__ is __`"Search for location"`__. + /// Text of search bar's placeholder. __Default__ is __`"Search for location"`__. public var searchBarPlaceholder = "Search for location" - /// Text of location denied alert title. __Default__ is __`"Location access denied"`__ + /// Text of location denied alert title. __Default__ is __`"Location access denied"`__ public var locationDeniedAlertTitle = "Location access denied" - /// Text of location denied alert message. __Default__ is __`"Grant location access to use current location"`__ + /// Text of location denied alert message. __Default__ is __`"Grant location access to use current location"`__ public var locationDeniedAlertMessage = "Grant location access to use current location" - /// Text of location denied alert _Grant_ button. __Default__ is __`"Grant"`__ + /// Text of location denied alert _Grant_ button. __Default__ is __`"Grant"`__ public var locationDeniedGrantText = "Grant" - /// Text of location denied alert _Cancel_ button. __Default__ is __`"Cancel"`__ + /// Text of location denied alert _Cancel_ button. __Default__ is __`"Cancel"`__ public var locationDeniedCancelText = "Cancel" - - /// Longitudinal distance in meters that the map view shows when user select a location and before zoom in or zoom out. __Default__ is __`1000`__. + /// Longitudinal distance in meters that the map view shows when user select a location and before zoom in or zoom out. __Default__ is __`1000`__. public var defaultLongitudinalDistance: Double = 1000 - /// Distance in meters that is used to search locations. __Default__ is __`10000`__ + /// Distance in meters that is used to search locations. __Default__ is __`10000`__ public var searchDistance: Double = 10000 /// Default coordinate to use when current location information is not available. If not set, none is used. public var defaultSearchCoordinate: CLLocationCoordinate2D? + /// `mapView.zoomEnabled` will be set to this property's value after view is loaded. __Default__ is __`true`__ + public var isMapViewZoomEnabled = true - /// `mapView.zoomEnabled` will be set to this property's value after view is loaded. __Default__ is __`true`__ - public var mapViewZoomEnabled = true - - /// `mapView.showsUserLocation` is set to this property's value after view is loaded. __Default__ is __`true`__ - public var mapViewShowsUserLocation = true + /// `mapView.showsUserLocation` is set to this property's value after view is loaded. __Default__ is __`true`__ + public var isMapViewShowsUserLocation = true - /// `mapView.scrollEnabled` is set to this property's value after view is loaded. __Default__ is __`true`__ - public var mapViewScrollEnabled = true + /// `mapView.scrollEnabled` is set to this property's value after view is loaded. __Default__ is __`true`__ + public var isMapViewScrollEnabled = true /// Whether redirect to the exact coordinate after queried. __Default__ is __`true`__ public var isRedirectToExactCoordinate = true @@ -260,54 +270,51 @@ public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { - important: If this property is set to `true`, remember to update your models by closure, delegate, or override. */ - public var alternativeLocationEditable = false + public var isAlternativeLocationEditable = false /** Whether to force reverse geocoding or not. If this property is set to `true`, the location will be reverse geocoded. This is helpful if you require an exact location (e.g. providing street), but the user just searched for a town name. The default behavior is to not geocode any additional search result. */ - public var forceReverseGeocoding = false + public var isForceReverseGeocoding = false + /// `tableView.backgroundColor` is set to this property's value afte view is loaded. __Default__ is __`UIColor.whiteColor()`__ + public var tableViewBackgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) - /// `tableView.backgroundColor` is set to this property's value afte view is loaded. __Default__ is __`UIColor.whiteColor()`__ - public var tableViewBackgroundColor = UIColor.whiteColor() + /// The color of the icon showed in current location cell. __Default__ is __`UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1)`__ + public var currentLocationIconColor = #colorLiteral(red: 0.1176470588, green: 0.5098039216, blue: 0.3568627451, alpha: 1) - /// The color of the icon showed in current location cell. __Default__ is __`UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1)`__ - public var currentLocationIconColor = UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1) + /// The color of the icon showed in search result location cells. __Default__ is __`UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1)`__ + public var searchResultLocationIconColor = #colorLiteral(red: 0.1176470588, green: 0.5098039216, blue: 0.3568627451, alpha: 1) - /// The color of the icon showed in search result location cells. __Default__ is __`UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1)`__ - public var searchResultLocationIconColor = UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1) + /// The color of the icon showed in alternative location cells. __Default__ is __`UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1)`__ + public var alternativeLocationIconColor = #colorLiteral(red: 0.1176470588, green: 0.5098039216, blue: 0.3568627451, alpha: 1) - /// The color of the icon showed in alternative location cells. __Default__ is __`UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1)`__ - public var alternativeLocationIconColor = UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1) + /// The color of the pin showed in the center of map view. __Default__ is __`UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1)`__ + public var pinColor = #colorLiteral(red: 0.1176470588, green: 0.5098039216, blue: 0.3568627451, alpha: 1) - /// The color of the pin showed in the center of map view. __Default__ is __`UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1)`__ - public var pinColor = UIColor(hue: 0.447, saturation: 0.731, brightness: 0.569, alpha: 1) + /// The color of primary text color. __Default__ is __`UIColor(colorLiteralRed: 0.34902, green: 0.384314, blue: 0.427451, alpha: 1)`__ + public var primaryTextColor = #colorLiteral(red: 0.34902, green: 0.384314, blue: 0.427451, alpha: 1) - /// The color of primary text color. __Default__ is __`UIColor(colorLiteralRed: 0.34902, green: 0.384314, blue: 0.427451, alpha: 1)`__ - public var primaryTextColor = UIColor(colorLiteralRed: 0.34902, green: 0.384314, blue: 0.427451, alpha: 1) + /// The color of secondary text color. __Default__ is __`UIColor(colorLiteralRed: 0.541176, green: 0.568627, blue: 0.584314, alpha: 1)`__ + public var secondaryTextColor = #colorLiteral(red: 0.541176, green: 0.568627, blue: 0.584314, alpha: 1) - /// The color of secondary text color. __Default__ is __`UIColor(colorLiteralRed: 0.541176, green: 0.568627, blue: 0.584314, alpha: 1)`__ - public var secondaryTextColor = UIColor(colorLiteralRed: 0.541176, green: 0.568627, blue: 0.584314, alpha: 1) + /// The image of the icon showed in current location cell. If this property is set, the `var currentLocationIconColor` won't be adopted. + public var currentLocationIcon: UIImage? = nil + /// The image of the icon showed in search result location cells. If this property is set, the `var searchResultLocationIconColor` won't be adopted. + public var searchResultLocationIcon: UIImage? = nil - /// The image of the icon showed in current location cell. If this property is set, the `var currentLocationIconColor` won't be adopted. - public var currentLocationIconImage: UIImage? = nil + /// The image of the icon showed in alternative location cells. If this property is set, the `var alternativeLocationIconColor` won't be adopted. + public var alternativeLocationIcon: UIImage? = nil - /// The image of the icon showed in search result location cells. If this property is set, the `var searchResultLocationIconColor` won't be adopted. - public var searchResultLocationIconImage: UIImage? = nil - - /// The image of the icon showed in alternative location cells. If this property is set, the `var alternativeLocationIconColor` won't be adopted. - public var alternativeLocationIconImage: UIImage? = nil - - /// The image of the pin showed in the center of map view. If this property is set, the `var pinColor` won't be adopted. + /// The image of the pin showed in the center of map view. If this property is set, the `var pinColor` won't be adopted. public var pinImage: UIImage? = nil - - // MARK: UI Elements + // MARK: - UI Elements public let searchBar = UISearchBar() public let tableView = UITableView() @@ -317,23 +324,27 @@ public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { public private(set) var barButtonItems: (doneButtonItem: UIBarButtonItem, cancelButtonItem: UIBarButtonItem)? - // MARK: Attributes - private let locationManager = CLLocationManager() + fileprivate let locationManager = CLLocationManager() private let geocoder = CLGeocoder() - private var selectedLocationItem: LocationItem? - private var searchResultLocations = [LocationItem]() + fileprivate var selectedLocationItem: LocationItem? + fileprivate var searchResultLocations = [LocationItem]() - private var alternativeLocationCount: Int { + fileprivate var alternativeLocationCount: Int { get { return alternativeLocations?.count ?? dataSource?.numberOfAlternativeLocations() ?? 0 } } - private var longitudinalDistance: Double! // This property is used to record the longitudinal distance of the map view. This is neccessary because when user zoom in or zoom out the map view, func showMapViewWithCenterCoordinate(coordinate: CLLocationCoordinate2D, WithDistance distance: Double) will reset the region of the map view. - private var mapViewCenterChanged = false // This property is used to record whether the map view center changes. This is neccessary because private func showMapViewWithCenterCoordinate(coordinate: CLLocationCoordinate2D, WithDistance distance: Double) would trigger func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) which calls func reverseGeocodeLocation(location: CLLocation), and this method calls private func showMapViewWithCenterCoordinate(coordinate: CLLocationCoordinate2D, WithDistance distance: Double) back, this would lead to an infinite loop. + + /// This property is used to record the longitudinal distance of the map view. This is neccessary because when user zoom in or zoom out the map view, func showMapViewWithCenterCoordinate(coordinate: CLLocationCoordinate2D, WithDistance distance: Double) will reset the region of the map view. + public var longitudinalDistance: Double! + + + /// This property is used to record whether the map view center changes. This is neccessary because private func showMapViewWithCenterCoordinate(coordinate: CLLocationCoordinate2D, WithDistance distance: Double) would trigger func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) which calls func reverseGeocodeLocation(location: CLLocation), and this method calls private func showMapViewWithCenterCoordinate(coordinate: CLLocationCoordinate2D, WithDistance distance: Double) back, this would lead to an infinite loop. + public var isMapViewCenterChanged = false private var mapViewHeightConstraint: NSLayoutConstraint! private var mapViewHeight: CGFloat { @@ -343,134 +354,11 @@ public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { } private var pinViewCenterYConstraint: NSLayoutConstraint! - private var pinViewImageHeight: CGFloat { + fileprivate var pinViewImageHeight: CGFloat { get { return pinView.image!.size.height } } - - - - // MARK: View Controller - - public override func viewDidLoad() { - super.viewDidLoad() - - longitudinalDistance = defaultLongitudinalDistance - - setupLocationManager() - setupViews() - layoutViews() - - } - - public override func viewWillDisappear(animated: Bool) { - super.viewWillDisappear(animated) - - guard barButtonItems?.doneButtonItem == nil else { return } - if let locationItem = selectedLocationItem { - locationDidPick(locationItem) - } - } - - - - // MARK: Initializations - - private func setupLocationManager() { - locationManager.delegate = self - locationManager.desiredAccuracy = kCLLocationAccuracyBest - locationManager.distanceFilter = 10 - if #available(iOS 9.0, *) { - locationManager.requestLocation() - } else { - locationManager.startUpdatingLocation() - } - } - - private func setupViews() { - view.backgroundColor = UIColor.whiteColor() // the background color of view needs to be set because this color would affect the color of navigation bar if it is translucent. - - searchBar.delegate = self - searchBar.placeholder = searchBarPlaceholder - let textFieldInsideSearchBar = searchBar.valueForKey("searchField") as! UITextField - textFieldInsideSearchBar.textColor = primaryTextColor - - tableView.delegate = self - tableView.dataSource = self - tableView.keyboardDismissMode = .OnDrag - tableView.backgroundColor = tableViewBackgroundColor - - mapView.zoomEnabled = mapViewZoomEnabled - mapView.rotateEnabled = false - mapView.pitchEnabled = false - mapView.scrollEnabled = mapViewScrollEnabled - mapView.showsUserLocation = mapViewShowsUserLocation - mapView.delegate = self - - pinView.image = pinImage ?? StyleKit.imageOfPinIconFilled(color: pinColor) - - if mapViewScrollEnabled { - let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(panGestureInMapViewDidRecognize(_:))) - panGestureRecognizer.delegate = self - mapView.addGestureRecognizer(panGestureRecognizer) - } - - view.addSubview(searchBar) - view.addSubview(tableView) - view.addSubview(mapView) - mapView.addSubview(pinView) - } - - private func layoutViews() { - searchBar.translatesAutoresizingMaskIntoConstraints = false - tableView.translatesAutoresizingMaskIntoConstraints = false - mapView.translatesAutoresizingMaskIntoConstraints = false - pinView.translatesAutoresizingMaskIntoConstraints = false - - if #available(iOS 9.0, *) { - searchBar.topAnchor.constraintEqualToAnchor(topLayoutGuide.bottomAnchor).active = true - searchBar.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true - searchBar.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor).active = true - - tableView.topAnchor.constraintEqualToAnchor(searchBar.bottomAnchor).active = true - tableView.leadingAnchor.constraintEqualToAnchor(searchBar.leadingAnchor).active = true - tableView.trailingAnchor.constraintEqualToAnchor(searchBar.trailingAnchor).active = true - - mapView.topAnchor.constraintEqualToAnchor(tableView.bottomAnchor).active = true - mapView.leadingAnchor.constraintEqualToAnchor(tableView.leadingAnchor).active = true - mapView.trailingAnchor.constraintEqualToAnchor(tableView.trailingAnchor).active = true - mapView.bottomAnchor.constraintEqualToAnchor(bottomLayoutGuide.topAnchor).active = true - - mapViewHeightConstraint = mapView.heightAnchor.constraintEqualToConstant(0) - mapViewHeightConstraint.active = true - - pinView.centerXAnchor.constraintEqualToAnchor(mapView.centerXAnchor).active = true - pinViewCenterYConstraint = pinView.centerYAnchor.constraintEqualToAnchor(mapView.centerYAnchor, constant: -pinViewImageHeight / 2) - pinViewCenterYConstraint.active = true - } else { - NSLayoutConstraint(item: searchBar, attribute: .Top, relatedBy: .Equal, toItem: topLayoutGuide, attribute: .Bottom, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: searchBar, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: searchBar, attribute: .Trailing, relatedBy: .Equal, toItem: view, attribute: .Trailing, multiplier: 1, constant: 0).active = true - - NSLayoutConstraint(item: tableView, attribute: .Top, relatedBy: .Equal, toItem: searchBar, attribute: .Bottom, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: tableView, attribute: .Leading, relatedBy: .Equal, toItem: searchBar, attribute: .Leading, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: tableView, attribute: .Trailing, relatedBy: .Equal, toItem: searchBar, attribute: .Trailing, multiplier: 1, constant: 0).active = true - - NSLayoutConstraint(item: mapView, attribute: .Top, relatedBy: .Equal, toItem: tableView, attribute: .Bottom, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: mapView, attribute: .Leading, relatedBy: .Equal, toItem: tableView, attribute: .Leading, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: mapView, attribute: .Trailing, relatedBy: .Equal, toItem: tableView, attribute: .Trailing, multiplier: 1, constant: 0).active = true - NSLayoutConstraint(item: mapView, attribute: .Bottom, relatedBy: .Equal, toItem: bottomLayoutGuide, attribute: .Top, multiplier: 1, constant: 0).active = true - - mapViewHeightConstraint = NSLayoutConstraint(item: mapView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .Height, multiplier: 1, constant: 0) - mapViewHeightConstraint.active = true - - NSLayoutConstraint(item: pinView, attribute: .CenterX, relatedBy: .Equal, toItem: mapView, attribute: .CenterX, multiplier: 1, constant: 0).active = true - pinViewCenterYConstraint = NSLayoutConstraint(item: pinView, attribute: .CenterY, relatedBy: .Equal, toItem: mapView, attribute: .CenterY, multiplier: 1, constant: -pinViewImageHeight / 2) - pinViewCenterYConstraint.active = true - } - } - // MARK: Customs @@ -491,27 +379,26 @@ public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { */ public func addBarButtons(doneButtonItem: UIBarButtonItem? = nil, cancelButtonItem: UIBarButtonItem? = nil, - doneButtonOrientation: NavigationItemOrientation = .Right) { - let doneButtonItem = doneButtonItem ?? UIBarButtonItem(barButtonSystemItem: .Done, target: nil, action: nil) - doneButtonItem.enabled = false + doneButtonOrientation: NavigationItemOrientation = .right) { + let doneButtonItem = doneButtonItem ?? UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil) + doneButtonItem.isEnabled = false doneButtonItem.target = self - doneButtonItem.action = #selector(doneButtonDidTap(_:)) + doneButtonItem.action = #selector(doneButtonDidTap(barButtonItem:)) - let cancelButtonItem = cancelButtonItem ?? UIBarButtonItem(barButtonSystemItem: .Cancel, target: nil, action: nil) + let cancelButtonItem = cancelButtonItem ?? UIBarButtonItem(barButtonSystemItem: .cancel, target: nil, action: nil) cancelButtonItem.target = self - cancelButtonItem.action = #selector(cancelButtonDidTap(_:)) + cancelButtonItem.action = #selector(cancelButtonDidTap(barButtonItem:)) switch doneButtonOrientation { - case .Right: + case .right: navigationItem.leftBarButtonItem = cancelButtonItem navigationItem.rightBarButtonItem = doneButtonItem - case .Left: + case .left: navigationItem.leftBarButtonItem = doneButtonItem navigationItem.rightBarButtonItem = cancelButtonItem } barButtonItems = (doneButtonItem, cancelButtonItem) - } /** @@ -560,7 +447,7 @@ public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { - parameter grantText: Text of location denied alert _Grant_ button text - parameter cancelText: Text of location denied alert _Cancel_ button text */ - public func setLocationDeniedAlertControllerTitle(title: String? = nil, message: String? = nil, grantText: String? = nil, cancelText: String? = nil) { + public func setLocationDeniedAlertControllerTexts(title: String? = nil, message: String? = nil, grantText: String? = nil, cancelText: String? = nil) { self.locationDeniedAlertTitle = title ?? self.locationDeniedAlertTitle self.locationDeniedAlertMessage = message ?? self.locationDeniedAlertMessage self.locationDeniedGrantText = grantText ?? self.locationDeniedGrantText @@ -568,75 +455,190 @@ public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { } - /** Decide if an item from MKLocalSearch should be displayed or not - parameter locationItem: An instance of `LocationItem` */ - public func shouldShowSearchResult(mapItem: MKMapItem) -> Bool { + open func shouldShowSearchResult(for mapItem: MKMapItem) -> Bool { return true } + // MARK: - View Controller + + open override func viewDidLoad() { + super.viewDidLoad() + + longitudinalDistance = defaultLongitudinalDistance + + setupLocationManager() + setupViews() + layoutViews() + } + + open override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + guard barButtonItems?.doneButtonItem == nil else { return } + + if let locationItem = selectedLocationItem { + locationDidPick(locationItem: locationItem) + } + } + + + // MARK: Initializations + + private func setupLocationManager() { + locationManager.delegate = self + locationManager.desiredAccuracy = kCLLocationAccuracyBest + locationManager.distanceFilter = 10 + if #available(iOS 9.0, *) { + locationManager.requestLocation() + } else { + locationManager.startUpdatingLocation() + } + } + + private func setupViews() { + view.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) // the background color of view needs to be set because this color would affect the color of navigation bar if it is translucent. + + searchBar.delegate = self + searchBar.placeholder = searchBarPlaceholder + let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as! UITextField + textFieldInsideSearchBar.textColor = primaryTextColor + + tableView.delegate = self + tableView.dataSource = self + tableView.keyboardDismissMode = .onDrag + tableView.backgroundColor = tableViewBackgroundColor + + mapView.isZoomEnabled = isMapViewZoomEnabled + mapView.isRotateEnabled = false + mapView.isPitchEnabled = false + mapView.isScrollEnabled = isMapViewScrollEnabled + mapView.showsUserLocation = isMapViewShowsUserLocation + mapView.delegate = self + + pinView.image = pinImage ?? StyleKit.imageOfPinIconFilled(color: pinColor) + + if isMapViewScrollEnabled { + let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(panGestureInMapViewDidRecognize(panGestureRecognizer:))) + panGestureRecognizer.delegate = self + mapView.addGestureRecognizer(panGestureRecognizer) + } + + view.addSubview(searchBar) + view.addSubview(tableView) + view.addSubview(mapView) + mapView.addSubview(pinView) + } + + private func layoutViews() { + searchBar.translatesAutoresizingMaskIntoConstraints = false + tableView.translatesAutoresizingMaskIntoConstraints = false + mapView.translatesAutoresizingMaskIntoConstraints = false + pinView.translatesAutoresizingMaskIntoConstraints = false + + if #available(iOS 9.0, *) { + searchBar.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true + searchBar.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true + searchBar.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true + + tableView.topAnchor.constraint(equalTo: searchBar.bottomAnchor).isActive = true + tableView.leadingAnchor.constraint(equalTo: searchBar.leadingAnchor).isActive = true + tableView.trailingAnchor.constraint(equalTo: searchBar.trailingAnchor).isActive = true + + mapView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true + mapView.leadingAnchor.constraint(equalTo: tableView.leadingAnchor).isActive = true + mapView.trailingAnchor.constraint(equalTo: tableView.trailingAnchor).isActive = true + mapView.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor).isActive = true + + mapViewHeightConstraint = mapView.heightAnchor.constraint(equalToConstant: 0) + mapViewHeightConstraint.isActive = true + + pinView.centerXAnchor.constraint(equalTo: mapView.centerXAnchor).isActive = true + pinViewCenterYConstraint = pinView.centerYAnchor.constraint(equalTo: mapView.centerYAnchor, constant: -pinViewImageHeight / 2) + pinViewCenterYConstraint.isActive = true + } else { + NSLayoutConstraint(item: searchBar, attribute: .top, relatedBy: .equal, toItem: topLayoutGuide, attribute: .bottom, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: searchBar, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: searchBar, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0).isActive = true + + NSLayoutConstraint(item: tableView, attribute: .top, relatedBy: .equal, toItem: searchBar, attribute: .bottom, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: tableView, attribute: .leading, relatedBy: .equal, toItem: searchBar, attribute: .leading, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: tableView, attribute: .trailing, relatedBy: .equal, toItem: searchBar, attribute: .trailing, multiplier: 1, constant: 0).isActive = true + + NSLayoutConstraint(item: mapView, attribute: .top, relatedBy: .equal, toItem: tableView, attribute: .bottom, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: mapView, attribute: .leading, relatedBy: .equal, toItem: tableView, attribute: .leading, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: mapView, attribute: .trailing, relatedBy: .equal, toItem: tableView, attribute: .trailing, multiplier: 1, constant: 0).isActive = true + NSLayoutConstraint(item: mapView, attribute: .bottom, relatedBy: .equal, toItem: bottomLayoutGuide, attribute: .top, multiplier: 1, constant: 0).isActive = true + + mapViewHeightConstraint = NSLayoutConstraint(item: mapView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 0) + mapViewHeightConstraint.isActive = true + + NSLayoutConstraint(item: pinView, attribute: .centerX, relatedBy: .equal, toItem: mapView, attribute: .centerX, multiplier: 1, constant: 0).isActive = true + pinViewCenterYConstraint = NSLayoutConstraint(item: pinView, attribute: .centerY, relatedBy: .equal, toItem: mapView, attribute: .centerY, multiplier: 1, constant: -pinViewImageHeight / 2) + pinViewCenterYConstraint.isActive = true + } + } + // MARK: Gesture Recognizer - func panGestureInMapViewDidRecognize(sender: UIPanGestureRecognizer) { - switch(sender.state) { - case .Began: - mapViewCenterChanged = true + func panGestureInMapViewDidRecognize(panGestureRecognizer: UIPanGestureRecognizer) { + switch(panGestureRecognizer.state) { + case .began: + isMapViewCenterChanged = true selectedLocationItem = nil geocoder.cancelGeocode() searchBar.text = nil if let indexPathForSelectedRow = tableView.indexPathForSelectedRow { - tableView.deselectRowAtIndexPath(indexPathForSelectedRow, animated: true) + tableView.deselectRow(at: indexPathForSelectedRow, animated: true) } if let doneButtonItem = barButtonItems?.doneButtonItem { - doneButtonItem.enabled = false + doneButtonItem.isEnabled = false } default: break } } - public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } - // MARK: Buttons - func doneButtonDidTap(sender: UIBarButtonItem) { + func doneButtonDidTap(barButtonItem: UIBarButtonItem) { if let locationItem = selectedLocationItem { - dismissViewControllerAnimated(true, completion: nil) - locationDidPick(locationItem) + dismiss(animated: true, completion: nil) + locationDidPick(locationItem: locationItem) } } - func cancelButtonDidTap(sender: UIBarButtonItem) { - dismissViewControllerAnimated(true, completion: nil) + func cancelButtonDidTap(barButtonItem: UIBarButtonItem) { + dismiss(animated: true, completion: nil) } - // MARK: UI Mainipulations - private func showMapViewWithCenterCoordinate(coordinate: CLLocationCoordinate2D, WithDistance distance: Double) { + private func showMapView(withCenter coordinate: CLLocationCoordinate2D, distance: Double) { mapViewHeightConstraint.constant = mapViewHeight let coordinateRegion = MKCoordinateRegionMakeWithDistance(coordinate, 0 , distance) mapView.setRegion(coordinateRegion, animated: true) } - private func closeMapView() { + fileprivate func closeMapView() { mapViewHeightConstraint.constant = 0 } - // MARK: Location Handlers /** @@ -644,20 +646,20 @@ public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { - parameter locationItem: An instance of `LocationItem` */ - public func selectLocationItem(locationItem: LocationItem) { + public func selectLocationItem(_ locationItem: LocationItem) { selectedLocationItem = locationItem searchBar.text = locationItem.name if let coordinate = locationItem.coordinate { - showMapViewWithCenterCoordinate(coordinateObjectFromTuple(coordinate), WithDistance: longitudinalDistance) + showMapView(withCenter: coordinateObject(fromTuple: coordinate), distance: longitudinalDistance) } else { closeMapView() } - barButtonItems?.doneButtonItem.enabled = true - locationDidSelect(locationItem) + barButtonItems?.doneButtonItem.isEnabled = true + locationDidSelect(locationItem: locationItem) } - private func reverseGeocodeLocation(location: CLLocation) { + fileprivate func reverseGeocodeLocation(_ location: CLLocation) { geocoder.cancelGeocode() geocoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in guard error == nil else { @@ -665,13 +667,12 @@ public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { return } guard let placemarks = placemarks else { return } - var placemark = placemarks[0] if !self.isRedirectToExactCoordinate { placemark = MKPlacemark(coordinate: location.coordinate, addressDictionary: placemark.addressDictionary as? [String : NSObject]) } - if !self.searchBar.isFirstResponder() { + if !self.searchBar.isFirstResponder { let mapItem = MKMapItem(placemark: MKPlacemark(placemark: placemark)) self.selectLocationItem(LocationItem(mapItem: mapItem)) } @@ -680,10 +681,11 @@ public class LocationPicker: UIViewController, UIGestureRecognizerDelegate { } + +// MARK: - Callbacks + extension LocationPicker { - // MARK: Callbacks - /** This method would be called everytime user select a location including the change of region of the map view. @@ -717,9 +719,9 @@ extension LocationPicker { - parameter locationItem: The location item user selected */ - public func locationDidSelect(locationItem: LocationItem) { + open func locationDidSelect(locationItem: LocationItem) { selectCompletion?(locationItem) - delegate?.locationDidSelect?(locationItem) + delegate?.locationDidSelect?(locationItem: locationItem) } /** @@ -755,9 +757,9 @@ extension LocationPicker { - parameter locationItem: The location item user picked */ - public func locationDidPick(locationItem: LocationItem) { + open func locationDidPick(locationItem: LocationItem) { pickCompletion?(locationItem) - delegate?.locationDidPick?(locationItem) + delegate?.locationDidPick?(locationItem: locationItem) } /** @@ -791,9 +793,9 @@ extension LocationPicker { - parameter locationItem: The location item needs to be deleted */ - public func alternativeLocationDidDelete(locationItem: LocationItem) { + open func alternativeLocationDidDelete(locationItem: LocationItem) { deleteCompletion?(locationItem) - dataSource?.commitAlternativeLocationDeletion?(locationItem) + dataSource?.commitAlternativeLocationDeletion?(locationItem: locationItem) } /** @@ -831,48 +833,49 @@ extension LocationPicker { */ public func locationDidDeny(locationPicker: LocationPicker) { locationDeniedHandler?(self) - delegate?.locationDidDeny?(self) + delegate?.locationDidDeny?(locationPicker: self) if locationDeniedHandler == nil && delegate?.locationDidDeny == nil { if let alertController = locationDeniedAlertController { - presentViewController(alertController, animated: true, completion: nil) + present(alertController, animated: true, completion: nil) } else { - let alertController = UIAlertController(title: locationDeniedAlertTitle, message: locationDeniedAlertMessage, preferredStyle: .Alert) - alertController.addAction(UIAlertAction(title: locationDeniedGrantText, style: .Default, handler: { (alertAction) in - if let url = NSURL(string: UIApplicationOpenSettingsURLString) { - UIApplication.sharedApplication().openURL(url) + let alertController = UIAlertController(title: locationDeniedAlertTitle, message: locationDeniedAlertMessage, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: locationDeniedGrantText, style: .default, handler: { (alertAction) in + if let url = URL(string: UIApplicationOpenSettingsURLString) { + UIApplication.shared.openURL(url) } })) - alertController.addAction(UIAlertAction(title: locationDeniedCancelText, style: .Cancel, handler: nil)) - presentViewController(alertController, animated: true, completion: nil) + alertController.addAction(UIAlertAction(title: locationDeniedCancelText, style: .cancel, handler: nil)) + present(alertController, animated: true, completion: nil) } } } } + +// MARK: Search Bar Delegate + extension LocationPicker: UISearchBarDelegate { - // MARK: Search Bar Delegate - - public func searchBar(searchBar: UISearchBar, textDidChange searchText: String) { + public func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { if searchText.characters.count > 0 { let localSearchRequest = MKLocalSearchRequest() localSearchRequest.naturalLanguageQuery = searchText if let currentCoordinate = locationManager.location?.coordinate { localSearchRequest.region = MKCoordinateRegionMakeWithDistance(currentCoordinate, searchDistance, searchDistance) - } else if let defaultSearchCoordinate = defaultSearchCoordinate where CLLocationCoordinate2DIsValid(defaultSearchCoordinate) { + } else if let defaultSearchCoordinate = defaultSearchCoordinate, CLLocationCoordinate2DIsValid(defaultSearchCoordinate) { localSearchRequest.region = MKCoordinateRegionMakeWithDistance(defaultSearchCoordinate, searchDistance, searchDistance) } - MKLocalSearch(request: localSearchRequest).startWithCompletionHandler({ (localSearchResponse, error) -> Void in + MKLocalSearch(request: localSearchRequest).start(completionHandler: { (localSearchResponse, error) -> Void in guard searchText == searchBar.text else { // Ensure that the result is valid for the most recent searched text return } guard error == nil, - let localSearchResponse = localSearchResponse where localSearchResponse.mapItems.count > 0 else { - if self.allowArbitraryLocation { + let localSearchResponse = localSearchResponse, localSearchResponse.mapItems.count > 0 else { + if self.isAllowArbitraryLocation { let locationItem = LocationItem(locationName: searchText) self.searchResultLocations = [locationItem] } else { @@ -883,17 +886,17 @@ extension LocationPicker: UISearchBarDelegate { } self.searchResultLocations = localSearchResponse.mapItems.filter({ (mapItem) -> Bool in - return self.shouldShowSearchResult(mapItem) + return self.shouldShowSearchResult(for: mapItem) }).map({ LocationItem(mapItem: $0) }) - if self.allowArbitraryLocation { + if self.isAllowArbitraryLocation { let locationFound = self.searchResultLocations.filter({ - $0.name.lowercaseString == searchText.lowercaseString}).count > 0 + $0.name.lowercased() == searchText.lowercased()}).count > 0 if !locationFound { // Insert arbitrary location without coordinate let locationItem = LocationItem(locationName: searchText) - self.searchResultLocations.insert(locationItem, atIndex: 0) + self.searchResultLocations.insert(locationItem, at: 0) } } @@ -906,45 +909,46 @@ extension LocationPicker: UISearchBarDelegate { closeMapView() if let doneButtonItem = barButtonItems?.doneButtonItem { - doneButtonItem.enabled = false + doneButtonItem.isEnabled = false } } } - public func searchBarSearchButtonClicked(searchBar: UISearchBar) { + public func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { searchBar.endEditing(true) } } + +// MARK: Table View Delegate and Data Source + extension LocationPicker: UITableViewDelegate, UITableViewDataSource { - // MARK: Table View Delegate and Data Source - - public func numberOfSectionsInTableView(tableView: UITableView) -> Int { + public func numberOfSections(in tableView: UITableView) -> Int { return 1 } - public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 + searchResultLocations.count + alternativeLocationCount } - public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { var cell: LocationCell! if indexPath.row == 0 { - cell = LocationCell(locationType: .CurrentLocation, locationItem: nil) + cell = LocationCell(locationType: .currentLocation, locationItem: nil) cell.locationNameLabel.text = currentLocationText - cell.iconView.image = currentLocationIconImage ?? StyleKit.imageOfMapPointerIcon(color: currentLocationIconColor) + cell.iconView.image = currentLocationIcon ?? StyleKit.imageOfMapPointerIcon(color: currentLocationIconColor) } else if indexPath.row > 0 && indexPath.row <= searchResultLocations.count { let index = indexPath.row - 1 - cell = LocationCell(locationType: .SearchLocation, locationItem: searchResultLocations[index]) - cell.iconView.image = searchResultLocationIconImage ?? StyleKit.imageOfSearchIcon(color: searchResultLocationIconColor) + cell = LocationCell(locationType: .searchLocation, locationItem: searchResultLocations[index]) + cell.iconView.image = searchResultLocationIcon ?? StyleKit.imageOfSearchIcon(color: searchResultLocationIconColor) } else if indexPath.row > searchResultLocations.count && indexPath.row <= alternativeLocationCount + searchResultLocations.count { let index = indexPath.row - 1 - searchResultLocations.count - let locationItem = (alternativeLocations?[index] ?? dataSource?.alternativeLocationAtIndex(index))! - cell = LocationCell(locationType: .AlternativeLocation, locationItem: locationItem) - cell.iconView.image = alternativeLocationIconImage ?? StyleKit.imageOfPinIcon(color: alternativeLocationIconColor) + let locationItem = (alternativeLocations?[index] ?? dataSource?.alternativeLocation(at: index))! + cell = LocationCell(locationType: .alternativeLocation, locationItem: locationItem) + cell.iconView.image = alternativeLocationIcon ?? StyleKit.imageOfPinIcon(color: alternativeLocationIconColor) } cell.locationNameLabel.textColor = primaryTextColor cell.locationAddressLabel.textColor = secondaryTextColor @@ -952,17 +956,17 @@ extension LocationPicker: UITableViewDelegate, UITableViewDataSource { return cell } - public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { searchBar.endEditing(true) longitudinalDistance = defaultLongitudinalDistance if indexPath.row == 0 { switch CLLocationManager.authorizationStatus() { - case .NotDetermined: + case .notDetermined: locationManager.requestWhenInUseAuthorization() - case .Denied: - locationDidDeny(self) - tableView.deselectRowAtIndexPath(indexPath, animated: true) + case .denied: + locationDidDeny(locationPicker: self) + tableView.deselectRow(at: indexPath, animated: true) default: break @@ -972,10 +976,10 @@ extension LocationPicker: UITableViewDelegate, UITableViewDataSource { reverseGeocodeLocation(currentLocation) } } else { - let cell = tableView.cellForRowAtIndexPath(indexPath) as! LocationCell + let cell = tableView.cellForRow(at: indexPath) as! LocationCell let locationItem = cell.locationItem! let coordinate = locationItem.coordinate - if (coordinate != nil && self.forceReverseGeocoding) { + if (coordinate != nil && self.isForceReverseGeocoding) { reverseGeocodeLocation(CLLocation(latitude: coordinate!.latitude, longitude: coordinate!.longitude)) } else { selectLocationItem(locationItem) @@ -984,52 +988,53 @@ extension LocationPicker: UITableViewDelegate, UITableViewDataSource { } - public func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { - return alternativeLocationEditable && indexPath.row > searchResultLocations.count && indexPath.row <= alternativeLocationCount + searchResultLocations.count + public func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + return isAlternativeLocationEditable && indexPath.row > searchResultLocations.count && indexPath.row <= alternativeLocationCount + searchResultLocations.count } - public func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { - if editingStyle == .Delete { - let cell = tableView.cellForRowAtIndexPath(indexPath) as! LocationCell + public func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + let cell = tableView.cellForRow(at: indexPath) as! LocationCell let locationItem = cell.locationItem! let index = indexPath.row - 1 - searchResultLocations.count - alternativeLocations?.removeAtIndex(index) + alternativeLocations?.remove(at: index) - alternativeLocationDidDelete(locationItem) + alternativeLocationDidDelete(locationItem: locationItem) - tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) + tableView.deleteRows(at: [indexPath], with: .automatic) } } } + +// MARK: Map View Delegate + extension LocationPicker: MKMapViewDelegate { - // MARK: Map View Delegate - - public func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) { + public func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) { if !animated { - UIView.animateWithDuration(0.35, delay: 0, options: .CurveEaseOut, animations: { + UIView.animate(withDuration: 0.35, delay: 0, options: .curveEaseOut, animations: { self.pinView.frame.origin.y -= self.pinViewImageHeight / 2 }, completion: nil) } } - public func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) { - longitudinalDistance = longitudinalDistanceFromMapRect(mapView.visibleMapRect) - if mapViewCenterChanged { - mapViewCenterChanged = false + public func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) { + longitudinalDistance = getLongitudinalDistance(fromMapRect: mapView.visibleMapRect) + if isMapViewCenterChanged { + isMapViewCenterChanged = false if #available(iOS 10, *) { let coordinate = mapView.centerCoordinate reverseGeocodeLocation(CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)) } else { - let adjustedCoordinate = gcj2wgs(mapView.centerCoordinate) + let adjustedCoordinate = gcjToWgs(coordinate: mapView.centerCoordinate) reverseGeocodeLocation(CLLocation(latitude: adjustedCoordinate.latitude, longitude: adjustedCoordinate.longitude)) } } if !animated { - UIView.animateWithDuration(0.35, delay: 0, options: .CurveEaseOut, animations: { + UIView.animate(withDuration: 0.35, delay: 0, options: .curveEaseOut, animations: { self.pinView.frame.origin.y += self.pinViewImageHeight / 2 }, completion: nil) } @@ -1037,21 +1042,22 @@ extension LocationPicker: MKMapViewDelegate { } + +// MARK: Location Manager Delegate + extension LocationPicker: CLLocationManagerDelegate { - // MARK: Location Manager Delegate - - public func locationManager(manager: CLLocationManager, didFailWithError error: NSError) { + public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { print(error) } - public func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { - if tableView.indexPathForSelectedRow?.row == 0 { + public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + if (tableView.indexPathForSelectedRow as NSIndexPath?)?.row == 0 { let currentLocation = locations[0] reverseGeocodeLocation(currentLocation) - if #available(iOS 9.0, *) { - } else { + guard #available(iOS 9.0, *) else { locationManager.stopUpdatingLocation() + return } } } diff --git a/LocationPicker/Protocol.swift b/LocationPicker/Protocol.swift index 1a25cf8..a80b96d 100644 --- a/LocationPicker/Protocol.swift +++ b/LocationPicker/Protocol.swift @@ -57,7 +57,7 @@ import Foundation - parameter locationItem: The location item user selected */ - optional func locationDidSelect(locationItem: LocationItem) + @objc optional func locationDidSelect(locationItem: LocationItem) /** This delegate method would be called after user finally pick a location. @@ -83,7 +83,7 @@ import Foundation - parameter locationItem: The location item user picked */ - optional func locationDidPick(locationItem: LocationItem) + @objc optional func locationDidPick(locationItem: LocationItem) /** This delegate method would be called when user try to fetch current location without granting location access. @@ -109,7 +109,7 @@ import Foundation - parameter locationPicker `LocationPicker` instance that needs to response to user's location request */ - optional func locationDidDeny(locationPicker: LocationPicker) + @objc optional func locationDidDeny(locationPicker: LocationPicker) } @@ -129,7 +129,7 @@ import Foundation - returns: The location item in the specific index */ - func alternativeLocationAtIndex(index: Int) -> LocationItem + func alternativeLocation(at index: Int) -> LocationItem /** This delegate method would be called after user delete an alternative location. @@ -153,6 +153,6 @@ import Foundation - parameter locationItem: The location item needs to be deleted */ - optional func commitAlternativeLocationDeletion(locationItem: LocationItem) + @objc optional func commitAlternativeLocationDeletion(locationItem: LocationItem) -} \ No newline at end of file +} diff --git a/LocationPicker/StyleKit.swift b/LocationPicker/StyleKit.swift index 740f9f6..2653819 100644 --- a/LocationPicker/StyleKit.swift +++ b/LocationPicker/StyleKit.swift @@ -16,234 +16,234 @@ class StyleKit: NSObject { /// Page 1 - class func drawMapPointerIcon(frame frame: CGRect = CGRect(x: 0, y: 0, width: 44, height: 44), resizing: ResizingBehavior = .AspectFit, color: UIColor = UIColor.blackColor()) { + class func drawMapPointerIcon(frame: CGRect = CGRect(x: 0, y: 0, width: 44, height: 44), resizing: ResizingBehavior = .aspectFit, color: UIColor = UIColor.black) { /// General Declarations let context = UIGraphicsGetCurrentContext()! /// Resize To Frame - CGContextSaveGState(context) + context.saveGState() let resizedFrame = resizing.apply(rect: CGRect(x: 0, y: 0, width: 44, height: 44), target: frame) - CGContextTranslateCTM(context, resizedFrame.minX, resizedFrame.minY) + context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY) let resizedScale = CGSize(width: resizedFrame.width / 44, height: resizedFrame.height / 44) - CGContextScaleCTM(context, resizedScale.width, resizedScale.height) + context.scaleBy(x: resizedScale.width, y: resizedScale.height) /// v_u_map_pointer do { - CGContextSaveGState(context) - CGContextTranslateCTM(context, 12, 12) + context.saveGState() + context.translateBy(x: 12, y: 12) /// Capa_1 do { - CGContextSaveGState(context) + context.saveGState() /// Shape let shape = UIBezierPath() - shape.moveToPoint(CGPoint(x: 19.15, y: 0.05)) - shape.addLineToPoint(CGPoint(x: 0.34, y: 8.7)) - shape.addCurveToPoint(CGPoint(x: 0, y: 9.25), controlPoint1: CGPoint(x: 0.12, y: 8.8), controlPoint2: CGPoint(x: -0.01, y: 9.02)) - shape.addCurveToPoint(CGPoint(x: 0.39, y: 9.77), controlPoint1: CGPoint(x: 0.01, y: 9.49), controlPoint2: CGPoint(x: 0.17, y: 9.69)) - shape.addLineToPoint(CGPoint(x: 6.17, y: 11.74)) - shape.addCurveToPoint(CGPoint(x: 8.2, y: 13.77), controlPoint1: CGPoint(x: 7.13, y: 12.07), controlPoint2: CGPoint(x: 7.87, y: 12.82)) - shape.addLineToPoint(CGPoint(x: 10.18, y: 19.54)) - shape.addCurveToPoint(CGPoint(x: 10.7, y: 19.93), controlPoint1: CGPoint(x: 10.26, y: 19.76), controlPoint2: CGPoint(x: 10.46, y: 19.91)) - shape.addCurveToPoint(CGPoint(x: 11.25, y: 19.59), controlPoint1: CGPoint(x: 10.94, y: 19.94), controlPoint2: CGPoint(x: 11.16, y: 19.8)) - shape.addLineToPoint(CGPoint(x: 19.92, y: 0.82)) - shape.addCurveToPoint(CGPoint(x: 19.8, y: 0.17), controlPoint1: CGPoint(x: 20.02, y: 0.6), controlPoint2: CGPoint(x: 19.97, y: 0.34)) - shape.addCurveToPoint(CGPoint(x: 19.15, y: 0.05), controlPoint1: CGPoint(x: 19.63, y: -0), controlPoint2: CGPoint(x: 19.37, y: -0.05)) - shape.closePath() - shape.moveToPoint(CGPoint(x: 19.15, y: 0.05)) - CGContextSaveGState(context) - CGContextTranslateCTM(context, 0, 0.04) + shape.move(to: CGPoint(x: 19.15, y: 0.05)) + shape.addLine(to: CGPoint(x: 0.34, y: 8.7)) + shape.addCurve(to: CGPoint(x: 0, y: 9.25), controlPoint1: CGPoint(x: 0.12, y: 8.8), controlPoint2: CGPoint(x: -0.01, y: 9.02)) + shape.addCurve(to: CGPoint(x: 0.39, y: 9.77), controlPoint1: CGPoint(x: 0.01, y: 9.49), controlPoint2: CGPoint(x: 0.17, y: 9.69)) + shape.addLine(to: CGPoint(x: 6.17, y: 11.74)) + shape.addCurve(to: CGPoint(x: 8.2, y: 13.77), controlPoint1: CGPoint(x: 7.13, y: 12.07), controlPoint2: CGPoint(x: 7.87, y: 12.82)) + shape.addLine(to: CGPoint(x: 10.18, y: 19.54)) + shape.addCurve(to: CGPoint(x: 10.7, y: 19.93), controlPoint1: CGPoint(x: 10.26, y: 19.76), controlPoint2: CGPoint(x: 10.46, y: 19.91)) + shape.addCurve(to: CGPoint(x: 11.25, y: 19.59), controlPoint1: CGPoint(x: 10.94, y: 19.94), controlPoint2: CGPoint(x: 11.16, y: 19.8)) + shape.addLine(to: CGPoint(x: 19.92, y: 0.82)) + shape.addCurve(to: CGPoint(x: 19.8, y: 0.17), controlPoint1: CGPoint(x: 20.02, y: 0.6), controlPoint2: CGPoint(x: 19.97, y: 0.34)) + shape.addCurve(to: CGPoint(x: 19.15, y: 0.05), controlPoint1: CGPoint(x: 19.63, y: -0), controlPoint2: CGPoint(x: 19.37, y: -0.05)) + shape.close() + shape.move(to: CGPoint(x: 19.15, y: 0.05)) + context.saveGState() + context.translateBy(x: 0, y: 0.04) shape.lineWidth = 2 color.setStroke() shape.stroke() - CGContextRestoreGState(context) + context.restoreGState() - CGContextRestoreGState(context) + context.restoreGState() } - CGContextRestoreGState(context) + context.restoreGState() } - CGContextRestoreGState(context) + context.restoreGState() } - class func drawSearchIcon(frame frame: CGRect = CGRect(x: 0, y: 0, width: 44, height: 44), resizing: ResizingBehavior = .AspectFit, color: UIColor = UIColor.blackColor()) { + class func drawSearchIcon(frame: CGRect = CGRect(x: 0, y: 0, width: 44, height: 44), resizing: ResizingBehavior = .aspectFit, color: UIColor = UIColor.black) { /// General Declarations let context = UIGraphicsGetCurrentContext()! /// Resize To Frame - CGContextSaveGState(context) + context.saveGState() let resizedFrame = resizing.apply(rect: CGRect(x: 0, y: 0, width: 44, height: 44), target: frame) - CGContextTranslateCTM(context, resizedFrame.minX, resizedFrame.minY) + context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY) let resizedScale = CGSize(width: resizedFrame.width / 44, height: resizedFrame.height / 44) - CGContextScaleCTM(context, resizedScale.width, resizedScale.height) + context.scaleBy(x: resizedScale.width, y: resizedScale.height) /// Group 2 do { - CGContextSaveGState(context) - CGContextTranslateCTM(context, 18.68, 24.68) - CGContextRotateCTM(context, 45 * CGFloat(M_PI/180)) - CGContextTranslateCTM(context, -10, -15) + context.saveGState() + context.translateBy(x: 18.68, y: 24.68) + context.rotate(by: 45 * CGFloat(M_PI/180)) + context.translateBy(x: -10, y: -15) /// Oval 167 - let oval167 = UIBezierPath(ovalInRect: CGRect(x: 0, y: 0, width: 8, height: 8)) - CGContextSaveGState(context) - CGContextTranslateCTM(context, 6, 6) + let oval167 = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 8, height: 8)) + context.saveGState() + context.translateBy(x: 6, y: 6) oval167.lineWidth = 2 color.setStroke() oval167.stroke() - CGContextRestoreGState(context) + context.restoreGState() /// Oval 166 let oval166 = UIBezierPath() - oval166.moveToPoint(CGPoint(x: 6.03, y: 19.18)) - oval166.addCurveToPoint(CGPoint(x: 7, y: 19.93), controlPoint1: CGPoint(x: 6.35, y: 19.32), controlPoint2: CGPoint(x: 6.99, y: 19.38)) - oval166.addCurveToPoint(CGPoint(x: 7, y: 27), controlPoint1: CGPoint(x: 7.01, y: 20.47), controlPoint2: CGPoint(x: 7, y: 27)) - oval166.addCurveToPoint(CGPoint(x: 10, y: 30), controlPoint1: CGPoint(x: 7, y: 28), controlPoint2: CGPoint(x: 8, y: 30)) - oval166.addCurveToPoint(CGPoint(x: 13, y: 27), controlPoint1: CGPoint(x: 12, y: 30), controlPoint2: CGPoint(x: 13, y: 28)) - oval166.addLineToPoint(CGPoint(x: 13, y: 20)) - oval166.addCurveToPoint(CGPoint(x: 14.02, y: 19.16), controlPoint1: CGPoint(x: 13, y: 19.38), controlPoint2: CGPoint(x: 13.65, y: 19.32)) - oval166.addCurveToPoint(CGPoint(x: 20, y: 10), controlPoint1: CGPoint(x: 17.55, y: 17.6), controlPoint2: CGPoint(x: 20, y: 14.09)) - oval166.addCurveToPoint(CGPoint(x: 10, y: 0), controlPoint1: CGPoint(x: 20, y: 4.48), controlPoint2: CGPoint(x: 15.52, y: 0)) - oval166.addCurveToPoint(CGPoint(x: 0, y: 10), controlPoint1: CGPoint(x: 4.48, y: 0), controlPoint2: CGPoint(x: 0, y: 4.48)) - oval166.addCurveToPoint(CGPoint(x: 6.03, y: 19.18), controlPoint1: CGPoint(x: 0, y: 14.11), controlPoint2: CGPoint(x: 2.48, y: 17.64)) - oval166.closePath() - oval166.moveToPoint(CGPoint(x: 6.03, y: 19.18)) - CGContextSaveGState(context) + oval166.move(to: CGPoint(x: 6.03, y: 19.18)) + oval166.addCurve(to: CGPoint(x: 7, y: 19.93), controlPoint1: CGPoint(x: 6.35, y: 19.32), controlPoint2: CGPoint(x: 6.99, y: 19.38)) + oval166.addCurve(to: CGPoint(x: 7, y: 27), controlPoint1: CGPoint(x: 7.01, y: 20.47), controlPoint2: CGPoint(x: 7, y: 27)) + oval166.addCurve(to: CGPoint(x: 10, y: 30), controlPoint1: CGPoint(x: 7, y: 28), controlPoint2: CGPoint(x: 8, y: 30)) + oval166.addCurve(to: CGPoint(x: 13, y: 27), controlPoint1: CGPoint(x: 12, y: 30), controlPoint2: CGPoint(x: 13, y: 28)) + oval166.addLine(to: CGPoint(x: 13, y: 20)) + oval166.addCurve(to: CGPoint(x: 14.02, y: 19.16), controlPoint1: CGPoint(x: 13, y: 19.38), controlPoint2: CGPoint(x: 13.65, y: 19.32)) + oval166.addCurve(to: CGPoint(x: 20, y: 10), controlPoint1: CGPoint(x: 17.55, y: 17.6), controlPoint2: CGPoint(x: 20, y: 14.09)) + oval166.addCurve(to: CGPoint(x: 10, y: 0), controlPoint1: CGPoint(x: 20, y: 4.48), controlPoint2: CGPoint(x: 15.52, y: 0)) + oval166.addCurve(to: CGPoint(x: 0, y: 10), controlPoint1: CGPoint(x: 4.48, y: 0), controlPoint2: CGPoint(x: 0, y: 4.48)) + oval166.addCurve(to: CGPoint(x: 6.03, y: 19.18), controlPoint1: CGPoint(x: 0, y: 14.11), controlPoint2: CGPoint(x: 2.48, y: 17.64)) + oval166.close() + oval166.move(to: CGPoint(x: 6.03, y: 19.18)) + context.saveGState() oval166.lineWidth = 2 color.setStroke() oval166.stroke() - CGContextRestoreGState(context) + context.restoreGState() - CGContextRestoreGState(context) + context.restoreGState() } - CGContextRestoreGState(context) + context.restoreGState() } - class func drawPinIcon(frame frame: CGRect = CGRect(x: 0, y: 0, width: 44, height: 44), resizing: ResizingBehavior = .AspectFit, color: UIColor = UIColor.blackColor()) { + class func drawPinIcon(frame: CGRect = CGRect(x: 0, y: 0, width: 44, height: 44), resizing: ResizingBehavior = .aspectFit, color: UIColor = UIColor.black) { /// General Declarations let context = UIGraphicsGetCurrentContext()! /// Resize To Frame - CGContextSaveGState(context) + context.saveGState() let resizedFrame = resizing.apply(rect: CGRect(x: 0, y: 0, width: 44, height: 44), target: frame) - CGContextTranslateCTM(context, resizedFrame.minX, resizedFrame.minY) + context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY) let resizedScale = CGSize(width: resizedFrame.width / 44, height: resizedFrame.height / 44) - CGContextScaleCTM(context, resizedScale.width, resizedScale.height) + context.scaleBy(x: resizedScale.width, y: resizedScale.height) /// v_u_icon_pin do { - CGContextSaveGState(context) - CGContextTranslateCTM(context, 12, 6) + context.saveGState() + context.translateBy(x: 12, y: 6) /// Layer_1 do { - CGContextSaveGState(context) - CGContextTranslateCTM(context, 1, 0) + context.saveGState() + context.translateBy(x: 1, y: 0) // Empty. - CGContextRestoreGState(context) + context.restoreGState() } /// map_x5F_pin_x5F_fill do { - CGContextSaveGState(context) + context.saveGState() /// Shape let shape = UIBezierPath() - shape.moveToPoint(CGPoint(x: 2.93, y: 2.93)) - shape.addCurveToPoint(CGPoint(x: 2.93, y: 17.07), controlPoint1: CGPoint(x: -0.98, y: 6.83), controlPoint2: CGPoint(x: -0.98, y: 13.17)) - shape.addCurveToPoint(CGPoint(x: 10, y: 32), controlPoint1: CGPoint(x: 2.93, y: 17.07), controlPoint2: CGPoint(x: 10, y: 24)) - shape.addCurveToPoint(CGPoint(x: 17.07, y: 17.07), controlPoint1: CGPoint(x: 10, y: 24), controlPoint2: CGPoint(x: 17.07, y: 17.07)) - shape.addCurveToPoint(CGPoint(x: 17.07, y: 2.93), controlPoint1: CGPoint(x: 20.98, y: 13.17), controlPoint2: CGPoint(x: 20.98, y: 6.83)) - shape.addCurveToPoint(CGPoint(x: 2.93, y: 2.93), controlPoint1: CGPoint(x: 13.16, y: -0.98), controlPoint2: CGPoint(x: 6.84, y: -0.98)) - shape.closePath() - shape.moveToPoint(CGPoint(x: 10, y: 14.01)) - shape.addCurveToPoint(CGPoint(x: 6, y: 10.01), controlPoint1: CGPoint(x: 7.79, y: 14.01), controlPoint2: CGPoint(x: 6, y: 12.22)) - shape.addCurveToPoint(CGPoint(x: 10, y: 6.01), controlPoint1: CGPoint(x: 6, y: 7.79), controlPoint2: CGPoint(x: 7.79, y: 6.01)) - shape.addCurveToPoint(CGPoint(x: 14, y: 10.01), controlPoint1: CGPoint(x: 12.21, y: 6.01), controlPoint2: CGPoint(x: 14, y: 7.79)) - shape.addCurveToPoint(CGPoint(x: 10, y: 14.01), controlPoint1: CGPoint(x: 14, y: 12.22), controlPoint2: CGPoint(x: 12.21, y: 14.01)) - shape.addLineToPoint(CGPoint(x: 10, y: 14.01)) - shape.closePath() - shape.moveToPoint(CGPoint(x: 10, y: 14.01)) - CGContextSaveGState(context) + shape.move(to: CGPoint(x: 2.93, y: 2.93)) + shape.addCurve(to: CGPoint(x: 2.93, y: 17.07), controlPoint1: CGPoint(x: -0.98, y: 6.83), controlPoint2: CGPoint(x: -0.98, y: 13.17)) + shape.addCurve(to: CGPoint(x: 10, y: 32), controlPoint1: CGPoint(x: 2.93, y: 17.07), controlPoint2: CGPoint(x: 10, y: 24)) + shape.addCurve(to: CGPoint(x: 17.07, y: 17.07), controlPoint1: CGPoint(x: 10, y: 24), controlPoint2: CGPoint(x: 17.07, y: 17.07)) + shape.addCurve(to: CGPoint(x: 17.07, y: 2.93), controlPoint1: CGPoint(x: 20.98, y: 13.17), controlPoint2: CGPoint(x: 20.98, y: 6.83)) + shape.addCurve(to: CGPoint(x: 2.93, y: 2.93), controlPoint1: CGPoint(x: 13.16, y: -0.98), controlPoint2: CGPoint(x: 6.84, y: -0.98)) + shape.close() + shape.move(to: CGPoint(x: 10, y: 14.01)) + shape.addCurve(to: CGPoint(x: 6, y: 10.01), controlPoint1: CGPoint(x: 7.79, y: 14.01), controlPoint2: CGPoint(x: 6, y: 12.22)) + shape.addCurve(to: CGPoint(x: 10, y: 6.01), controlPoint1: CGPoint(x: 6, y: 7.79), controlPoint2: CGPoint(x: 7.79, y: 6.01)) + shape.addCurve(to: CGPoint(x: 14, y: 10.01), controlPoint1: CGPoint(x: 12.21, y: 6.01), controlPoint2: CGPoint(x: 14, y: 7.79)) + shape.addCurve(to: CGPoint(x: 10, y: 14.01), controlPoint1: CGPoint(x: 14, y: 12.22), controlPoint2: CGPoint(x: 12.21, y: 14.01)) + shape.addLine(to: CGPoint(x: 10, y: 14.01)) + shape.close() + shape.move(to: CGPoint(x: 10, y: 14.01)) + context.saveGState() shape.lineWidth = 2 color.setStroke() shape.stroke() - CGContextRestoreGState(context) + context.restoreGState() - CGContextRestoreGState(context) + context.restoreGState() } - CGContextRestoreGState(context) + context.restoreGState() } - CGContextRestoreGState(context) + context.restoreGState() } - class func drawPinIconFilled(frame frame: CGRect = CGRect(x: 0, y: 0, width: 20, height: 32), resizing: ResizingBehavior = .AspectFit, color: UIColor = UIColor.blackColor()) { + class func drawPinIconFilled(frame: CGRect = CGRect(x: 0, y: 0, width: 20, height: 32), resizing: ResizingBehavior = .aspectFit, color: UIColor = UIColor.black) { /// General Declarations let context = UIGraphicsGetCurrentContext()! /// Resize To Frame - CGContextSaveGState(context) + context.saveGState() let resizedFrame = resizing.apply(rect: CGRect(x: 0, y: 0, width: 20, height: 32), target: frame) - CGContextTranslateCTM(context, resizedFrame.minX, resizedFrame.minY) + context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY) let resizedScale = CGSize(width: resizedFrame.width / 20, height: resizedFrame.height / 32) - CGContextScaleCTM(context, resizedScale.width, resizedScale.height) + context.scaleBy(x: resizedScale.width, y: resizedScale.height) /// v_u_icon_pin do { - CGContextSaveGState(context) + context.saveGState() /// Layer_1 do { - CGContextSaveGState(context) - CGContextTranslateCTM(context, 1, 0) + context.saveGState() + context.translateBy(x: 1, y: 0) // Empty. - CGContextRestoreGState(context) + context.restoreGState() } /// map_x5F_pin_x5F_fill do { - CGContextSaveGState(context) + context.saveGState() /// Shape let shape = UIBezierPath() - shape.moveToPoint(CGPoint(x: 17.07, y: 2.93)) - shape.addCurveToPoint(CGPoint(x: 2.93, y: 2.93), controlPoint1: CGPoint(x: 13.16, y: -0.98), controlPoint2: CGPoint(x: 6.84, y: -0.98)) - shape.addCurveToPoint(CGPoint(x: 2.93, y: 17.07), controlPoint1: CGPoint(x: -0.98, y: 6.83), controlPoint2: CGPoint(x: -0.98, y: 13.17)) - shape.addCurveToPoint(CGPoint(x: 10, y: 32), controlPoint1: CGPoint(x: 2.93, y: 17.07), controlPoint2: CGPoint(x: 10, y: 24)) - shape.addCurveToPoint(CGPoint(x: 17.07, y: 17.07), controlPoint1: CGPoint(x: 10, y: 24), controlPoint2: CGPoint(x: 17.07, y: 17.07)) - shape.addCurveToPoint(CGPoint(x: 17.07, y: 2.93), controlPoint1: CGPoint(x: 20.98, y: 13.17), controlPoint2: CGPoint(x: 20.98, y: 6.83)) - shape.addLineToPoint(CGPoint(x: 17.07, y: 2.93)) - shape.closePath() - shape.moveToPoint(CGPoint(x: 10, y: 14.01)) - shape.addCurveToPoint(CGPoint(x: 6, y: 10.01), controlPoint1: CGPoint(x: 7.79, y: 14.01), controlPoint2: CGPoint(x: 6, y: 12.22)) - shape.addCurveToPoint(CGPoint(x: 10, y: 6.01), controlPoint1: CGPoint(x: 6, y: 7.79), controlPoint2: CGPoint(x: 7.79, y: 6.01)) - shape.addCurveToPoint(CGPoint(x: 14, y: 10.01), controlPoint1: CGPoint(x: 12.21, y: 6.01), controlPoint2: CGPoint(x: 14, y: 7.79)) - shape.addCurveToPoint(CGPoint(x: 10, y: 14.01), controlPoint1: CGPoint(x: 14, y: 12.22), controlPoint2: CGPoint(x: 12.21, y: 14.01)) - shape.addLineToPoint(CGPoint(x: 10, y: 14.01)) - shape.closePath() - shape.moveToPoint(CGPoint(x: 10, y: 14.01)) - CGContextSaveGState(context) + shape.move(to: CGPoint(x: 17.07, y: 2.93)) + shape.addCurve(to: CGPoint(x: 2.93, y: 2.93), controlPoint1: CGPoint(x: 13.16, y: -0.98), controlPoint2: CGPoint(x: 6.84, y: -0.98)) + shape.addCurve(to: CGPoint(x: 2.93, y: 17.07), controlPoint1: CGPoint(x: -0.98, y: 6.83), controlPoint2: CGPoint(x: -0.98, y: 13.17)) + shape.addCurve(to: CGPoint(x: 10, y: 32), controlPoint1: CGPoint(x: 2.93, y: 17.07), controlPoint2: CGPoint(x: 10, y: 24)) + shape.addCurve(to: CGPoint(x: 17.07, y: 17.07), controlPoint1: CGPoint(x: 10, y: 24), controlPoint2: CGPoint(x: 17.07, y: 17.07)) + shape.addCurve(to: CGPoint(x: 17.07, y: 2.93), controlPoint1: CGPoint(x: 20.98, y: 13.17), controlPoint2: CGPoint(x: 20.98, y: 6.83)) + shape.addLine(to: CGPoint(x: 17.07, y: 2.93)) + shape.close() + shape.move(to: CGPoint(x: 10, y: 14.01)) + shape.addCurve(to: CGPoint(x: 6, y: 10.01), controlPoint1: CGPoint(x: 7.79, y: 14.01), controlPoint2: CGPoint(x: 6, y: 12.22)) + shape.addCurve(to: CGPoint(x: 10, y: 6.01), controlPoint1: CGPoint(x: 6, y: 7.79), controlPoint2: CGPoint(x: 7.79, y: 6.01)) + shape.addCurve(to: CGPoint(x: 14, y: 10.01), controlPoint1: CGPoint(x: 12.21, y: 6.01), controlPoint2: CGPoint(x: 14, y: 7.79)) + shape.addCurve(to: CGPoint(x: 10, y: 14.01), controlPoint1: CGPoint(x: 14, y: 12.22), controlPoint2: CGPoint(x: 12.21, y: 14.01)) + shape.addLine(to: CGPoint(x: 10, y: 14.01)) + shape.close() + shape.move(to: CGPoint(x: 10, y: 14.01)) + context.saveGState() shape.usesEvenOddFillRule = true color.setFill() shape.fill() - CGContextRestoreGState(context) + context.restoreGState() - CGContextRestoreGState(context) + context.restoreGState() } - CGContextRestoreGState(context) + context.restoreGState() } - CGContextRestoreGState(context) + context.restoreGState() } @@ -251,7 +251,7 @@ class StyleKit: NSObject { /// Page 1 - class func imageOfMapPointerIcon(size size: CGSize = CGSize(width: 44, height: 44), resizing: ResizingBehavior = .AspectFit, color: UIColor = UIColor.blackColor()) -> UIImage { + class func imageOfMapPointerIcon(size: CGSize = CGSize(width: 44, height: 44), resizing: ResizingBehavior = .aspectFit, color: UIColor = UIColor.black) -> UIImage { var image: UIImage UIGraphicsBeginImageContextWithOptions(size, false, 0) @@ -262,7 +262,7 @@ class StyleKit: NSObject { return image } - class func imageOfSearchIcon(size size: CGSize = CGSize(width: 44, height: 44), resizing: ResizingBehavior = .AspectFit, color: UIColor = UIColor.blackColor()) -> UIImage { + class func imageOfSearchIcon(size: CGSize = CGSize(width: 44, height: 44), resizing: ResizingBehavior = .aspectFit, color: UIColor = UIColor.black) -> UIImage { var image: UIImage UIGraphicsBeginImageContextWithOptions(size, false, 0) @@ -273,7 +273,7 @@ class StyleKit: NSObject { return image } - class func imageOfPinIcon(size size: CGSize = CGSize(width: 44, height: 44), resizing: ResizingBehavior = .AspectFit, color: UIColor = UIColor.blackColor()) -> UIImage { + class func imageOfPinIcon(size: CGSize = CGSize(width: 44, height: 44), resizing: ResizingBehavior = .aspectFit, color: UIColor = UIColor.black) -> UIImage { var image: UIImage UIGraphicsBeginImageContextWithOptions(size, false, 0) @@ -284,7 +284,7 @@ class StyleKit: NSObject { return image } - class func imageOfPinIconFilled(size size: CGSize = CGSize(width: 20, height: 32), resizing: ResizingBehavior = .AspectFit, color: UIColor = UIColor.blackColor()) -> UIImage { + class func imageOfPinIconFilled(size: CGSize = CGSize(width: 20, height: 32), resizing: ResizingBehavior = .aspectFit, color: UIColor = UIColor.black) -> UIImage { var image: UIImage UIGraphicsBeginImageContextWithOptions(size, false, 0) @@ -299,12 +299,12 @@ class StyleKit: NSObject { //MARK: - Resizing Behavior enum ResizingBehavior { - case AspectFit /// The content is proportionally resized to fit into the target rectangle. - case AspectFill /// The content is proportionally resized to completely fill the target rectangle. - case Stretch /// The content is stretched to match the entire target rectangle. - case Center /// The content is centered in the target rectangle, but it is NOT resized. + case aspectFit /// The content is proportionally resized to fit into the target rectangle. + case aspectFill /// The content is proportionally resized to completely fill the target rectangle. + case stretch /// The content is stretched to match the entire target rectangle. + case center /// The content is centered in the target rectangle, but it is NOT resized. - func apply(rect rect: CGRect, target: CGRect) -> CGRect { + func apply(rect: CGRect, target: CGRect) -> CGRect { if rect == target || target == CGRect.zero { return rect } @@ -314,15 +314,15 @@ class StyleKit: NSObject { scales.height = abs(target.height / rect.height) switch self { - case .AspectFit: + case .aspectFit: scales.width = min(scales.width, scales.height) scales.height = scales.width - case .AspectFill: + case .aspectFill: scales.width = max(scales.width, scales.height) scales.height = scales.width - case .Stretch: + case .stretch: break - case .Center: + case .center: scales.width = 1 scales.height = 1 } diff --git a/LocationPickerDemo/LocationPickerDemo.xcodeproj/project.pbxproj b/LocationPickerDemo/LocationPickerDemo.xcodeproj/project.pbxproj index 5c0df33..9e5f7f8 100644 --- a/LocationPickerDemo/LocationPickerDemo.xcodeproj/project.pbxproj +++ b/LocationPickerDemo/LocationPickerDemo.xcodeproj/project.pbxproj @@ -7,16 +7,32 @@ objects = { /* Begin PBXBuildFile section */ + 0228C14F1D5440FA00C05C9E /* LocationPicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0228C14E1D5440FA00C05C9E /* LocationPicker.framework */; }; + 0228C1501D5440FA00C05C9E /* LocationPicker.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0228C14E1D5440FA00C05C9E /* LocationPicker.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 022E3F6E1CB11C87006BF665 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022E3F6D1CB11C87006BF665 /* AppDelegate.swift */; }; 022E3F701CB11C87006BF665 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022E3F6F1CB11C87006BF665 /* ViewController.swift */; }; 022E3F731CB11C87006BF665 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 022E3F711CB11C87006BF665 /* Main.storyboard */; }; 022E3F751CB11C87006BF665 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 022E3F741CB11C87006BF665 /* Assets.xcassets */; }; 022E3F781CB11C87006BF665 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 022E3F761CB11C87006BF665 /* LaunchScreen.storyboard */; }; 022E3FAF1CB11D21006BF665 /* CustomLocationPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022E3FAE1CB11D21006BF665 /* CustomLocationPicker.swift */; }; - 028D87681D16213200F3AE0F /* LocationPicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 028D87671D16213200F3AE0F /* LocationPicker.framework */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + 0228C1511D5440FB00C05C9E /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 0228C1501D5440FA00C05C9E /* LocationPicker.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ + 0228C14E1D5440FA00C05C9E /* LocationPicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LocationPicker.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 022E3F6A1CB11C87006BF665 /* LocationPickerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LocationPickerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 022E3F6D1CB11C87006BF665 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 022E3F6F1CB11C87006BF665 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -25,7 +41,6 @@ 022E3F771CB11C87006BF665 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 022E3F791CB11C87006BF665 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 022E3FAE1CB11D21006BF665 /* CustomLocationPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomLocationPicker.swift; sourceTree = ""; }; - 028D87671D16213200F3AE0F /* LocationPicker.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LocationPicker.framework; path = "../Debug-iphonesimulator/LocationPicker.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -33,7 +48,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 028D87681D16213200F3AE0F /* LocationPicker.framework in Frameworks */, + 0228C14F1D5440FA00C05C9E /* LocationPicker.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -43,7 +58,7 @@ 022E3F611CB11C87006BF665 = { isa = PBXGroup; children = ( - 028D87671D16213200F3AE0F /* LocationPicker.framework */, + 0228C14E1D5440FA00C05C9E /* LocationPicker.framework */, 022E3F6C1CB11C87006BF665 /* LocationPickerDemo */, 022E3F6B1CB11C87006BF665 /* Products */, ); @@ -81,6 +96,7 @@ 022E3F661CB11C87006BF665 /* Sources */, 022E3F671CB11C87006BF665 /* Frameworks */, 022E3F681CB11C87006BF665 /* Resources */, + 0228C1511D5440FB00C05C9E /* Embed Frameworks */, ); buildRules = ( ); @@ -98,7 +114,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Jerome Tan"; TargetAttributes = { 022E3F691CB11C87006BF665 = { @@ -187,8 +203,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"; @@ -232,8 +250,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"; @@ -269,7 +289,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = JeromeTan.LocationPickerDemo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -287,7 +307,7 @@ PRODUCT_BUNDLE_IDENTIFIER = JeromeTan.LocationPickerDemo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/LocationPickerDemo/LocationPickerDemo.xcodeproj/xcshareddata/xcschemes/LocationPickerDemo.xcscheme b/LocationPickerDemo/LocationPickerDemo.xcodeproj/xcshareddata/xcschemes/LocationPickerDemo.xcscheme index f6e050d..cf7f77e 100644 --- a/LocationPickerDemo/LocationPickerDemo.xcodeproj/xcshareddata/xcschemes/LocationPickerDemo.xcscheme +++ b/LocationPickerDemo/LocationPickerDemo.xcodeproj/xcshareddata/xcschemes/LocationPickerDemo.xcscheme @@ -1,6 +1,6 @@ Bool { + private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. return true } - func applicationWillResignActive(application: UIApplication) { + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - func applicationDidEnterBackground(application: UIApplication) { + func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - func applicationWillEnterForeground(application: UIApplication) { + func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - func applicationDidBecomeActive(application: UIApplication) { + func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - func applicationWillTerminate(application: UIApplication) { + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } diff --git a/LocationPickerDemo/LocationPickerDemo/Base.lproj/Main.storyboard b/LocationPickerDemo/LocationPickerDemo/Base.lproj/Main.storyboard index d86b708..a24fd8d 100644 --- a/LocationPickerDemo/LocationPickerDemo/Base.lproj/Main.storyboard +++ b/LocationPickerDemo/LocationPickerDemo/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - - + + @@ -15,51 +15,43 @@ - + - - - - - + - + @@ -123,9 +115,9 @@ - + - + diff --git a/LocationPickerDemo/LocationPickerDemo/CustomLocationPicker.swift b/LocationPickerDemo/LocationPickerDemo/CustomLocationPicker.swift index 6cae000..30f69de 100644 --- a/LocationPickerDemo/LocationPickerDemo/CustomLocationPicker.swift +++ b/LocationPickerDemo/LocationPickerDemo/CustomLocationPicker.swift @@ -23,8 +23,8 @@ class CustomLocationPicker: LocationPicker { } override func locationDidPick(locationItem: LocationItem) { - viewController.showLocation(locationItem) - viewController.storeLocation(locationItem) + viewController.showLocation(locationItem: locationItem) + viewController.storeLocation(locationItem: locationItem) } } diff --git a/LocationPickerDemo/LocationPickerDemo/ViewController.swift b/LocationPickerDemo/LocationPickerDemo/ViewController.swift index ea3d929..5375921 100644 --- a/LocationPickerDemo/LocationPickerDemo/ViewController.swift +++ b/LocationPickerDemo/LocationPickerDemo/ViewController.swift @@ -17,17 +17,17 @@ class ViewController: UIViewController, LocationPickerDelegate, LocationPickerDa var historyLocationList: [LocationItem] { get { - if let locationDataList = NSUserDefaults.standardUserDefaults().arrayForKey("HistoryLocationList") as? [NSData] { + if let locationDataList = UserDefaults.standard.array(forKey: "HistoryLocationList") as? [Data] { // Decode NSData into LocationItem object. - return locationDataList.map({ NSKeyedUnarchiver.unarchiveObjectWithData($0) as! LocationItem }) + return locationDataList.map({ NSKeyedUnarchiver.unarchiveObject(with: $0) as! LocationItem }) } else { return [] } } set { // Encode LocationItem object. - let locationDataList = newValue.map({ NSKeyedArchiver.archivedDataWithRootObject($0) }) - NSUserDefaults.standardUserDefaults().setObject(locationDataList, forKey: "HistoryLocationList") + let locationDataList = newValue.map({ NSKeyedArchiver.archivedData(withRootObject: $0) }) + UserDefaults.standard.set(locationDataList, forKey: "HistoryLocationList") } } @@ -35,7 +35,7 @@ class ViewController: UIViewController, LocationPickerDelegate, LocationPickerDa super.viewDidLoad() } - override func viewDidDisappear(animated: Bool) { + override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) locationNameTextField.text = nil locationAddressTextField.text = nil @@ -43,49 +43,49 @@ class ViewController: UIViewController, LocationPickerDelegate, LocationPickerDa // MARK: Navigation - override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // Show Location Picker via push segue. // LocationPicker in Storyboard. if segue.identifier == "LocationPicker" { - let locationPicker = segue.destinationViewController as! LocationPicker + let locationPicker = segue.destination as! LocationPicker // User delegate and dataSource. locationPicker.delegate = self locationPicker.dataSource = self - locationPicker.alternativeLocationEditable = true - locationPicker.allowArbitraryLocation = arbitraryLocationSwitch.on + locationPicker.isAlternativeLocationEditable = true + locationPicker.isAllowArbitraryLocation = arbitraryLocationSwitch.isOn } } - @IBAction func presentLocationPickerButtonDidTap(sender: UIButton) { + @IBAction func presentLocationPickerButtonDidTap(button: UIButton) { // Present Location Picker subclass via codes. // Create LocationPicker subclass. let customLocationPicker = CustomLocationPicker() - customLocationPicker.allowArbitraryLocation = arbitraryLocationSwitch.on + customLocationPicker.isAllowArbitraryLocation = arbitraryLocationSwitch.isOn customLocationPicker.viewController = self let navigationController = UINavigationController(rootViewController: customLocationPicker) - presentViewController(navigationController, animated: true, completion: nil) + present(navigationController, animated: true, completion: nil) } // Push LocationPicker to navigation controller. - @IBAction func pushLocationPickerButtonDidTap(sender: UIButton) { + @IBAction func pushLocationPickerButtonDidTap(button: UIButton) { // Push Location Picker via codes. let locationPicker = LocationPicker() - locationPicker.alternativeLocations = historyLocationList.reverse() - locationPicker.alternativeLocationEditable = true - locationPicker.allowArbitraryLocation = arbitraryLocationSwitch.on + locationPicker.alternativeLocations = historyLocationList.reversed() + locationPicker.isAlternativeLocationEditable = true + locationPicker.isAllowArbitraryLocation = arbitraryLocationSwitch.isOn // Completion closures locationPicker.selectCompletion = { selectedLocationItem in print("Select completion closure: " + selectedLocationItem.name) } locationPicker.pickCompletion = { pickedLocationItem in - self.showLocation(pickedLocationItem) - self.storeLocation(pickedLocationItem) + self.showLocation(locationItem: pickedLocationItem) + self.storeLocation(locationItem: pickedLocationItem) } locationPicker.deleteCompletion = { locationItem in - self.historyLocationList.removeAtIndex(self.historyLocationList.indexOf(locationItem)!) + self.historyLocationList.remove(at: self.historyLocationList.index(of: locationItem)!) } navigationController!.pushViewController(locationPicker, animated: true) } @@ -99,8 +99,8 @@ class ViewController: UIViewController, LocationPickerDelegate, LocationPickerDa } func locationDidPick(locationItem: LocationItem) { - showLocation(locationItem) - storeLocation(locationItem) + showLocation(locationItem: locationItem) + storeLocation(locationItem: locationItem) } @@ -111,12 +111,12 @@ class ViewController: UIViewController, LocationPickerDelegate, LocationPickerDa return historyLocationList.count } - func alternativeLocationAtIndex(index: Int) -> LocationItem { - return historyLocationList.reverse()[index] + func alternativeLocation(at index: Int) -> LocationItem { + return historyLocationList.reversed()[index] } func commitAlternativeLocationDeletion(locationItem: LocationItem) { - historyLocationList.removeAtIndex(historyLocationList.indexOf(locationItem)!) + historyLocationList.remove(at: historyLocationList.index(of: locationItem)!) } @@ -127,8 +127,8 @@ class ViewController: UIViewController, LocationPickerDelegate, LocationPickerDa } func storeLocation(locationItem: LocationItem) { - if let index = historyLocationList.indexOf(locationItem) { - historyLocationList.removeAtIndex(index) + if let index = historyLocationList.index(of: locationItem) { + historyLocationList.remove(at: index) } historyLocationList.append(locationItem) }