-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Hamad Fuad
committed
Apr 14, 2022
1 parent
3032406
commit 8ac172f
Showing
18 changed files
with
677 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,30 @@ | ||
# SwiftExtensions | ||
|
||
A description of this package. | ||
[](https://opensource.org/licenses/MIT) | ||
[](https://swift.org/package-manager/) | ||
[](https://swift.org) | ||
[](https://developer.apple.com/xcode) | ||
 | ||
 | ||
|
||
# Sponsor | ||
[](https://paypal.me/nuralme?country.x=BH&locale.x=en_US) | ||
|
||
# AppStoreReviewsAPI | ||
|
||
A Swift 5.6 implementation of native extensions for iOS, macOS, tvOS, watchOS. | ||
|
||
## Installation | ||
### Swift Package Manager (SPM) | ||
|
||
You can use The Swift Package Manager to install SwiftEmailValidator by adding it to your Package.swift file: | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "MyApp", | ||
targets: [], | ||
dependencies: [ | ||
.Package(url: "https://github.com/ihamadfuad/SwiftExtensions.git", .from: "1.0.0") | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// | ||
// Character.swift | ||
// | ||
// | ||
// Created by Hamad Ali on 14/04/2022. | ||
// | ||
|
||
import Foundation | ||
|
||
public extension Character { | ||
|
||
var isEmoji: Bool { | ||
|
||
let scalarValue = String(self).unicodeScalars.first!.value | ||
|
||
switch scalarValue { | ||
case 0x1F600...0x1F64F, // Emoticons | ||
0x1F300...0x1F5FF, // Misc Symbols and Pictographs | ||
0x1F680...0x1F6FF, // Transport and Map | ||
0x1F1E6...0x1F1FF, // Regional country flags | ||
0x2600...0x26FF, // Misc symbols | ||
0x2700...0x27BF, // Dingbats | ||
0xE0020...0xE007F, // Tags | ||
0xFE00...0xFE0F, // Variation Selectors | ||
0x1F900...0x1F9FF, // Supplemental Symbols and Pictographs | ||
127_000...127_600, // Various asian characters | ||
65024...65039, // Variation selector | ||
9100...9300, // Misc items | ||
8400...8447: // Combining Diacritical Marks for Symbols | ||
return true | ||
default: | ||
return false | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import Foundation | ||
|
||
public extension Collection { | ||
|
||
var hasElements: Bool { | ||
|
||
!isEmpty | ||
} | ||
} | ||
|
||
public extension Collection { | ||
|
||
subscript (safe index: Index) -> Element? { | ||
|
||
indices.contains(index) ? self[index] : nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// | ||
// Data.swift | ||
// | ||
// | ||
// Created by Hamad Ali on 14/04/2022. | ||
// | ||
|
||
import Foundation | ||
|
||
public extension Data { | ||
|
||
func string(encoding: String.Encoding) -> String? { | ||
String(data: self, encoding: encoding) | ||
} | ||
|
||
func json(options: JSONSerialization.ReadingOptions = []) throws -> Any { | ||
try JSONSerialization.jsonObject(with: self, options: options) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
// | ||
// Date.swift | ||
// | ||
// | ||
// Created by Hamad Ali on 14/04/2022. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Convenience comparable | ||
public extension Date { | ||
|
||
func isBetween(_ startDate: Date, _ endDate: Date, includeBounds: Bool = false) -> Bool { | ||
|
||
if includeBounds { | ||
return startDate.compare(self).rawValue * compare(endDate).rawValue >= 0 | ||
} | ||
|
||
return startDate.compare(self).rawValue * compare(endDate).rawValue > 0 | ||
} | ||
|
||
var isInFuture: Bool { | ||
self > Date() | ||
} | ||
|
||
var isInPast: Bool { | ||
self < Date() | ||
} | ||
|
||
var isInToday: Bool { | ||
Calendar.current.isDateInToday(self) | ||
} | ||
|
||
var isInYesterday: Bool { | ||
Calendar.current.isDateInYesterday(self) | ||
} | ||
|
||
var isInTomorrow: Bool { | ||
Calendar.current.isDateInTomorrow(self) | ||
} | ||
|
||
var isInCurrentWeek: Bool { | ||
Calendar.current.isDate(self, equalTo: Date(), toGranularity: .weekOfYear) | ||
} | ||
|
||
var isInCurrentMonth: Bool { | ||
Calendar.current.isDate(self, equalTo: Date(), toGranularity: .month) | ||
} | ||
|
||
var isInCurrentYear: Bool { | ||
return Calendar.current.isDate(self, equalTo: Date(), toGranularity: .year) | ||
} | ||
} | ||
|
||
/// Convenience get | ||
public extension Date { | ||
|
||
/// Number of day in the current week. | ||
var weekday: Int { | ||
return Calendar.current.component(.weekday, from: self) | ||
} | ||
|
||
/// Number of week in the month. | ||
var weekOfMonth: Int { | ||
return Calendar.current.component(.weekOfMonth, from: self) | ||
} | ||
|
||
/// Number of week in the year. | ||
var weekOfYear: Int { | ||
return Calendar.current.component(.weekOfYear, from: self) | ||
} | ||
|
||
var yesterday: Date { | ||
Calendar.current.date(byAdding: .day, value: -1, to: self) ?? Date() | ||
} | ||
|
||
var tomorrow: Date { | ||
Calendar.current.date(byAdding: .day, value: 1, to: self) ?? Date() | ||
} | ||
} | ||
|
||
/// Convenience set/get | ||
public extension Date { | ||
|
||
/// Get and set second | ||
var second: Int { | ||
|
||
get { | ||
return Calendar.current.component(.second, from: self) | ||
} | ||
set { | ||
let allowedRange = Calendar.current.range(of: .second, in: .minute, for: self)! | ||
guard allowedRange.contains(newValue) else { return } | ||
|
||
let currentSeconds = Calendar.current.component(.second, from: self) | ||
let secondsToAdd = newValue - currentSeconds | ||
if let date = Calendar.current.date(byAdding: .second, value: secondsToAdd, to: self) { | ||
self = date | ||
} | ||
} | ||
} | ||
|
||
/// Get and set minute | ||
var minute: Int { | ||
|
||
get { | ||
return Calendar.current.component(.minute, from: self) | ||
} | ||
set { | ||
|
||
let allowedRange = Calendar.current.range(of: .minute, in: .hour, for: self)! | ||
|
||
guard allowedRange.contains(newValue) | ||
else { | ||
return | ||
} | ||
|
||
let currentMinutes = Calendar.current.component(.minute, from: self) | ||
let minutesToAdd = newValue - currentMinutes | ||
|
||
if let date = Calendar.current.date(byAdding: .minute, value: minutesToAdd, to: self) { | ||
|
||
self = date | ||
} | ||
} | ||
} | ||
|
||
/// Get and set hour | ||
var hour: Int { | ||
|
||
get { | ||
return Calendar.current.component(.hour, from: self) | ||
} | ||
set { | ||
|
||
let allowedRange = Calendar.current.range(of: .hour, in: .day, for: self)! | ||
|
||
guard allowedRange.contains(newValue) | ||
else { | ||
return | ||
} | ||
|
||
let currentHour = Calendar.current.component(.hour, from: self) | ||
let hoursToAdd = newValue - currentHour | ||
|
||
if let date = Calendar.current.date(byAdding: .hour, value: hoursToAdd, to: self) { | ||
|
||
self = date | ||
} | ||
} | ||
} | ||
|
||
/// Get and set day | ||
var day: Int { | ||
|
||
get { | ||
return Calendar.current.component(.day, from: self) | ||
} | ||
set { | ||
|
||
let allowedRange = Calendar.current.range(of: .day, in: .month, for: self)! | ||
|
||
guard allowedRange.contains(newValue) | ||
else { | ||
return | ||
} | ||
|
||
let currentDay = Calendar.current.component(.day, from: self) | ||
let daysToAdd = newValue - currentDay | ||
|
||
if let date = Calendar.current.date(byAdding: .day, value: daysToAdd, to: self) { | ||
|
||
self = date | ||
} | ||
} | ||
} | ||
|
||
/// Get and set month | ||
var month: Int { | ||
|
||
get { | ||
return Calendar.current.component(.month, from: self) | ||
} | ||
set { | ||
|
||
let allowedRange = Calendar.current.range(of: .month, in: .year, for: self)! | ||
|
||
guard allowedRange.contains(newValue) | ||
else { | ||
return | ||
} | ||
|
||
let currentMonth = Calendar.current.component(.month, from: self) | ||
let monthsToAdd = newValue - currentMonth | ||
|
||
if let date = Calendar.current.date(byAdding: .month, value: monthsToAdd, to: self) { | ||
|
||
self = date | ||
} | ||
} | ||
} | ||
|
||
/// Get and set year | ||
var year: Int { | ||
|
||
get { | ||
return Calendar.current.component(.year, from: self) | ||
} | ||
set { | ||
|
||
guard newValue > 0 | ||
else { | ||
return | ||
} | ||
|
||
let currentYear = Calendar.current.component(.year, from: self) | ||
let yearsToAdd = newValue - currentYear | ||
|
||
if let date = Calendar.current.date(byAdding: .year, value: yearsToAdd, to: self) { | ||
|
||
self = date | ||
} | ||
} | ||
} | ||
} | ||
|
||
/// Convenience calendar | ||
public extension Date { | ||
|
||
mutating func add(_ component: Calendar.Component, value: Int) { | ||
self = Calendar.current.date(byAdding: component, value: value, to: self)! | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import Foundation | ||
|
||
public func debounced(delay: TimeInterval, | ||
queue: DispatchQueue = .main, | ||
action: @escaping (() -> Void)) -> () -> Void { | ||
|
||
var workItem: DispatchWorkItem? | ||
|
||
return { | ||
workItem?.cancel() | ||
workItem = DispatchWorkItem(block: action) | ||
queue.asyncAfter(deadline: .now() + delay, execute: workItem!) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import Foundation | ||
|
||
public func dispatcher(enter: (VoidBlock) -> Void, _ main: @escaping VoidBlock) { | ||
|
||
let dispatchGroup = DispatchGroup() | ||
|
||
dispatchGroup.enter() | ||
|
||
enter({ | ||
|
||
dispatchGroup.leave() | ||
}) | ||
|
||
dispatchGroup.notify(queue: .main) { | ||
main() | ||
} | ||
} |
Oops, something went wrong.