Stabilize iOS/watchOS/tvOS apps and add cross-platform audit remediation
This commit is contained in:
@@ -9,6 +9,67 @@ import Foundation
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
private enum DateFormatterCache {
|
||||
static let lock = NSLock()
|
||||
|
||||
static let serverDateFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssX"
|
||||
formatter.locale = Locale(identifier: "en_US_POSIX")
|
||||
return formatter
|
||||
}()
|
||||
|
||||
static let plannedDateFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = "yyyy-MM-dd"
|
||||
formatter.locale = Locale(identifier: "en_US_POSIX")
|
||||
return formatter
|
||||
}()
|
||||
|
||||
static let weekDayFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = "EEE"
|
||||
formatter.locale = Locale(identifier: "en_US_POSIX")
|
||||
return formatter
|
||||
}()
|
||||
|
||||
static let monthFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = "MMM"
|
||||
formatter.locale = Locale(identifier: "en_US_POSIX")
|
||||
return formatter
|
||||
}()
|
||||
|
||||
static let dayFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = "d"
|
||||
formatter.locale = Locale(identifier: "en_US_POSIX")
|
||||
return formatter
|
||||
}()
|
||||
|
||||
static func withLock<T>(_ block: () -> T) -> T {
|
||||
lock.lock()
|
||||
defer { lock.unlock() }
|
||||
return block()
|
||||
}
|
||||
}
|
||||
|
||||
private enum DurationFormatterCache {
|
||||
static let lock = NSLock()
|
||||
static let formatter: DateComponentsFormatter = {
|
||||
let formatter = DateComponentsFormatter()
|
||||
formatter.allowedUnits = [.hour, .minute, .second, .nanosecond]
|
||||
return formatter
|
||||
}()
|
||||
|
||||
static func string(from seconds: Double, style: DateComponentsFormatter.UnitsStyle) -> String {
|
||||
lock.lock()
|
||||
defer { lock.unlock() }
|
||||
formatter.unitsStyle = style
|
||||
return formatter.string(from: seconds) ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
extension Dictionary {
|
||||
func percentEncoded() -> Data? {
|
||||
map { key, value in
|
||||
@@ -34,25 +95,23 @@ extension CharacterSet {
|
||||
|
||||
extension Date {
|
||||
var timeFormatForUpload: String {
|
||||
let isoFormatter = DateFormatter()
|
||||
isoFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssX"
|
||||
return isoFormatter.string(from: self)
|
||||
DateFormatterCache.withLock {
|
||||
DateFormatterCache.serverDateFormatter.string(from: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
var dateFromServerDate: Date? {
|
||||
let df = DateFormatter()
|
||||
df.dateFormat = "yyyy-MM-dd'T'HH:mm:ssX"
|
||||
df.locale = Locale(identifier: "en_US_POSIX")
|
||||
return df.date(from: self)
|
||||
DateFormatterCache.withLock {
|
||||
DateFormatterCache.serverDateFormatter.date(from: self)
|
||||
}
|
||||
}
|
||||
|
||||
var plannedDate: Date? {
|
||||
let df = DateFormatter()
|
||||
df.dateFormat = "yyyy-MM-dd"
|
||||
df.locale = Locale(identifier: "en_US_POSIX")
|
||||
return df.date(from: self)
|
||||
DateFormatterCache.withLock {
|
||||
DateFormatterCache.plannedDateFormatter.date(from: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,31 +125,27 @@ extension Date {
|
||||
}
|
||||
|
||||
var formatForPlannedWorkout: String {
|
||||
let df = DateFormatter()
|
||||
df.dateFormat = "yyyy-MM-dd"
|
||||
df.locale = Locale(identifier: "en_US_POSIX")
|
||||
return df.string(from: self)
|
||||
DateFormatterCache.withLock {
|
||||
DateFormatterCache.plannedDateFormatter.string(from: self)
|
||||
}
|
||||
}
|
||||
|
||||
var weekDay: String {
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = "EEE"
|
||||
let weekDay = dateFormatter.string(from: self)
|
||||
return weekDay
|
||||
DateFormatterCache.withLock {
|
||||
DateFormatterCache.weekDayFormatter.string(from: self)
|
||||
}
|
||||
}
|
||||
|
||||
var monthString: String {
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = "MMM"
|
||||
let weekDay = dateFormatter.string(from: self)
|
||||
return weekDay
|
||||
DateFormatterCache.withLock {
|
||||
DateFormatterCache.monthFormatter.string(from: self)
|
||||
}
|
||||
}
|
||||
|
||||
var dateString: String {
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = "d"
|
||||
let weekDay = dateFormatter.string(from: self)
|
||||
return weekDay
|
||||
DateFormatterCache.withLock {
|
||||
DateFormatterCache.dayFormatter.string(from: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,10 +171,7 @@ extension Double {
|
||||
10000.asString(style: .brief) // 2hr 46min 40sec
|
||||
*/
|
||||
func asString(style: DateComponentsFormatter.UnitsStyle) -> String {
|
||||
let formatter = DateComponentsFormatter()
|
||||
formatter.allowedUnits = [.hour, .minute, .second, .nanosecond]
|
||||
formatter.unitsStyle = style
|
||||
return formatter.string(from: self) ?? ""
|
||||
DurationFormatterCache.string(from: self, style: style)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user