diff --git a/LeadKit/LeadKit.xcodeproj/project.pbxproj b/LeadKit/LeadKit.xcodeproj/project.pbxproj index 4ccfe7a5..4e233ae4 100644 --- a/LeadKit/LeadKit.xcodeproj/project.pbxproj +++ b/LeadKit/LeadKit.xcodeproj/project.pbxproj @@ -358,6 +358,22 @@ BA6C6DB45950382041948FC5 /* Pods_LeadKit_LeadKit_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CFE9323150A9760008093F73 /* Pods_LeadKit_LeadKit_iOS.framework */; }; D6EE55093E404DEA62B03DDF /* Pods_LeadKit_LeadKit_watchOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8590CA7831555C295C5DC572 /* Pods_LeadKit_LeadKit_watchOS.framework */; }; DEE25FE98D40ED1C168F384A /* Pods_LeadKit_LeadKit_iOS_Extensions.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 887F99C5326BD220C2811BD6 /* Pods_LeadKit_LeadKit_iOS_Extensions.framework */; }; + EFBE57D01EC35EF20040E00A /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57CF1EC35EF20040E00A /* Array+Extensions.swift */; }; + EFBE57D11EC35EF20040E00A /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57CF1EC35EF20040E00A /* Array+Extensions.swift */; }; + EFBE57D21EC35EF20040E00A /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57CF1EC35EF20040E00A /* Array+Extensions.swift */; }; + EFBE57D31EC35EF20040E00A /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57CF1EC35EF20040E00A /* Array+Extensions.swift */; }; + EFBE57D61EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57D51EC3603E0040E00A /* UIAlertController+Extensions.swift */; }; + EFBE57D71EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57D51EC3603E0040E00A /* UIAlertController+Extensions.swift */; }; + EFBE57D81EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57D51EC3603E0040E00A /* UIAlertController+Extensions.swift */; }; + EFBE57D91EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57D51EC3603E0040E00A /* UIAlertController+Extensions.swift */; }; + EFBE57DB1EC361620040E00A /* UIView+Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57DA1EC361620040E00A /* UIView+Layout.swift */; }; + EFBE57DC1EC361620040E00A /* UIView+Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57DA1EC361620040E00A /* UIView+Layout.swift */; }; + EFBE57DD1EC361620040E00A /* UIView+Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57DA1EC361620040E00A /* UIView+Layout.swift */; }; + EFBE57DE1EC361620040E00A /* UIView+Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57DA1EC361620040E00A /* UIView+Layout.swift */; }; + EFBE57E01EC362470040E00A /* AlertRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57DF1EC362470040E00A /* AlertRepresentable.swift */; }; + EFBE57E11EC362470040E00A /* AlertRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57DF1EC362470040E00A /* AlertRepresentable.swift */; }; + EFBE57E21EC362470040E00A /* AlertRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57DF1EC362470040E00A /* AlertRepresentable.swift */; }; + EFBE57E31EC362470040E00A /* AlertRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBE57DF1EC362470040E00A /* AlertRepresentable.swift */; }; FDE4AA990268F140877307E7 /* Pods_LeadKit_iOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 78405D3B3D3C3E17456877FF /* Pods_LeadKit_iOSTests.framework */; }; /* End PBXBuildFile section */ @@ -526,6 +542,10 @@ D0F8D0002B21A4F31981F1ED /* Pods_LeadKit_LeadKit_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_LeadKit_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D840E55867DC9BB63460B856 /* Pods-LeadKit tvOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKit tvOSTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKit tvOSTests/Pods-LeadKit tvOSTests.release.xcconfig"; sourceTree = ""; }; DF1148A279C7AC7A42B0A0F8 /* Pods_LeadKit_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + EFBE57CF1EC35EF20040E00A /* Array+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+Extensions.swift"; sourceTree = ""; }; + EFBE57D51EC3603E0040E00A /* UIAlertController+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIAlertController+Extensions.swift"; sourceTree = ""; }; + EFBE57DA1EC361620040E00A /* UIView+Layout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Layout.swift"; sourceTree = ""; }; + EFBE57DF1EC362470040E00A /* AlertRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertRepresentable.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -671,6 +691,7 @@ isa = PBXGroup; children = ( 671461DB1EB3396E00EAB194 /* Alamofire */, + EFBE57CE1EC35ED90040E00A /* Array */, 671461DE1EB3396E00EAB194 /* CGContext */, 671461E01EB3396E00EAB194 /* CGFloat */, 671461E21EB3396E00EAB194 /* CGImage */, @@ -689,6 +710,7 @@ 671462001EB3396E00EAB194 /* TableDirector */, 671462021EB3396E00EAB194 /* TimeInterval */, 671462041EB3396E00EAB194 /* UIActivityIndicator */, + EFBE57D41EC360240040E00A /* UIAlertController */, 671462061EB3396E00EAB194 /* UICollectionView */, 671462081EB3396E00EAB194 /* UIColor */, 6714620A1EB3396E00EAB194 /* UIDevice */, @@ -899,6 +921,7 @@ children = ( 671462121EB3396E00EAB194 /* UIView+DefaultReuseIdentifier.swift */, 671462131EB3396E00EAB194 /* UIView+DefaultXibName.swift */, + EFBE57DA1EC361620040E00A /* UIView+Layout.swift */, 671462141EB3396E00EAB194 /* UIView+LoadFromNib.swift */, 671462151EB3396E00EAB194 /* UIView+LoadingIndicator.swift */, 671462161EB3396E00EAB194 /* UIView+Rotation.swift */, @@ -945,6 +968,8 @@ 671462221EB3396E00EAB194 /* Protocols */ = { isa = PBXGroup; children = ( + EFBE57DF1EC362470040E00A /* AlertRepresentable.swift */, + 671463A11EB33FF600EAB194 /* Animatable.swift */, 671462231EB3396E00EAB194 /* BaseViewModel.swift */, 671462241EB3396E00EAB194 /* ConfigurableController.swift */, 671462251EB3396E00EAB194 /* CursorType.swift */, @@ -963,7 +988,6 @@ 671462321EB3396E00EAB194 /* ViewHeightProtocol.swift */, 671462331EB3396E00EAB194 /* ViewModelProtocol.swift */, 671462341EB3396E00EAB194 /* XibNameProtocol.swift */, - 671463A11EB33FF600EAB194 /* Animatable.swift */, ); path = Protocols; sourceTree = ""; @@ -1145,6 +1169,22 @@ name = Pods; sourceTree = ""; }; + EFBE57CE1EC35ED90040E00A /* Array */ = { + isa = PBXGroup; + children = ( + EFBE57CF1EC35EF20040E00A /* Array+Extensions.swift */, + ); + path = Array; + sourceTree = ""; + }; + EFBE57D41EC360240040E00A /* UIAlertController */ = { + isa = PBXGroup; + children = ( + EFBE57D51EC3603E0040E00A /* UIAlertController+Extensions.swift */, + ); + path = UIAlertController; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -1837,6 +1877,7 @@ buildActionMask = 2147483647; files = ( 671463481EB3396E00EAB194 /* ResettableType.swift in Sources */, + EFBE57D01EC35EF20040E00A /* Array+Extensions.swift in Sources */, 671462E41EB3396E00EAB194 /* UIColor+Hex.swift in Sources */, 671462CC1EB3396E00EAB194 /* String+SizeCalculation.swift in Sources */, 671462801EB3396E00EAB194 /* AlamofireRequest+Extensions.swift in Sources */, @@ -1847,6 +1888,7 @@ 671462DC1EB3396E00EAB194 /* UIActivityIndicator+LoadingIndicator.swift in Sources */, 671462841EB3396E00EAB194 /* CGContext+Initializers.swift in Sources */, 671463201EB3396E00EAB194 /* Any+Cast.swift in Sources */, + EFBE57DB1EC361620040E00A /* UIView+Layout.swift in Sources */, 6714639E1EB33AEB00EAB194 /* NetworkService+ActivityIndicator.swift in Sources */, 6714634C1EB3396E00EAB194 /* ReuseIdentifierProtocol.swift in Sources */, 671462F01EB3396E00EAB194 /* UIImage+SupportExtensions.swift in Sources */, @@ -1881,6 +1923,7 @@ 671462B41EB3396E00EAB194 /* PaginationTableViewWrapperDelegate+DefaultImplementation.swift in Sources */, 671462781EB3396E00EAB194 /* ResizeContentMode.swift in Sources */, 671463041EB3396E00EAB194 /* UIView+LoadingIndicator.swift in Sources */, + EFBE57D61EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */, 671463701EB3396E00EAB194 /* ApiRequestParameters.swift in Sources */, 671462EC1EB3396E00EAB194 /* UIImage+Extensions.swift in Sources */, 6714636C1EB3396E00EAB194 /* XibNameProtocol.swift in Sources */, @@ -1922,6 +1965,7 @@ 6714638C1EB3396E00EAB194 /* SolidFillDrawingOperation.swift in Sources */, 671463A21EB33FF600EAB194 /* Animatable.swift in Sources */, 671462501EB3396E00EAB194 /* StaticCursor.swift in Sources */, + EFBE57E01EC362470040E00A /* AlertRepresentable.swift in Sources */, 6714629C1EB3396E00EAB194 /* CursorType+Slice.swift in Sources */, 671463681EB3396E00EAB194 /* ViewModelProtocol.swift in Sources */, 671462E81EB3396E00EAB194 /* UIDevice+Extensions.swift in Sources */, @@ -1949,12 +1993,14 @@ 6714634A1EB3396E00EAB194 /* ResettableType.swift in Sources */, 671462E61EB3396E00EAB194 /* UIColor+Hex.swift in Sources */, 671462CE1EB3396E00EAB194 /* String+SizeCalculation.swift in Sources */, + EFBE57D21EC35EF20040E00A /* Array+Extensions.swift in Sources */, 671462821EB3396E00EAB194 /* AlamofireRequest+Extensions.swift in Sources */, 671462C61EB3396E00EAB194 /* String+Extensions.swift in Sources */, 671463561EB3396E00EAB194 /* StaticViewHeightProtocol.swift in Sources */, 671462AA1EB3396E00EAB194 /* ImmutableMappable+ObservableMappable.swift in Sources */, 671463621EB3396E00EAB194 /* SupportProtocol.swift in Sources */, 671462861EB3396E00EAB194 /* CGContext+Initializers.swift in Sources */, + EFBE57D81EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */, 671463221EB3396E00EAB194 /* Any+Cast.swift in Sources */, 6714634E1EB3396E00EAB194 /* ReuseIdentifierProtocol.swift in Sources */, 6714626A1EB3396E00EAB194 /* NetworkService.swift in Sources */, @@ -1971,6 +2017,7 @@ 671463261EB3396E00EAB194 /* Any+TypeName.swift in Sources */, 6714638A1EB3396E00EAB194 /* RoundDrawingOperation.swift in Sources */, 671463821EB3396E00EAB194 /* PaddingDrawingOperation.swift in Sources */, + EFBE57E21EC362470040E00A /* AlertRepresentable.swift in Sources */, 6714632A1EB3396E00EAB194 /* BaseViewModel.swift in Sources */, 671462AE1EB3396E00EAB194 /* Observable+DeferredJust.swift in Sources */, 6714627E1EB3396E00EAB194 /* AlamofireManager+Extensions.swift in Sources */, @@ -1983,6 +2030,7 @@ 67CDEE401EB369BF00895905 /* ConfigurableController.swift in Sources */, 671462A61EB3396E00EAB194 /* IndexPath+ImmutableIndexPath.swift in Sources */, 671462A21EB3396E00EAB194 /* Double+Rounding.swift in Sources */, + EFBE57DD1EC361620040E00A /* UIView+Layout.swift in Sources */, 6714625E1EB3396E00EAB194 /* LogFormatter.swift in Sources */, 6714637E1EB3396E00EAB194 /* ImageDrawingOperation.swift in Sources */, 6714631E1EB3396E00EAB194 /* UserDefaults+MappableDataTypes.swift in Sources */, @@ -2011,6 +2059,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + EFBE57D91EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */, 6714634B1EB3396E00EAB194 /* ResettableType.swift in Sources */, 671462E71EB3396E00EAB194 /* UIColor+Hex.swift in Sources */, 671462CF1EB3396E00EAB194 /* String+SizeCalculation.swift in Sources */, @@ -2042,6 +2091,7 @@ 671463331EB3396E00EAB194 /* CursorType.swift in Sources */, 6714624F1EB3396E00EAB194 /* MapCursor.swift in Sources */, 671463271EB3396E00EAB194 /* Any+TypeName.swift in Sources */, + EFBE57D31EC35EF20040E00A /* Array+Extensions.swift in Sources */, 6714638B1EB3396E00EAB194 /* RoundDrawingOperation.swift in Sources */, 671463831EB3396E00EAB194 /* PaddingDrawingOperation.swift in Sources */, 671462E31EB3396E00EAB194 /* UICollectionView+CellRegistration.swift in Sources */, @@ -2053,12 +2103,14 @@ 6714625B1EB3396E00EAB194 /* Log.swift in Sources */, 6714627B1EB3396E00EAB194 /* ResizeContentMode.swift in Sources */, 671463071EB3396E00EAB194 /* UIView+LoadingIndicator.swift in Sources */, + EFBE57E31EC362470040E00A /* AlertRepresentable.swift in Sources */, 671463A91EB340C000EAB194 /* UIViewController+ConfigurableController.swift in Sources */, 671463731EB3396E00EAB194 /* ApiRequestParameters.swift in Sources */, 671462EF1EB3396E00EAB194 /* UIImage+Extensions.swift in Sources */, 6714636F1EB3396E00EAB194 /* XibNameProtocol.swift in Sources */, 671462A71EB3396E00EAB194 /* IndexPath+ImmutableIndexPath.swift in Sources */, 671462BF1EB3396E00EAB194 /* StoryboardProtocol+DefaultBundle.swift in Sources */, + EFBE57DE1EC361620040E00A /* UIView+Layout.swift in Sources */, 671462A31EB3396E00EAB194 /* Double+Rounding.swift in Sources */, 6714625F1EB3396E00EAB194 /* LogFormatter.swift in Sources */, 6714630B1EB3396E00EAB194 /* UIView+Rotation.swift in Sources */, @@ -2178,11 +2230,13 @@ 671462951EB3396E00EAB194 /* CGSize+CGContextSize.swift in Sources */, 671463651EB3396E00EAB194 /* ViewHeightProtocol.swift in Sources */, 671462491EB3396E00EAB194 /* FixedPageCursor.swift in Sources */, + EFBE57E11EC362470040E00A /* AlertRepresentable.swift in Sources */, 671462C91EB3396E00EAB194 /* String+Localization.swift in Sources */, 671462B91EB3396E00EAB194 /* Sequence+ConcurrentMap.swift in Sources */, 671463751EB3396E00EAB194 /* BorderDrawingOperation.swift in Sources */, 6714633D1EB3396E00EAB194 /* LoadingIndicator.swift in Sources */, 671463191EB3396E00EAB194 /* UIWindow+Extensions.swift in Sources */, + EFBE57DC1EC361620040E00A /* UIView+Layout.swift in Sources */, 671462551EB3396E00EAB194 /* App.swift in Sources */, 6714635D1EB3396E00EAB194 /* StoryboardProtocol.swift in Sources */, 671462F51EB3396E00EAB194 /* UIStoryboard+InstantiateViewController.swift in Sources */, @@ -2191,6 +2245,7 @@ 6714632D1EB3396E00EAB194 /* ConfigurableController.swift in Sources */, 6714628D1EB3396E00EAB194 /* CGImage+Alpha.swift in Sources */, 671462751EB3396E00EAB194 /* LeadKitError.swift in Sources */, + EFBE57D11EC35EF20040E00A /* Array+Extensions.swift in Sources */, 67CDEE431EB3AD1C00895905 /* NetworkService+RxLoadImage.swift in Sources */, 671462D91EB3396E00EAB194 /* TimeInterval+DateComponents.swift in Sources */, 6714638D1EB3396E00EAB194 /* SolidFillDrawingOperation.swift in Sources */, @@ -2198,6 +2253,7 @@ 671462511EB3396E00EAB194 /* StaticCursor.swift in Sources */, 6714629D1EB3396E00EAB194 /* CursorType+Slice.swift in Sources */, 671463691EB3396E00EAB194 /* ViewModelProtocol.swift in Sources */, + EFBE57D71EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */, 671462E91EB3396E00EAB194 /* UIDevice+Extensions.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/LeadKit/Sources/Extensions/Array/Array+Extensions.swift b/LeadKit/Sources/Extensions/Array/Array+Extensions.swift new file mode 100644 index 00000000..8253e4b8 --- /dev/null +++ b/LeadKit/Sources/Extensions/Array/Array+Extensions.swift @@ -0,0 +1,78 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +public extension Array where Element: Equatable { + + /// Union array with another arrays, without element duplication + func union(values: [Array.Element]...) -> Array { + var result = self + + for array in values { + for value in array { + if !result.contains(value) { + result.append(value) + } + } + } + + return result + } + + /// Find common elements among arrays + func intersection(values: [Array.Element]...) -> Array { + var result = self + var intersection = Array() + + for (index, value) in values.enumerated() { + if index > 0 { + result = intersection + intersection = Array() + } + + value.forEach { item in + if result.contains(item) && !intersection.contains(item) { + intersection.append(item) + } + } + } + + return intersection + } + + /// Find unique elements in array compared to other arrays + func subtract(values: [Array.Element]...) -> Array { + var result = Array() + + elements: for item in self { + for value in values { + if value.contains(item) { + continue elements + } + } + + result.append(item) + } + + return result + } + +} diff --git a/LeadKit/Sources/Extensions/String/String+Extensions.swift b/LeadKit/Sources/Extensions/String/String+Extensions.swift index 2d477290..2d06fa31 100644 --- a/LeadKit/Sources/Extensions/String/String+Extensions.swift +++ b/LeadKit/Sources/Extensions/String/String+Extensions.swift @@ -33,4 +33,13 @@ public extension String { return UIImage(named: self) } + /** + Nil if empty representation + + - returns: nil if string empty, self otherwise + */ + public var nilIfEmpty: String? { + return isEmpty ? nil : self + } + } diff --git a/LeadKit/Sources/Extensions/UIAlertController/UIAlertController+Extensions.swift b/LeadKit/Sources/Extensions/UIAlertController/UIAlertController+Extensions.swift new file mode 100644 index 00000000..8e84e05c --- /dev/null +++ b/LeadKit/Sources/Extensions/UIAlertController/UIAlertController+Extensions.swift @@ -0,0 +1,47 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit + +public extension UIAlertController { + + /** + Creates UIAlertController instance + + - parameter item: information about alert in AlertRepresentable form + - parameter actions: actions handlers + + - returns: UIAlertController instance + */ + static func alert(item: AlertRepresentable, actions: (() -> Void)?...) -> UIAlertController { + let alert = UIAlertController(title: item.title, message: item.text, preferredStyle: .alert) + + zip(item.actionTitles, actions + [nil]) + .map { (title, action) in + UIAlertAction(title: title, style: .default, handler: { _ in action?() }) + } + .forEach { alert.addAction($0) } + + return alert + } + +} diff --git a/LeadKit/Sources/Extensions/UIView/UIView+Layout.swift b/LeadKit/Sources/Extensions/UIView/UIView+Layout.swift new file mode 100644 index 00000000..f8bdefe8 --- /dev/null +++ b/LeadKit/Sources/Extensions/UIView/UIView+Layout.swift @@ -0,0 +1,61 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit + +public extension UIView { + + /** + Place and fix view to parent view's center + + - parameter size: desired view size, by default size is equal parent's size + */ + func setToCenter(withSize size: CGSize? = nil) { + guard let parent = superview else { + return + } + + translatesAutoresizingMaskIntoConstraints = false + + guard let size = size else { + scaleToFill() + return + } + + centerXAnchor.constraint(equalTo: parent.centerXAnchor).isActive = true + centerYAnchor.constraint(equalTo: parent.centerYAnchor).isActive = true + heightAnchor.constraint(equalToConstant: size.height).isActive = true + widthAnchor.constraint(equalToConstant: size.width).isActive = true + } + + private func scaleToFill() { + guard let superview = superview else { + return + } + + topAnchor.constraint(equalTo: superview.topAnchor).isActive = true + bottomAnchor.constraint(equalTo: superview.bottomAnchor).isActive = true + leftAnchor.constraint(equalTo: superview.leftAnchor).isActive = true + rightAnchor.constraint(equalTo: superview.rightAnchor).isActive = true + } + +} diff --git a/LeadKit/Sources/Protocols/AlertRepresentable.swift b/LeadKit/Sources/Protocols/AlertRepresentable.swift new file mode 100644 index 00000000..4a86c988 --- /dev/null +++ b/LeadKit/Sources/Protocols/AlertRepresentable.swift @@ -0,0 +1,41 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +/// Protocol describes alert +public protocol AlertRepresentable { + /// Alert title + var title: String { get } + /// Alert message + var text: String { get } + /// Single (default, for example - "OK") action title + var actionTitle: String { get } + /// Actions titles, if there are more than one action + var actionTitles: [String] { get } +} + +public extension AlertRepresentable { + /// By default actionTitles contains single action title + var actionTitles: [String] { + return [actionTitle] + } + +}