From 0f5e5af5e735bf4202a8c5d6df7931c2b0af518d Mon Sep 17 00:00:00 2001 From: Luca Schifino Date: Tue, 20 Aug 2019 14:24:03 -0300 Subject: [PATCH 1/4] Adding dx utils methods and extension with unit tests. --- UtilitiesCore.xcodeproj/project.pbxproj | 130 +++++++++--- ...nsion.swift => Collection+Extension.swift} | 0 UtilitiesCore/Extensions/Date+Extension.swift | 43 ++++ .../Extensions/Float+Extension.swift | 17 ++ UtilitiesCore/Extensions/Int+Extension.swift | 33 ++++ .../Extensions/String+Extension.swift | 185 ++++++++++++++---- .../UIActivityIndicatorView+Extension.swift | 39 ++++ .../Extensions/UIColor+Extension.swift | 49 +++++ .../Extensions/UIFont+Extension.swift | 25 +++ .../Extensions/UILabel+Extension.swift | 23 +++ .../Extensions/UIView+Extension.swift | 48 +++++ .../UIViewController+Extension.swift | 26 +++ UtilitiesCore/Resources/NibInstantiable.swift | 21 ++ .../Resources/NibRegistrableView.swift | 56 ++++++ UtilitiesCore/Resources/SystemInfo.swift | 44 +++++ UtilitiesCoreTests/Extensions/DateTests.swift | 42 ++++ .../Extensions/FloatTests.swift | 18 ++ UtilitiesCoreTests/Extensions/IntTests.swift | 29 +++ .../Extensions/StringTests.swift | 29 +++ .../UIActivityIndicatorViewTests.swift | 75 +++++++ .../Extensions/UIColorTests.swift | 28 +++ .../Extensions/UIViewControllerTests.swift | 24 +++ .../Extensions/UIViewTests.swift | 28 +++ 23 files changed, 947 insertions(+), 65 deletions(-) rename UtilitiesCore/Extensions/{Colletion+Extension.swift => Collection+Extension.swift} (100%) create mode 100644 UtilitiesCore/Extensions/Date+Extension.swift create mode 100644 UtilitiesCore/Extensions/Float+Extension.swift create mode 100644 UtilitiesCore/Extensions/Int+Extension.swift create mode 100644 UtilitiesCore/Extensions/UIActivityIndicatorView+Extension.swift create mode 100644 UtilitiesCore/Extensions/UIColor+Extension.swift create mode 100644 UtilitiesCore/Extensions/UIFont+Extension.swift create mode 100644 UtilitiesCore/Extensions/UILabel+Extension.swift create mode 100644 UtilitiesCore/Extensions/UIView+Extension.swift create mode 100644 UtilitiesCore/Extensions/UIViewController+Extension.swift create mode 100644 UtilitiesCore/Resources/NibInstantiable.swift create mode 100644 UtilitiesCore/Resources/NibRegistrableView.swift create mode 100644 UtilitiesCore/Resources/SystemInfo.swift create mode 100644 UtilitiesCoreTests/Extensions/DateTests.swift create mode 100644 UtilitiesCoreTests/Extensions/FloatTests.swift create mode 100644 UtilitiesCoreTests/Extensions/IntTests.swift create mode 100644 UtilitiesCoreTests/Extensions/UIActivityIndicatorViewTests.swift create mode 100644 UtilitiesCoreTests/Extensions/UIColorTests.swift create mode 100644 UtilitiesCoreTests/Extensions/UIViewControllerTests.swift create mode 100644 UtilitiesCoreTests/Extensions/UIViewTests.swift diff --git a/UtilitiesCore.xcodeproj/project.pbxproj b/UtilitiesCore.xcodeproj/project.pbxproj index f2edcfd..8256d81 100644 --- a/UtilitiesCore.xcodeproj/project.pbxproj +++ b/UtilitiesCore.xcodeproj/project.pbxproj @@ -11,6 +11,25 @@ 0259946A22C531400017850B /* CpfValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0259946922C531400017850B /* CpfValidatorTests.swift */; }; 0259946C22C53A0A0017850B /* CnpjValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0259946B22C53A0A0017850B /* CnpjValidator.swift */; }; 0259946E22C53B2B0017850B /* CnpjValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0259946D22C53B2B0017850B /* CnpjValidatorTests.swift */; }; + 0279FD48230C0E6900AFD2CB /* UIActivityIndicatorView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD47230C0E6900AFD2CB /* UIActivityIndicatorView+Extension.swift */; }; + 0279FD4A230C0EB000AFD2CB /* UIActivityIndicatorViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD49230C0EB000AFD2CB /* UIActivityIndicatorViewTests.swift */; }; + 0279FD4C230C11F000AFD2CB /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD4B230C11F000AFD2CB /* UIColor+Extension.swift */; }; + 0279FD4E230C123D00AFD2CB /* UIColorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD4D230C123D00AFD2CB /* UIColorTests.swift */; }; + 0279FD50230C135300AFD2CB /* UIFont+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD4F230C135300AFD2CB /* UIFont+Extension.swift */; }; + 0279FD54230C147300AFD2CB /* UILabel+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD53230C147300AFD2CB /* UILabel+Extension.swift */; }; + 0279FD56230C14A800AFD2CB /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD55230C14A800AFD2CB /* UIView+Extension.swift */; }; + 0279FD58230C14EA00AFD2CB /* UIViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD57230C14EA00AFD2CB /* UIViewTests.swift */; }; + 0279FD5A230C174800AFD2CB /* UIViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD59230C174800AFD2CB /* UIViewController+Extension.swift */; }; + 0279FD5C230C177400AFD2CB /* UIViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD5B230C177400AFD2CB /* UIViewControllerTests.swift */; }; + 0279FD5E230C188700AFD2CB /* NibRegistrableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD5D230C188700AFD2CB /* NibRegistrableView.swift */; }; + 0279FD60230C189400AFD2CB /* NibInstantiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD5F230C189400AFD2CB /* NibInstantiable.swift */; }; + 0279FD62230C1B2E00AFD2CB /* SystemInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0279FD61230C1B2D00AFD2CB /* SystemInfo.swift */; }; + 028672C522FB37AE00C6326A /* Float+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 028672C422FB37AE00C6326A /* Float+Extension.swift */; }; + 028672C722FB381000C6326A /* FloatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 028672C622FB381000C6326A /* FloatTests.swift */; }; + 028672C922FB387800C6326A /* Int+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 028672C822FB387800C6326A /* Int+Extension.swift */; }; + 028672CD22FB3D1C00C6326A /* IntTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 028672CC22FB3D1C00C6326A /* IntTests.swift */; }; + 028672CF22FB3FFD00C6326A /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 028672CE22FB3FFD00C6326A /* Date+Extension.swift */; }; + 028672D122FB591100C6326A /* DateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 028672D022FB591100C6326A /* DateTests.swift */; }; C90551D122B27F4900FC600A /* DecodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C90551D022B27F4900FC600A /* DecodableTests.swift */; }; C92250A3227B4D8400ABFB38 /* UtilitiesCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9225099227B4D8400ABFB38 /* UtilitiesCore.framework */; }; C92250AA227B4D8400ABFB38 /* UtilitiesCore.h in Headers */ = {isa = PBXBuildFile; fileRef = C922509C227B4D8400ABFB38 /* UtilitiesCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -18,7 +37,7 @@ C92250C1227B527800ABFB38 /* NumberFormatter+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C92250B7227B527700ABFB38 /* NumberFormatter+Extension.swift */; }; C92250C2227B527800ABFB38 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C92250B8227B527700ABFB38 /* String+Extension.swift */; }; C92250C3227B527800ABFB38 /* DateFormatter+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C92250B9227B527700ABFB38 /* DateFormatter+Extension.swift */; }; - C92250C4227B527800ABFB38 /* Colletion+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C92250BA227B527700ABFB38 /* Colletion+Extension.swift */; }; + C92250C4227B527800ABFB38 /* Collection+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C92250BA227B527700ABFB38 /* Collection+Extension.swift */; }; C92250CA227B57FB00ABFB38 /* CollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C92250C9227B57FB00ABFB38 /* CollectionTests.swift */; }; C92250CC227B5FCB00ABFB38 /* DateFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C92250CB227B5FCB00ABFB38 /* DateFormatterTests.swift */; }; C92250CE227B62C700ABFB38 /* NumberFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C92250CD227B62C700ABFB38 /* NumberFormatterTests.swift */; }; @@ -61,6 +80,25 @@ 0259946922C531400017850B /* CpfValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CpfValidatorTests.swift; sourceTree = ""; }; 0259946B22C53A0A0017850B /* CnpjValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CnpjValidator.swift; sourceTree = ""; }; 0259946D22C53B2B0017850B /* CnpjValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CnpjValidatorTests.swift; sourceTree = ""; }; + 0279FD47230C0E6900AFD2CB /* UIActivityIndicatorView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIActivityIndicatorView+Extension.swift"; sourceTree = ""; }; + 0279FD49230C0EB000AFD2CB /* UIActivityIndicatorViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIActivityIndicatorViewTests.swift; sourceTree = ""; }; + 0279FD4B230C11F000AFD2CB /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = ""; }; + 0279FD4D230C123D00AFD2CB /* UIColorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColorTests.swift; sourceTree = ""; }; + 0279FD4F230C135300AFD2CB /* UIFont+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Extension.swift"; sourceTree = ""; }; + 0279FD53230C147300AFD2CB /* UILabel+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Extension.swift"; sourceTree = ""; }; + 0279FD55230C14A800AFD2CB /* UIView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Extension.swift"; sourceTree = ""; }; + 0279FD57230C14EA00AFD2CB /* UIViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewTests.swift; sourceTree = ""; }; + 0279FD59230C174800AFD2CB /* UIViewController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extension.swift"; sourceTree = ""; }; + 0279FD5B230C177400AFD2CB /* UIViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerTests.swift; sourceTree = ""; }; + 0279FD5D230C188700AFD2CB /* NibRegistrableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NibRegistrableView.swift; sourceTree = ""; }; + 0279FD5F230C189400AFD2CB /* NibInstantiable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NibInstantiable.swift; sourceTree = ""; }; + 0279FD61230C1B2D00AFD2CB /* SystemInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemInfo.swift; sourceTree = ""; }; + 028672C422FB37AE00C6326A /* Float+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Float+Extension.swift"; sourceTree = ""; }; + 028672C622FB381000C6326A /* FloatTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatTests.swift; sourceTree = ""; }; + 028672C822FB387800C6326A /* Int+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Int+Extension.swift"; sourceTree = ""; }; + 028672CC22FB3D1C00C6326A /* IntTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntTests.swift; sourceTree = ""; }; + 028672CE22FB3FFD00C6326A /* Date+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extension.swift"; sourceTree = ""; }; + 028672D022FB591100C6326A /* DateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTests.swift; sourceTree = ""; }; C90551D022B27F4900FC600A /* DecodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecodableTests.swift; sourceTree = ""; }; C9225099227B4D8400ABFB38 /* UtilitiesCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = UtilitiesCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C922509C227B4D8400ABFB38 /* UtilitiesCore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UtilitiesCore.h; sourceTree = ""; }; @@ -71,7 +109,7 @@ C92250B7227B527700ABFB38 /* NumberFormatter+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NumberFormatter+Extension.swift"; sourceTree = ""; }; C92250B8227B527700ABFB38 /* String+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = ""; }; C92250B9227B527700ABFB38 /* DateFormatter+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DateFormatter+Extension.swift"; sourceTree = ""; }; - C92250BA227B527700ABFB38 /* Colletion+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Colletion+Extension.swift"; sourceTree = ""; }; + C92250BA227B527700ABFB38 /* Collection+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Collection+Extension.swift"; sourceTree = ""; }; C92250C9227B57FB00ABFB38 /* CollectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionTests.swift; sourceTree = ""; }; C92250CB227B5FCB00ABFB38 /* DateFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateFormatterTests.swift; sourceTree = ""; }; C92250CD227B62C700ABFB38 /* NumberFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NumberFormatterTests.swift; sourceTree = ""; }; @@ -118,6 +156,16 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 028672C322FB360E00C6326A /* Resources */ = { + isa = PBXGroup; + children = ( + 0279FD5D230C188700AFD2CB /* NibRegistrableView.swift */, + 0279FD5F230C189400AFD2CB /* NibInstantiable.swift */, + 0279FD61230C1B2D00AFD2CB /* SystemInfo.swift */, + ); + path = Resources; + sourceTree = ""; + }; C922508F227B4D8400ABFB38 = { isa = PBXGroup; children = ( @@ -139,6 +187,7 @@ C922509B227B4D8400ABFB38 /* UtilitiesCore */ = { isa = PBXGroup; children = ( + 028672C322FB360E00C6326A /* Resources */, C9835CC82281B89500DB672B /* Validators */, C92250B5227B527700ABFB38 /* Extensions */, C922509C227B4D8400ABFB38 /* UtilitiesCore.h */, @@ -160,15 +209,24 @@ C92250B5227B527700ABFB38 /* Extensions */ = { isa = PBXGroup; children = ( + C92250BA227B527700ABFB38 /* Collection+Extension.swift */, + 028672CE22FB3FFD00C6326A /* Date+Extension.swift */, + C92250B9227B527700ABFB38 /* DateFormatter+Extension.swift */, C92250B6227B527700ABFB38 /* Decimal+Extension.swift */, + C99B09B622B27CC800AADF3B /* Decode+Extension.swift */, + C9ED4A5A229D91F100939BFB /* Encodable+Extension.swift */, + C99B09B422B27C5E00AADF3B /* Encodable+Extensions.swift */, + 028672C422FB37AE00C6326A /* Float+Extension.swift */, + 028672C822FB387800C6326A /* Int+Extension.swift */, C92250B7227B527700ABFB38 /* NumberFormatter+Extension.swift */, C92250B8227B527700ABFB38 /* String+Extension.swift */, - C92250B9227B527700ABFB38 /* DateFormatter+Extension.swift */, - C92250BA227B527700ABFB38 /* Colletion+Extension.swift */, + 0279FD47230C0E6900AFD2CB /* UIActivityIndicatorView+Extension.swift */, + 0279FD4B230C11F000AFD2CB /* UIColor+Extension.swift */, + 0279FD4F230C135300AFD2CB /* UIFont+Extension.swift */, + 0279FD53230C147300AFD2CB /* UILabel+Extension.swift */, C9835D01228320FF00DB672B /* UITextField+Extension.swift */, - C99B09B422B27C5E00AADF3B /* Encodable+Extensions.swift */, - C99B09B622B27CC800AADF3B /* Decode+Extension.swift */, - C9ED4A5A229D91F100939BFB /* Encodable+Extension.swift */, + 0279FD55230C14A800AFD2CB /* UIView+Extension.swift */, + 0279FD59230C174800AFD2CB /* UIViewController+Extension.swift */, ); path = Extensions; sourceTree = ""; @@ -177,12 +235,19 @@ isa = PBXGroup; children = ( C92250C9227B57FB00ABFB38 /* CollectionTests.swift */, + 028672D022FB591100C6326A /* DateTests.swift */, C92250CB227B5FCB00ABFB38 /* DateFormatterTests.swift */, + C90551D022B27F4900FC600A /* DecodableTests.swift */, + C9ED4A5C229D920800939BFB /* EncodableTests.swift */, + 028672C622FB381000C6326A /* FloatTests.swift */, + 028672CC22FB3D1C00C6326A /* IntTests.swift */, C92250CD227B62C700ABFB38 /* NumberFormatterTests.swift */, C92250CF227B683500ABFB38 /* StringTests.swift */, + 0279FD49230C0EB000AFD2CB /* UIActivityIndicatorViewTests.swift */, + 0279FD4D230C123D00AFD2CB /* UIColorTests.swift */, C9835D0322833FBD00DB672B /* UITextFieldTests.swift */, - C90551D022B27F4900FC600A /* DecodableTests.swift */, - C9ED4A5C229D920800939BFB /* EncodableTests.swift */, + 0279FD57230C14EA00AFD2CB /* UIViewTests.swift */, + 0279FD5B230C177400AFD2CB /* UIViewControllerTests.swift */, ); path = Extensions; sourceTree = ""; @@ -190,16 +255,16 @@ C9835CC82281B89500DB672B /* Validators */ = { isa = PBXGroup; children = ( - C9835CCF2281B8A800DB672B /* Validator.swift */, - C9835CDB2281BECD00DB672B /* RequiredFieldValidator.swift */, - C9835CCE2281B8A700DB672B /* EmailValidator.swift */, - C9835CCB2281B8A700DB672B /* ValidAgeValidator.swift */, - C9835CC92281B8A700DB672B /* PasswordValidator.swift */, C9835CCD2281B8A700DB672B /* AlphabetValidator.swift */, - C9835CD12281B8A800DB672B /* FutureDateValidator.swift */, - 0259946722C52F7F0017850B /* CpfValidator.swift */, 0259946B22C53A0A0017850B /* CnpjValidator.swift */, + 0259946722C52F7F0017850B /* CpfValidator.swift */, C9835CF02282065B00DB672B /* CustomValidator.swift */, + C9835CCE2281B8A700DB672B /* EmailValidator.swift */, + C9835CD12281B8A800DB672B /* FutureDateValidator.swift */, + C9835CC92281B8A700DB672B /* PasswordValidator.swift */, + C9835CDB2281BECD00DB672B /* RequiredFieldValidator.swift */, + C9835CCB2281B8A700DB672B /* ValidAgeValidator.swift */, + C9835CCF2281B8A800DB672B /* Validator.swift */, ); path = Validators; sourceTree = ""; @@ -207,15 +272,15 @@ C9835CF222821AAF00DB672B /* Validators */ = { isa = PBXGroup; children = ( + C9835CFB228314E200DB672B /* AlphabetValidatorTests.swift */, + 0259946D22C53B2B0017850B /* CnpjValidatorTests.swift */, + 0259946922C531400017850B /* CpfValidatorTests.swift */, + C9835CFF228319AC00DB672B /* CustomValidatorTests.swift */, C9835CF522821FE300DB672B /* RequiredFieldValidatorTests.swift */, C9835CF322821B8500DB672B /* EmailValidatorTests.swift */, - C9835CF7228220B300DB672B /* ValidAgeValidatorTests.swift */, - C9835CF92283135200DB672B /* PasswordValidatorTests.swift */, - C9835CFB228314E200DB672B /* AlphabetValidatorTests.swift */, C9835CFD2283177100DB672B /* FutureDateValidatorTests.swift */, - C9835CFF228319AC00DB672B /* CustomValidatorTests.swift */, - 0259946922C531400017850B /* CpfValidatorTests.swift */, - 0259946D22C53B2B0017850B /* CnpjValidatorTests.swift */, + C9835CF92283135200DB672B /* PasswordValidatorTests.swift */, + C9835CF7228220B300DB672B /* ValidAgeValidatorTests.swift */, ); path = Validators; sourceTree = ""; @@ -351,8 +416,15 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0279FD5E230C188700AFD2CB /* NibRegistrableView.swift in Sources */, + 0279FD60230C189400AFD2CB /* NibInstantiable.swift in Sources */, C9835CDC2281BECD00DB672B /* RequiredFieldValidator.swift in Sources */, + 028672CF22FB3FFD00C6326A /* Date+Extension.swift in Sources */, + 0279FD62230C1B2E00AFD2CB /* SystemInfo.swift in Sources */, C9835CD42281B8A800DB672B /* ValidAgeValidator.swift in Sources */, + 028672C522FB37AE00C6326A /* Float+Extension.swift in Sources */, + 0279FD5A230C174800AFD2CB /* UIViewController+Extension.swift in Sources */, + 028672C922FB387800C6326A /* Int+Extension.swift in Sources */, C9835CEC2281F01200DB672B /* EmailValidator.swift in Sources */, C92250C3227B527800ABFB38 /* DateFormatter+Extension.swift in Sources */, C92250C0227B527800ABFB38 /* Decimal+Extension.swift in Sources */, @@ -360,15 +432,20 @@ C9835CEF2282042B00DB672B /* AlphabetValidator.swift in Sources */, C99B09B522B27C5E00AADF3B /* Encodable+Extensions.swift in Sources */, 0259946C22C53A0A0017850B /* CnpjValidator.swift in Sources */, + 0279FD56230C14A800AFD2CB /* UIView+Extension.swift in Sources */, C92250C2227B527800ABFB38 /* String+Extension.swift in Sources */, + 0279FD48230C0E6900AFD2CB /* UIActivityIndicatorView+Extension.swift in Sources */, C9ED4A5B229D91F100939BFB /* Encodable+Extension.swift in Sources */, + 0279FD4C230C11F000AFD2CB /* UIColor+Extension.swift in Sources */, C9835CED228201B600DB672B /* PasswordValidator.swift in Sources */, C9835D02228320FF00DB672B /* UITextField+Extension.swift in Sources */, - C92250C4227B527800ABFB38 /* Colletion+Extension.swift in Sources */, + 0279FD50230C135300AFD2CB /* UIFont+Extension.swift in Sources */, + C92250C4227B527800ABFB38 /* Collection+Extension.swift in Sources */, 0259946822C52F7F0017850B /* CpfValidator.swift in Sources */, C9835CEE2282030600DB672B /* FutureDateValidator.swift in Sources */, C99B09B722B27CC800AADF3B /* Decode+Extension.swift in Sources */, C92250C1227B527800ABFB38 /* NumberFormatter+Extension.swift in Sources */, + 0279FD54230C147300AFD2CB /* UILabel+Extension.swift in Sources */, C9835CF12282065B00DB672B /* CustomValidator.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -386,10 +463,17 @@ 0259946A22C531400017850B /* CpfValidatorTests.swift in Sources */, C9835CFA2283135200DB672B /* PasswordValidatorTests.swift in Sources */, C9835D0422833FBD00DB672B /* UITextFieldTests.swift in Sources */, + 028672CD22FB3D1C00C6326A /* IntTests.swift in Sources */, 0259946E22C53B2B0017850B /* CnpjValidatorTests.swift in Sources */, + 0279FD4E230C123D00AFD2CB /* UIColorTests.swift in Sources */, + 0279FD4A230C0EB000AFD2CB /* UIActivityIndicatorViewTests.swift in Sources */, C9ED4A5D229D920800939BFB /* EncodableTests.swift in Sources */, + 028672D122FB591100C6326A /* DateTests.swift in Sources */, + 0279FD5C230C177400AFD2CB /* UIViewControllerTests.swift in Sources */, C9835CF8228220B300DB672B /* ValidAgeValidatorTests.swift in Sources */, + 0279FD58230C14EA00AFD2CB /* UIViewTests.swift in Sources */, C92250CE227B62C700ABFB38 /* NumberFormatterTests.swift in Sources */, + 028672C722FB381000C6326A /* FloatTests.swift in Sources */, C90551D122B27F4900FC600A /* DecodableTests.swift in Sources */, C92250CC227B5FCB00ABFB38 /* DateFormatterTests.swift in Sources */, C92250CA227B57FB00ABFB38 /* CollectionTests.swift in Sources */, diff --git a/UtilitiesCore/Extensions/Colletion+Extension.swift b/UtilitiesCore/Extensions/Collection+Extension.swift similarity index 100% rename from UtilitiesCore/Extensions/Colletion+Extension.swift rename to UtilitiesCore/Extensions/Collection+Extension.swift diff --git a/UtilitiesCore/Extensions/Date+Extension.swift b/UtilitiesCore/Extensions/Date+Extension.swift new file mode 100644 index 0000000..d82184c --- /dev/null +++ b/UtilitiesCore/Extensions/Date+Extension.swift @@ -0,0 +1,43 @@ +// +// Date+Extension.swift +// UtilitiesCore +// +// Created by Luca Saldanha Schifino on 07/08/19. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public extension Date { + + /// String describing elapsed time from date to now. + var brazilianElapsedInterval: String { + let interval = Calendar.current.dateComponents([.year, .month, .day, .hour], from: self, to: Date()) + + if let year = interval.year, year > 0 { + return year == 1 ? "há \(year)" + " " + "ano" : + "há \(year)" + " " + "anos" + } else if let month = interval.month, month > 0 { + return month == 1 ? "há \(month)" + " " + "mês" : + "há \(month)" + " " + "meses" + } else if let day = interval.day, day > 0 { + return day == 1 ? "há \(day)" + " " + "dia" : + "há \(day)" + " " + "dias" + } else if let hour = interval.hour, hour > 0 { + return hour == 1 ? "há \(hour)" + " " + "hora" : + "há \(hour)" + " " + "horas" + } else { + return "agora" + } + } + + /// Returns String from date. + /// + /// - Parameter format: Date format. + /// - Returns: Date's String. + func getString(withFormat format: String) -> String { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = format + return dateFormatter.string(from: self) + } +} diff --git a/UtilitiesCore/Extensions/Float+Extension.swift b/UtilitiesCore/Extensions/Float+Extension.swift new file mode 100644 index 0000000..fe56ff2 --- /dev/null +++ b/UtilitiesCore/Extensions/Float+Extension.swift @@ -0,0 +1,17 @@ +// +// Float+Extension.swift +// UtilitiesCore +// +// Created by Luca Saldanha Schifino on 22/03/2018. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public extension Float { + + /// Returns Float's String value with comma and two decimals. + var cleanValue: String { + return String(format: "%.2f",self).replacingOccurrences(of: ".", with: ",") + } +} diff --git a/UtilitiesCore/Extensions/Int+Extension.swift b/UtilitiesCore/Extensions/Int+Extension.swift new file mode 100644 index 0000000..4bd8e42 --- /dev/null +++ b/UtilitiesCore/Extensions/Int+Extension.swift @@ -0,0 +1,33 @@ +// +// Int+Extension.swift +// UtilitiesCore +// +// Created by Betina Pereira de Farias on 03/12/18. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public extension Int { + + /// Returns price String from cents. + var priceStringFromCents: String? { + let formatter = NumberFormatter.brazilianCurrencyFormatter + let amountFloat = Float(self) + let price = amountFloat/100 + guard let priceString = formatter.string(from: NSNumber(value: price)) else { + return nil + } + return priceString + } + + /// Returns the Int's representation on a badge. + var badgeValue: String? { + if self > 99 { + return "99+" + } else if self <= 0 { + return nil + } + return String(self) + } +} diff --git a/UtilitiesCore/Extensions/String+Extension.swift b/UtilitiesCore/Extensions/String+Extension.swift index feb9f9c..b2cabdd 100644 --- a/UtilitiesCore/Extensions/String+Extension.swift +++ b/UtilitiesCore/Extensions/String+Extension.swift @@ -8,68 +8,38 @@ import Foundation -public extension String { - /// Returns a String removing all whitespaces, not only the leading/trailing but also in the middle of the string - var removingWhitespaces: String { - return components(separatedBy: .whitespaces).joined() - } - - /// Returns a String removing the leading/trailing whitespaces and new lines - var trimmingWhitespacesAndNewLines: String { - return trimmingCharacters(in: .whitespacesAndNewlines) - } - - /// Transform String date from one format to another - /// - /// - Parameters: - /// - receivingFormat: actual string date format - /// - transforming: new date format - /// - Returns: String with the new format or nil if fail - func transformDateFormat(_ receivingFormat: String, new transforming: String) -> String? { - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = receivingFormat - let date = dateFormatter.date(from: self) - - dateFormatter.dateFormat = transforming - - guard let unDate = date else { return nil } - let stringFormatted = dateFormatter.string(from: unDate) - - return stringFormatted - } -} - +// MARK: - General public extension String { /// Returns a String containing only numbers or an empty String var numbersOnly: String { return components(separatedBy: CharacterSet.decimalDigits.inverted).joined() } - + /// Verify if the string has one or more numbers var hasNumbers: Bool { return rangeOfCharacter(from: .decimalDigits, options: .literal, range: nil) != nil } - + /// Verify if the string has only numbers var hasOnlyNumbers: Bool { return rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil } - + /// Returns a String containing only letters or an empty String var lettersOnly: String { return components(separatedBy: CharacterSet.letters.inverted).joined() } - + /// Verify if the string has one or more letters var hasLetters: Bool { return rangeOfCharacter(from: .letters, options: .numeric, range: nil) != nil } - + /// Verify if the string has only letters var hasOnlyLetters: Bool { return rangeOfCharacter(from: CharacterSet.letters.inverted) == nil } - + /// Verify if the string contains at least one letter and one number var isAlphaNumeric: Bool { let hasLetters = rangeOfCharacter(from: .letters, options: .numeric, range: nil) != nil @@ -77,8 +47,63 @@ public extension String { let comps = components(separatedBy: .alphanumerics) return comps.joined(separator: "").isEmpty && hasLetters && hasNumbers } + + /// Returns a String removing all whitespaces, not only the leading/trailing but also in the middle of the string + var removingWhitespaces: String { + return components(separatedBy: .whitespaces).joined() + } + + /// Returns a String removing the leading/trailing whitespaces and new lines + var trimmingWhitespacesAndNewLines: String { + return trimmingCharacters(in: .whitespacesAndNewlines) + } + +} + +// MARK: - Localized +public extension String { + + /// Returns localized string from key. + /// + /// - Returns: NSLocalizedString + func localized() -> String { + return NSLocalizedString(self, comment: "") + } +} + +// MARK: - Date +public extension String { + /// Get Date from string. + /// + /// - Parameter inputFormat: String's input format. Example: "23/04/2014" is "dd/MM/yyyy" + /// - Returns: Date + func getDate(withInputFormat inputFormat: String) -> Date? { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = inputFormat + return dateFormatter.date(from: self) + } + + /// Transform String date from one format to another + /// + /// - Parameters: + /// - receivingFormat: actual string date format + /// - transforming: new date format + /// - Returns: String with the new format or nil if fail + func transformDateFormat(_ receivingFormat: String, new transforming: String) -> String? { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = receivingFormat + let date = dateFormatter.date(from: self) + + dateFormatter.dateFormat = transforming + + guard let unDate = date else { return nil } + let stringFormatted = dateFormatter.string(from: unDate) + + return stringFormatted + } } +// MARK: - Dictionary public extension String { /// Dictionary from string JSON format var toDictionary: [String: Any] { @@ -93,6 +118,7 @@ public extension String { } } +// MARK: - Currency public extension String { /// Get number if string is brazilian currency or return nil var brazilianCurrencyNumber: NSNumber? { @@ -104,6 +130,46 @@ public extension String { return value } + /// Get price String amount in cents + var amountCentsFormat: Int? { + let value = self.replacingOccurrences(of: "R$ ", with: "") + .replacingOccurrences(of: ".", with: "") + .replacingOccurrences(of: ",", with: "") + .trimmingCharacters(in: .whitespaces) + guard !value.isEmpty else { + return nil + } + return Int(value) + } + + // Formatting text for currency textField + var textFieldCurrencyFormat: String? { + let formatter = NumberFormatter.brazilianCurrencyFormatter + var amountWithPrefix = self + + do { + // remove from String: "$", ".", "," + let regex = try NSRegularExpression(pattern: "[^0-9]", options: .caseInsensitive) + amountWithPrefix = regex.stringByReplacingMatches(in: amountWithPrefix, + options: NSRegularExpression.MatchingOptions(rawValue: 0), + range: NSRange(location: 0, length: count), + withTemplate: "") + } catch { + return nil + } + + let double = (amountWithPrefix as NSString).doubleValue + let number = NSNumber(value: (double / 100)) + + // if first number is 0 or all numbers were deleted + guard number != 0 else { return nil } + return formatter.string(from: number) ?? nil + } +} + +// MARK: - Html +public extension String { + /// Transform string in html format to NSAttributedString with the layout of html var htmlToAttributedString: NSAttributedString? { guard let data = data(using: .utf8) else { return NSAttributedString() } @@ -114,7 +180,42 @@ public extension String { return NSAttributedString() } } + + /// Transform string in html format to NSMutableAttributedString using font and color attributes passed as parameter. + /// + /// - Parameters: + /// - font: UIFont to be used. + /// - fontSize: CGFloat for the UIFont's size. + /// - color: UIColor to be used. + /// - Returns: NSMutableAttributedString + func htmlAttributed(using font: String, fontSize: CGFloat, color: UIColor) -> NSMutableAttributedString? { + do { + let htmlCSSString = " \(self)" + + guard let data = htmlCSSString.data(using: String.Encoding.utf8) else { + return nil + } + + return try NSMutableAttributedString(data: data, + options: [.documentType: NSAttributedString.DocumentType.html, + .characterEncoding: String.Encoding.utf8.rawValue], + documentAttributes: nil) + } catch { + return nil + } + } +} +// MARK: - Range +public extension String { + /// Create a substring based on the range passed /// /// - Parameter range: range to create the substring @@ -123,23 +224,23 @@ public extension String { let endIndex = self.index(self.startIndex, offsetBy: range.upperBound) return String(self[startIndex..) -> Substring { return self[index(at: range.lowerBound)...index(at: range.upperBound)] } - + subscript(range: PartialRangeUpTo) -> Substring { return self[..) -> Substring { return self[...index(at: range.upperBound)] } - + subscript(range: PartialRangeFrom) -> Substring { return self[index(at: range.lowerBound)...] } - + internal func index(at offset: Int) -> String.Index { return index(startIndex, offsetBy: offset) } diff --git a/UtilitiesCore/Extensions/UIActivityIndicatorView+Extension.swift b/UtilitiesCore/Extensions/UIActivityIndicatorView+Extension.swift new file mode 100644 index 0000000..92516c9 --- /dev/null +++ b/UtilitiesCore/Extensions/UIActivityIndicatorView+Extension.swift @@ -0,0 +1,39 @@ +// +// UIActivityIndicatorView+Extension.swift +// UtilitiesCore +// +// Created by Luca Saldanha Schifino on 18/12/2017. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public extension UIActivityIndicatorView { + + /// Starts animating UIActivityIndicator and shows it. + /// If a UIRefreshControl is passed as parameter, it only starts animating if refreshControl is not currently animating. + /// + /// - Parameter refreshControl: UIRefreshControl that loads the same activity as the UIActivityIndicator. + func startLoad(withRefreshControl refreshControl: UIRefreshControl? = nil) { + if refreshControl?.isRefreshing == true { + isHidden = true + stopAnimating() + return + } + isHidden = false + startAnimating() + } + + /// Stops animating UIActivityIndicator and hides it. + /// If a UIRefreshControl is passed as parameter, it ends its refreshing as well as stops the UIActivityIndicator. + /// + /// - Parameters: + /// - refreshControl: UIRefreshControl that loads the same activity as the UIActivityIndicator. + func stopLoad(withRefreshControl refreshControl: UIRefreshControl? = nil) { + if refreshControl?.isRefreshing == true { + refreshControl?.endRefreshing() + } + isHidden = true + stopAnimating() + } +} diff --git a/UtilitiesCore/Extensions/UIColor+Extension.swift b/UtilitiesCore/Extensions/UIColor+Extension.swift new file mode 100644 index 0000000..ac7fb30 --- /dev/null +++ b/UtilitiesCore/Extensions/UIColor+Extension.swift @@ -0,0 +1,49 @@ +// +// UIColor+Extension.swift +// UtilitiesCore +// +// Created by Betina Pereira de Farias on 27/11/18. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public extension UIColor { + + /// UIColor's current hex String. + var hexString: String? { + var red: CGFloat = 0 + var green: CGFloat = 0 + var blue: CGFloat = 0 + var alpha: CGFloat = 0 + self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) + return String( + format: "%02X%02X%02X", + Int(red * 0xff), + Int(green * 0xff), + Int(blue * 0xff) + ) + } + + /// Gets an UIColor from a hex String. + /// + /// - Parameter hex: String containing the hex value. + /// - Returns: UIColor + static func hexStringToColor(hex:String) -> UIColor { + var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() + if (cString.hasPrefix("#")) { + cString.remove(at: cString.startIndex) + } + if ((cString.count) != 6) { + return UIColor.gray + } + var rgbValue:UInt32 = 0 + Scanner(string: cString).scanHexInt32(&rgbValue) + return UIColor( + red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, + green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, + blue: CGFloat(rgbValue & 0x0000FF) / 255.0, + alpha: CGFloat(1.0) + ) + } +} diff --git a/UtilitiesCore/Extensions/UIFont+Extension.swift b/UtilitiesCore/Extensions/UIFont+Extension.swift new file mode 100644 index 0000000..82f3258 --- /dev/null +++ b/UtilitiesCore/Extensions/UIFont+Extension.swift @@ -0,0 +1,25 @@ +// +// UIFont+Extension.swift +// UtilitiesCore +// +// Created by Betina Pereira de Farias on 27/11/18. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public extension UIFont { + + /// Returns an specific UIFont for a family and size. If none is found, returns the system font. + /// + /// - Parameters: + /// - family: Font family. Example: "Montserrat-Bold" + /// - size: CGFloat for UIFont's size + /// - Returns: UIFont + static func font(ofFamily family: String, withSize size: CGFloat) -> UIFont { + guard let font = UIFont(name: family, size: size) else { + return .systemFont(ofSize: size) + } + return font + } +} diff --git a/UtilitiesCore/Extensions/UILabel+Extension.swift b/UtilitiesCore/Extensions/UILabel+Extension.swift new file mode 100644 index 0000000..4c60183 --- /dev/null +++ b/UtilitiesCore/Extensions/UILabel+Extension.swift @@ -0,0 +1,23 @@ +// +// UILabel+Extension.swift +// UtilitiesCore +// +// Created by Betina Pereira de Farias on 28/11/18. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public extension UILabel { + + /// Adds spacing in between charactes. + /// + /// - Parameter value: Float for spacing. Default: 3 + func addCharacterSpacing(_ value: Float = 3) { + if let text = self.text, !text.isEmpty { + let attributedString = NSMutableAttributedString(string: text) + attributedString.addAttribute(.kern, value: value, range: .init(location: 0, length: attributedString.length)) + self.attributedText = attributedString + } + } +} diff --git a/UtilitiesCore/Extensions/UIView+Extension.swift b/UtilitiesCore/Extensions/UIView+Extension.swift new file mode 100644 index 0000000..b47ba2c --- /dev/null +++ b/UtilitiesCore/Extensions/UIView+Extension.swift @@ -0,0 +1,48 @@ +// +// UIView+Extension.swift +// UtilitiesCore +// +// Created by Betina Pereira de Farias on 30/11/18. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public extension UIView { + + static var className: String { + let str = String(describing: type(of: self)) + guard str.hasSuffix(".Type") else { + return str + } + return String(str[..(type: T.Type, animationDuration: TimeInterval? = nil) { + for subview in subviews where subview is T { + if let duration = animationDuration { + UIView.animate(withDuration: duration, animations: { + subview.alpha = 0 + }, completion: { _ in + subview.removeFromSuperview() + }) + } else { + subview.removeFromSuperview() + } + } + } + + func hasSubviewOf(type: T.Type) -> Bool { + guard getSubviewOf(type: type) != nil else { + return false + } + return true + } + + func getSubviewOf(type: T.Type) -> UIView? { + for subview in subviews where subview is T { + return subview + } + return nil + } +} diff --git a/UtilitiesCore/Extensions/UIViewController+Extension.swift b/UtilitiesCore/Extensions/UIViewController+Extension.swift new file mode 100644 index 0000000..288ded0 --- /dev/null +++ b/UtilitiesCore/Extensions/UIViewController+Extension.swift @@ -0,0 +1,26 @@ +// +// UIViewController+Extension.swift +// UtilitiesCore +// +// Created by João Pedro De Souza Coutinho on 22/07/19. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public extension UIViewController { + + /// Removes back button text to the View Controller. + /// This won't remove the text on the current UIViewController, just on the back button of the pushed view controller. + func removeBackButtonText() { + navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) + } + + /// Sets Navigation Bar transparent. + /// + /// - Parameter isTransparent: Should navigation bar be set as transparent. + func setNavigationBarTransparent(_ isTransparent: Bool) { + self.navigationController?.navigationBar.setBackgroundImage(isTransparent ? UIImage() : nil, for: UIBarMetrics.default) + self.navigationController?.navigationBar.shadowImage = isTransparent ? UIImage() : nil + } +} diff --git a/UtilitiesCore/Resources/NibInstantiable.swift b/UtilitiesCore/Resources/NibInstantiable.swift new file mode 100644 index 0000000..c93634d --- /dev/null +++ b/UtilitiesCore/Resources/NibInstantiable.swift @@ -0,0 +1,21 @@ +// +// NibInstantiable.swift +// UtilitiesCore +// +// Created by Luca Saldanha Schifino on 20/08/19. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public protocol NibInstantiatable { + static func instantiateFromNib(bundle: Bundle?) -> Self? +} + +public extension NibInstantiatable where Self: UIView { + static func instantiateFromNib(bundle: Bundle?) -> Self? { + let nibName = Self.className + let arrayViews = UINib(nibName: nibName, bundle: bundle).instantiate(withOwner: nil, options: nil) + return arrayViews.first as? Self + } +} diff --git a/UtilitiesCore/Resources/NibRegistrableView.swift b/UtilitiesCore/Resources/NibRegistrableView.swift new file mode 100644 index 0000000..831786b --- /dev/null +++ b/UtilitiesCore/Resources/NibRegistrableView.swift @@ -0,0 +1,56 @@ +// +// NibRegistrableView.swift +// UtilitiesCore +// +// Created by Luca Saldanha Schifino on 20/08/19. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public protocol NibRegistrableView: UIView { + static var nibName: String { get } + static var reuseId: String { get } +} + +public extension NibRegistrableView { + static var nibName: String { return className } + static var reuseId: String { return className } + static var nib: UINib { return UINib(nibName: nibName, bundle: Bundle(for: self)) } + + static func instantiateFromNib() -> Self? { + return self.nib.instantiate(withOwner: nil, options: nil).first as? Self + } +} + +public typealias NibRegistrableTableViewCell = NibRegistrableView & UITableViewCell +public typealias NibRegistrableCollectionViewCell = NibRegistrableView & UICollectionViewCell +public typealias NibRegistrableTableViewHeaderFooterView = NibRegistrableView & UITableViewHeaderFooterView + +public extension UITableView { + func registerNib(for cellClass: NibRegistrableTableViewCell.Type) { + register(cellClass.nib, forCellReuseIdentifier: cellClass.reuseId) + } + + func registerHeaderNib(for headerFooterClass: NibRegistrableTableViewHeaderFooterView.Type) { + register(headerFooterClass.nib, forHeaderFooterViewReuseIdentifier: headerFooterClass.reuseId) + } + + func dequeueReusableCell() -> T? { + return dequeueReusableCell(withIdentifier: T.reuseId) as? T + } + + func dequeueReusableHeaderFooter() -> T? { + return dequeueReusableHeaderFooterView(withIdentifier: T.reuseId) as? T + } +} + +public extension UICollectionView { + func registerNib(for cellClass: NibRegistrableCollectionViewCell.Type) { + register(cellClass.nib, forCellWithReuseIdentifier: cellClass.reuseId) + } + + func dequeueReusableCell(for indexPath: IndexPath) -> T? { + return dequeueReusableCell(withReuseIdentifier: T.reuseId, for: indexPath) as? T + } +} diff --git a/UtilitiesCore/Resources/SystemInfo.swift b/UtilitiesCore/Resources/SystemInfo.swift new file mode 100644 index 0000000..6f55166 --- /dev/null +++ b/UtilitiesCore/Resources/SystemInfo.swift @@ -0,0 +1,44 @@ +// +// SystemInfo.swift +// UtilitiesCore +// +// Created by Luca Saldanha Schifino on 20/08/19. +// Copyright © 2019 4all. All rights reserved. +// + +import Foundation + +public class SystemInfo { + + public static var deviceName: String { + return UIDevice.current.name + } + + public static var systemName: String { + return UIDevice.current.systemName + } + + public static var systemVersion: String { + return UIDevice.current.systemVersion + } + + public static var deviceUUID: String? { + return UIDevice.current.identifierForVendor?.uuidString + } + + public static var bundleVersion: String? { + guard let dictionary = Bundle.main.infoDictionary, + let build = dictionary["CFBundleVersion"] as? String else { + return nil + } + return build + } + + public static var appVersion: String? { + guard let dictionary = Bundle.main.infoDictionary, + let version = dictionary["CFBundleShortVersionString"] as? String else { + return nil + } + return version + } +} diff --git a/UtilitiesCoreTests/Extensions/DateTests.swift b/UtilitiesCoreTests/Extensions/DateTests.swift new file mode 100644 index 0000000..843178b --- /dev/null +++ b/UtilitiesCoreTests/Extensions/DateTests.swift @@ -0,0 +1,42 @@ +// +// DateTests.swift +// UtilitiesCoreTests +// +// Created by João Pedro De Souza Coutinho on 22/07/19. +// Copyright © 2019 4all. All rights reserved. +// + +import XCTest +@testable import UtilitiesCore + +class DateExtensionTests: XCTestCase { + + func testBrazilianElapsedInterval() { + let nowDate = Date(timeIntervalSinceNow: 1) + let nowElapse = "agora" + XCTAssertEqual(nowDate.brazilianElapsedInterval, nowElapse) + + let hourDate = Date(timeIntervalSinceNow: -3 * 60 * 60) + let hourElapse = "há 3 horas" + XCTAssertEqual(hourDate.brazilianElapsedInterval, hourElapse) + + let dayDate = Date(timeIntervalSinceNow: -4 * 24 * 60 * 60) + let dayElapse = "há 4 dias" + XCTAssertEqual(dayDate.brazilianElapsedInterval, dayElapse) + + let monthDate = Date(timeIntervalSinceNow: -5 * 31 * 24 * 60 * 60) + let monthElapse = "há 5 meses" + XCTAssertEqual(monthDate.brazilianElapsedInterval, monthElapse) + + let yearDate = Date(timeIntervalSinceNow: -6 * 12 * 31 * 24 * 60 * 60) + let yearElapse = "há 6 anos" + XCTAssertEqual(yearDate.brazilianElapsedInterval, yearElapse) + } + + func testGetString() { + let timestamp = Date(timeIntervalSince1970: 784166400) + let expectedResult = "06/11/1994 10:00:00" + let dateString = timestamp.getString(withFormat: "dd/MM/yyyy hh:mm:ss") + XCTAssertEqual(expectedResult, dateString) + } +} diff --git a/UtilitiesCoreTests/Extensions/FloatTests.swift b/UtilitiesCoreTests/Extensions/FloatTests.swift new file mode 100644 index 0000000..d7cd757 --- /dev/null +++ b/UtilitiesCoreTests/Extensions/FloatTests.swift @@ -0,0 +1,18 @@ +// +// FloatTests.swift +// UtilitiesCoreTests +// +// Created by Betina Pereira de Farias on 14/03/19. +// Copyright © 2019 4all. All rights reserved. +// + +import XCTest +@testable import UtilitiesCore + +class FloatTests: XCTestCase { + func testFloatCleanValue() { + let floatValue: Float = 20.5 + let expectedValue = "20,50" + XCTAssertEqual(floatValue.cleanValue, expectedValue) + } +} diff --git a/UtilitiesCoreTests/Extensions/IntTests.swift b/UtilitiesCoreTests/Extensions/IntTests.swift new file mode 100644 index 0000000..5b9e390 --- /dev/null +++ b/UtilitiesCoreTests/Extensions/IntTests.swift @@ -0,0 +1,29 @@ +// +// IntTests.swift +// UtilitiesCoreTests +// +// Created by Betina Pereira de Farias on 14/03/19. +// Copyright © 2019 4all. All rights reserved. +// + +import XCTest +@testable import UtilitiesCore + +class IntTests: XCTestCase { + func testConvertCentsToString() { + let cents: Int = 1000 + let expectedValue = "R$ 10,00" + XCTAssertEqual(cents.priceStringFromCents ?? "", expectedValue) + } + + func testBadgeValue() { + let normalInt: Int = 25 + XCTAssertEqual(normalInt.badgeValue, "25") + + let highInt: Int = 200 + XCTAssertEqual(highInt.badgeValue, "99+") + + let negativeInt: Int = -10 + XCTAssertNil(negativeInt.badgeValue) + } +} diff --git a/UtilitiesCoreTests/Extensions/StringTests.swift b/UtilitiesCoreTests/Extensions/StringTests.swift index 1ad3138..0452aa7 100644 --- a/UtilitiesCoreTests/Extensions/StringTests.swift +++ b/UtilitiesCoreTests/Extensions/StringTests.swift @@ -113,4 +113,33 @@ class StringTests: XCTestCase { XCTAssertEqual(number, 1200.12) } + + func testCurrencyFormat() { + let possibleValues = ["5000", "R$ 5000", "5,000", "R$ 50,00"] + for value in possibleValues { + XCTAssertEqual(value.textFieldCurrencyFormat, "R$\u{00a0}50,00") + } + } + + func testAmountCentsFormat() { + let cents = 1000 + guard let amountString = cents.priceStringFromCents else { + XCTFail("Couldn't get price string") + return + } + XCTAssertEqual(amountString, "R$ 10,00") + + guard let centsFromString = amountString.amountCentsFormat else { + XCTFail("Couldn't get cents amount") + return + } + XCTAssertEqual(centsFromString, cents) + } + + func testGetDate() { + let dateString = "06/11/1994 22:00:00" + let expectedResult = Date(timeIntervalSince1970: 784166400) + let date = dateString.getDate(withInputFormat: "dd/MM/yyyy HH:mm:ss") + XCTAssertEqual(expectedResult, date) + } } diff --git a/UtilitiesCoreTests/Extensions/UIActivityIndicatorViewTests.swift b/UtilitiesCoreTests/Extensions/UIActivityIndicatorViewTests.swift new file mode 100644 index 0000000..f578f88 --- /dev/null +++ b/UtilitiesCoreTests/Extensions/UIActivityIndicatorViewTests.swift @@ -0,0 +1,75 @@ +// +// UIActivityIndicatorViewTests.swift +// UtilitiesCoreTests +// +// Created by Betina Pereira de Farias on 14/03/19. +// Copyright © 2019 4all. All rights reserved. +// + +import XCTest +@testable import UtilitiesCore + +class UIActivityIndicatorViewTests: XCTestCase { + + var refreshControl: UIRefreshControl! + var activity: UIActivityIndicatorView! + + override func setUp() { + super.setUp() + refreshControl = UIRefreshControl() + refreshControl.endRefreshing() + activity = UIActivityIndicatorView() + activity.isHidden = true + activity.stopAnimating() + } + + override func tearDown() { + super.tearDown() + refreshControl = nil + activity = nil + } + + func testStartLoad() { + // Testing with refresh control animating + refreshControl.beginRefreshing() + activity.startLoad(withRefreshControl: refreshControl) + XCTAssertTrue(refreshControl.isRefreshing) + XCTAssertTrue(activity.isHidden) + XCTAssertFalse(activity.isAnimating) + + // Testing with refresh control not animating + refreshControl.endRefreshing() + activity.startLoad(withRefreshControl: refreshControl) + XCTAssertFalse(refreshControl.isRefreshing) + XCTAssertFalse(activity.isHidden) + XCTAssertTrue(activity.isAnimating) + + // Testing without refresh control + activity.startLoad() + XCTAssertFalse(activity.isHidden) + XCTAssertTrue(activity.isAnimating) + } + + func testStopLoad() { + // Testing with Refresh control animating + refreshControl.beginRefreshing() + activity.stopLoad(withRefreshControl: refreshControl) + XCTAssertFalse(refreshControl.isRefreshing) + XCTAssertTrue(activity.isHidden) + XCTAssertFalse(activity.isAnimating) + + // Testing with Refresh control not animating + refreshControl.endRefreshing() + activity.startAnimating() + activity.stopLoad(withRefreshControl: refreshControl) + XCTAssertFalse(refreshControl.isRefreshing) + XCTAssertTrue(activity.isHidden) + XCTAssertFalse(activity.isAnimating) + + // Testing without refresh control + activity.startAnimating() + activity.stopLoad() + XCTAssertTrue(activity.isHidden) + XCTAssertFalse(activity.isAnimating) + } +} diff --git a/UtilitiesCoreTests/Extensions/UIColorTests.swift b/UtilitiesCoreTests/Extensions/UIColorTests.swift new file mode 100644 index 0000000..de188ee --- /dev/null +++ b/UtilitiesCoreTests/Extensions/UIColorTests.swift @@ -0,0 +1,28 @@ +// +// UIColorTests.swift +// UtilitiesCoreTests +// +// Created by Luca Saldanha Schifino on 14/03/19. +// Copyright © 2019 4all. All rights reserved. +// + +import XCTest +@testable import UtilitiesCore + +class UIColorTests: XCTestCase { + + func testHexStringToColor() { + let possibleValues = ["#ffffff", "ffffff"] + for value in possibleValues { + let color = UIColor.hexStringToColor(hex: value) + let expectedResult = UIColor(red: 1, green: 1, blue: 1, alpha: 1) + XCTAssertEqual(color, expectedResult) + } + } + + func testColorToHexString() { + let color = UIColor(red: 1, green: 1, blue: 1, alpha: 1) + let hex = color.hexString + XCTAssertEqual(hex, "FFFFFF") + } +} diff --git a/UtilitiesCoreTests/Extensions/UIViewControllerTests.swift b/UtilitiesCoreTests/Extensions/UIViewControllerTests.swift new file mode 100644 index 0000000..967caee --- /dev/null +++ b/UtilitiesCoreTests/Extensions/UIViewControllerTests.swift @@ -0,0 +1,24 @@ +// +// UIViewControllerTests.swift +// UtilitiesCoreTests +// +// Created by João Pedro De Souza Coutinho on 22/07/19. +// Copyright © 2019 4all. All rights reserved. +// + +import XCTest +@testable import UtilitiesCore + +class UIViewControllerTests: XCTestCase { + + func testRemoveBackButtonText() { + let viewController = UIViewController() + viewController.navigationItem.backBarButtonItem = UIBarButtonItem(title: "Button", + style: .plain, + target: viewController.self, + action: nil) + viewController.removeBackButtonText() + + XCTAssert(viewController.navigationItem.backBarButtonItem?.title == "") + } +} diff --git a/UtilitiesCoreTests/Extensions/UIViewTests.swift b/UtilitiesCoreTests/Extensions/UIViewTests.swift new file mode 100644 index 0000000..23811f5 --- /dev/null +++ b/UtilitiesCoreTests/Extensions/UIViewTests.swift @@ -0,0 +1,28 @@ +// +// UIViewTests.swift +// UtilitiesCoreTests +// +// Created by Luca Saldanha Schifino on 20/08/19. +// Copyright © 2019 4all. All rights reserved. +// + +import XCTest +@testable import UtilitiesCore + +class TestView: UIView { } + +class UIViewTests: XCTestCase { + + func testViewExtensionMethods() { + let contentView = UIView() + let childView = TestView() + contentView.addSubview(childView) + XCTAssert(contentView.hasSubviewOf(type: TestView.self)) + + let subview = contentView.getSubviewOf(type: TestView.self) + XCTAssertNotNil(subview) + + contentView.removeSubviewOf(type: TestView.self) + XCTAssertFalse(contentView.subviews.contains { $0 is TestView }) + } +} From 25848d062ec9c203a1474f274c50833769257da0 Mon Sep 17 00:00:00 2001 From: Luca Schifino Date: Tue, 20 Aug 2019 17:11:44 -0300 Subject: [PATCH 2/4] Fixing date and string tests timezone. --- UtilitiesCore/Extensions/Date+Extension.swift | 9 +++++++-- UtilitiesCore/Extensions/String+Extension.swift | 9 +++++++-- UtilitiesCoreTests/Extensions/DateTests.swift | 2 +- UtilitiesCoreTests/Extensions/StringTests.swift | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/UtilitiesCore/Extensions/Date+Extension.swift b/UtilitiesCore/Extensions/Date+Extension.swift index d82184c..64667e2 100644 --- a/UtilitiesCore/Extensions/Date+Extension.swift +++ b/UtilitiesCore/Extensions/Date+Extension.swift @@ -33,10 +33,15 @@ public extension Date { /// Returns String from date. /// - /// - Parameter format: Date format. + /// - Parameters: + /// - format: Date format. + /// - timezone: TimeZone for the date. If none is passed, the device's locale is used. /// - Returns: Date's String. - func getString(withFormat format: String) -> String { + func getString(withFormat format: String, andTimezone timezone: TimeZone? = nil) -> String { let dateFormatter = DateFormatter() + if let zone = timezone { + dateFormatter.timeZone = zone + } dateFormatter.dateFormat = format return dateFormatter.string(from: self) } diff --git a/UtilitiesCore/Extensions/String+Extension.swift b/UtilitiesCore/Extensions/String+Extension.swift index b2cabdd..4598592 100644 --- a/UtilitiesCore/Extensions/String+Extension.swift +++ b/UtilitiesCore/Extensions/String+Extension.swift @@ -75,10 +75,15 @@ public extension String { public extension String { /// Get Date from string. /// - /// - Parameter inputFormat: String's input format. Example: "23/04/2014" is "dd/MM/yyyy" + /// - Parameters: + /// - inputFormat: String's input format. Example: "23/04/2014" is "dd/MM/yyyy" + /// - timezone: TimeZone for the date. If none is passed, the device's locale is used. /// - Returns: Date - func getDate(withInputFormat inputFormat: String) -> Date? { + func getDate(withInputFormat inputFormat: String, andTimezone timezone: TimeZone? = nil) -> Date? { let dateFormatter = DateFormatter() + if let zone = timezone { + dateFormatter.timeZone = zone + } dateFormatter.dateFormat = inputFormat return dateFormatter.date(from: self) } diff --git a/UtilitiesCoreTests/Extensions/DateTests.swift b/UtilitiesCoreTests/Extensions/DateTests.swift index 843178b..f0beb68 100644 --- a/UtilitiesCoreTests/Extensions/DateTests.swift +++ b/UtilitiesCoreTests/Extensions/DateTests.swift @@ -36,7 +36,7 @@ class DateExtensionTests: XCTestCase { func testGetString() { let timestamp = Date(timeIntervalSince1970: 784166400) let expectedResult = "06/11/1994 10:00:00" - let dateString = timestamp.getString(withFormat: "dd/MM/yyyy hh:mm:ss") + let dateString = timestamp.getString(withFormat: "dd/MM/yyyy hh:mm:ss", andTimezone: TimeZone(abbreviation: "GMT-3")) XCTAssertEqual(expectedResult, dateString) } } diff --git a/UtilitiesCoreTests/Extensions/StringTests.swift b/UtilitiesCoreTests/Extensions/StringTests.swift index 0452aa7..6918fe7 100644 --- a/UtilitiesCoreTests/Extensions/StringTests.swift +++ b/UtilitiesCoreTests/Extensions/StringTests.swift @@ -139,7 +139,7 @@ class StringTests: XCTestCase { func testGetDate() { let dateString = "06/11/1994 22:00:00" let expectedResult = Date(timeIntervalSince1970: 784166400) - let date = dateString.getDate(withInputFormat: "dd/MM/yyyy HH:mm:ss") + let date = dateString.getDate(withInputFormat: "dd/MM/yyyy HH:mm:ss", andTimezone: TimeZone(abbreviation: "GMT-3")) XCTAssertEqual(expectedResult, date) } } From 2003e1f444a7b4b0e367761388540bf1619f1038 Mon Sep 17 00:00:00 2001 From: Luca Schifino Date: Wed, 21 Aug 2019 08:57:51 -0300 Subject: [PATCH 3/4] Fixing nil timezone. --- UtilitiesCore/Extensions/Date+Extension.swift | 6 +++--- UtilitiesCore/Extensions/String+Extension.swift | 6 +++--- UtilitiesCoreTests/Extensions/DateTests.swift | 4 ++-- UtilitiesCoreTests/Extensions/StringTests.swift | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/UtilitiesCore/Extensions/Date+Extension.swift b/UtilitiesCore/Extensions/Date+Extension.swift index 64667e2..8a3e34b 100644 --- a/UtilitiesCore/Extensions/Date+Extension.swift +++ b/UtilitiesCore/Extensions/Date+Extension.swift @@ -37,10 +37,10 @@ public extension Date { /// - format: Date format. /// - timezone: TimeZone for the date. If none is passed, the device's locale is used. /// - Returns: Date's String. - func getString(withFormat format: String, andTimezone timezone: TimeZone? = nil) -> String { + func getString(withFormat format: String, andTimezoneAbbreviation abbreviation: String? = nil) -> String { let dateFormatter = DateFormatter() - if let zone = timezone { - dateFormatter.timeZone = zone + if let abbreviation = abbreviation { + dateFormatter.timeZone = TimeZone(abbreviation: abbreviation) } dateFormatter.dateFormat = format return dateFormatter.string(from: self) diff --git a/UtilitiesCore/Extensions/String+Extension.swift b/UtilitiesCore/Extensions/String+Extension.swift index 4598592..0f3449b 100644 --- a/UtilitiesCore/Extensions/String+Extension.swift +++ b/UtilitiesCore/Extensions/String+Extension.swift @@ -79,10 +79,10 @@ public extension String { /// - inputFormat: String's input format. Example: "23/04/2014" is "dd/MM/yyyy" /// - timezone: TimeZone for the date. If none is passed, the device's locale is used. /// - Returns: Date - func getDate(withInputFormat inputFormat: String, andTimezone timezone: TimeZone? = nil) -> Date? { + func getDate(withInputFormat inputFormat: String, andTimezoneAbbreviation abbreviation: String? = nil) -> Date? { let dateFormatter = DateFormatter() - if let zone = timezone { - dateFormatter.timeZone = zone + if let abbreviation = abbreviation { + dateFormatter.timeZone = TimeZone(abbreviation: abbreviation) } dateFormatter.dateFormat = inputFormat return dateFormatter.date(from: self) diff --git a/UtilitiesCoreTests/Extensions/DateTests.swift b/UtilitiesCoreTests/Extensions/DateTests.swift index f0beb68..5278bda 100644 --- a/UtilitiesCoreTests/Extensions/DateTests.swift +++ b/UtilitiesCoreTests/Extensions/DateTests.swift @@ -35,8 +35,8 @@ class DateExtensionTests: XCTestCase { func testGetString() { let timestamp = Date(timeIntervalSince1970: 784166400) - let expectedResult = "06/11/1994 10:00:00" - let dateString = timestamp.getString(withFormat: "dd/MM/yyyy hh:mm:ss", andTimezone: TimeZone(abbreviation: "GMT-3")) + let expectedResult = "07/11/1994 12:00:00" + let dateString = timestamp.getString(withFormat: "dd/MM/yyyy hh:mm:ss", andTimezoneAbbreviation: "GMT") XCTAssertEqual(expectedResult, dateString) } } diff --git a/UtilitiesCoreTests/Extensions/StringTests.swift b/UtilitiesCoreTests/Extensions/StringTests.swift index 6918fe7..51bd976 100644 --- a/UtilitiesCoreTests/Extensions/StringTests.swift +++ b/UtilitiesCoreTests/Extensions/StringTests.swift @@ -137,9 +137,9 @@ class StringTests: XCTestCase { } func testGetDate() { - let dateString = "06/11/1994 22:00:00" + let dateString = "07/11/1994 00:00:00" let expectedResult = Date(timeIntervalSince1970: 784166400) - let date = dateString.getDate(withInputFormat: "dd/MM/yyyy HH:mm:ss", andTimezone: TimeZone(abbreviation: "GMT-3")) + let date = dateString.getDate(withInputFormat: "dd/MM/yyyy HH:mm:ss", andTimezoneAbbreviation: "GMT") XCTAssertEqual(expectedResult, date) } } From 954dba24528dd611d7276f24a3e25d5da2809ccc Mon Sep 17 00:00:00 2001 From: Luca Schifino Date: Thu, 22 Aug 2019 09:14:35 -0300 Subject: [PATCH 4/4] Updating module version. --- 4allUtilitiesCore.podspec | 2 +- UtilitiesCore/Info.plist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/4allUtilitiesCore.podspec b/4allUtilitiesCore.podspec index 6488edb..28b78c0 100644 --- a/4allUtilitiesCore.podspec +++ b/4allUtilitiesCore.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "4allUtilitiesCore" - s.version = "0.1.0" + s.version = "0.3.0" s.summary = "A utilities core library." # This description is used to generate tags and improve search results. diff --git a/UtilitiesCore/Info.plist b/UtilitiesCore/Info.plist index 64db690..6218651 100644 --- a/UtilitiesCore/Info.plist +++ b/UtilitiesCore/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 0.1.0 + 0.3.0 CFBundleVersion $(CURRENT_PROJECT_VERSION)