-
Notifications
You must be signed in to change notification settings - Fork 3
공통 모듈
Hiju edited this page Dec 1, 2021
·
37 revisions
- simpleAlert(title: String, message msg: String) -> UIAlertController
- alert(title: String, message: String, success: ((UIAlertAction) -> Void)? = nil, failure: ((UIAlertAction) -> Void)? = nil) -> UIAlertController
- var redValue: CGFloat
- var greenValue: CGFloat
- var blueValue: CGFloat
- static let boosterOrange: UIColor
- static let boosterLabel: UIColor
- static let boosterBackground: UIColor
//
// UIResponder+Extension.swift
// Booster
//
// Created by Hani on 2021/11/08.
//
import UIKit
extension UIResponder {
static var identifier: String {
String(describing: self)
}
}
extension TimeInterval {
private var seconds: Int {
return Int(self) % 60
}
private var minutes: Int {
return (Int(self) / 60) % 60
}
private var hours: Int {
return Int(self) / 3600
}
func stringToMinutesAndSeconds() -> String {
return "\(hours)h \(minutes)m"
}
}
var rx: Observable<NWPath> {
Observable.create { [weak self] observer in
self?.pathUpdateHandler = { path in
observer.onNext(path)
}
self?.start(queue: DispatchQueue.global())
return Disposables.create { self?.cancel() }
}
}
reachability를 Rx로 사용가능 하기 위해 정의
HealthStoreManager (Deprecated)
//
// HealthKitManager.swift
// Booster
//
// Created by Hani on 2021/11/23.
//
import Foundation
import HealthKit
import RxSwift
typealias HealthQuantityType = HealthKitManager.HealthQuantityType
typealias HealthUnit = HealthKitManager.HealthUnit
final class HealthKitManager {
enum HealthQuantityType: CaseIterable {
case steps, runing, energy
var quantity: HKQuantityType? {
switch self {
case .steps: return .quantityType(forIdentifier: .stepCount)
case .runing: return .quantityType(forIdentifier: .distanceWalkingRunning)
case .energy: return .quantityType(forIdentifier: .activeEnergyBurned)
}
}
}
enum HealthUnit: CaseIterable {
case count, kilometer, calorie
var unit: HKUnit {
switch self {
case .count: return .count()
case .kilometer: return .meterUnit(with: .kilo)
case .calorie: return .kilocalorie()
}
}
}
enum HealthKitError: Error {
case optionalCasting
case removeAllDataFail
}
static let shared = HealthKitManager()
private var healthStore: HKHealthStore?
private init() {
if HKHealthStore.isHealthDataAvailable() {
healthStore = HKHealthStore()
}
}
func requestAuthorization(shareTypes: Set<HKSampleType>, readTypes: Set<HKSampleType>) -> Single<Bool> {
return Single.create { [weak self] single in
self?.healthStore?.requestAuthorization(toShare: shareTypes, read: readTypes) { (success, error) in
guard error == nil
else { return }
return single(.success(success))
}
return Disposables.create()
}
}
func requestStatisticsCollectionQuery(type: HKQuantityType,
predicate: NSPredicate,
interval: DateComponents,
anchorDate: Date) -> Single<HKStatisticsCollection> {
return Single.create { [weak self] single in
let query = HKStatisticsCollectionQuery(
quantityType: type,
quantitySamplePredicate: predicate,
options: .cumulativeSum,
anchorDate: anchorDate,
intervalComponents: interval
)
query.initialResultsHandler = { _, hkStatisticsCollection, _ in
if let hkStatisticsCollection = hkStatisticsCollection {
return single(.success(hkStatisticsCollection))
}
}
self?.healthStore?.execute(query)
return Disposables.create()
}
}
func requestStatisticsQuery(type: HKQuantityType, predicate: NSPredicate) -> Single<HKStatistics?> {
return Single.create { [weak self] single in
let query = HKStatisticsQuery(
quantityType: type,
quantitySamplePredicate: predicate,
options: [.cumulativeSum, .duration]) { _, statistics, _ in
return single(.success(statistics))
}
self?.healthStore?.execute(query)
return Disposables.create()
}
}
func save(count: Double,
start: Date,
end: Date,
quantity: HealthQuantityType,
unit: HealthUnit) {
guard let healthStore = healthStore,
let type = quantity.quantity
else { return }
let unit = unit.unit
let countQuantity = HKQuantity(unit: unit, doubleValue: count)
let sample = HKQuantitySample(type: type,
quantity: countQuantity,
start: start,
end: end)
healthStore.save(sample) { _, _ in }
}
func removeAll() -> Single<Bool> {
return Single.create { [weak self] single in
let predicate = HKQuery.predicateForObjects(from: HKSource.default())
for type in HealthQuantityType.allCases {
guard let quantity = type.quantity
else { continue }
self?.healthStore?.deleteObjects(of: quantity, predicate: predicate) { (isDeleted, count, error) in
if !isDeleted,
let error = error {
single(.failure(error))
return
}
single(.success(isDeleted))
}
}
return Disposables.create()
}
}
}
func save(attributes: [String: Any],
type name: String,
completion handler: @escaping (Result<Void, Error>) -> Void) {
guard let entity = NSEntityDescription.entity(forEntityName: name, in: container.viewContext)
else { return }
let backgroundContext = container.newBackgroundContext()
backgroundContext.perform { [weak self] in
guard let self = self
else { return }
let entityObject = NSManagedObject(entity: entity, insertInto: self.container.viewContext)
attributes.forEach { entityObject.setValue($0.value, forKey: $0.key) }
let context = self.container.viewContext
do {
try context.save()
handler(.success(()))
} catch let error {
handler(.failure(error))
}
}
}
func save(attributes: [String: Any],
type name: String) -> Observable<Void> {
return Observable.create { observer in
guard let entity = NSEntityDescription.entity(forEntityName: name, in: self.container.viewContext)
else { return Disposables.create() }
let backgroundContext = self.container.newBackgroundContext()
backgroundContext.performAndWait { [weak self] in
guard let self = self
else { return }
let entityObject = NSManagedObject(entity: entity, insertInto: self.container.viewContext)
attributes.forEach { entityObject.setValue($0.value, forKey: $0.key) }
let context = self.container.viewContext
do {
try context.save()
observer.onNext(())
} catch let error {
observer.onError(error)
}
}
return Disposables.create()
}
}
func save<DataType: NSManagedObject>(value: [String: Any],
type name: String,
predicate: NSPredicate,
completion handler: @escaping (Result<DataType, Error>) -> Void) {
let backgroundContext = container.newBackgroundContext()
backgroundContext.perform { [weak self] in
guard let self = self
else { return }
let request = NSFetchRequest<DataType>.init(entityName: name)
request.predicate = predicate
do {
let objects = try self.container.viewContext.fetch(request)
value.forEach { objects[0].setValue($0.value, forKey: $0.key) }
try self.container.viewContext.save()
handler(.success(objects[0]))
} catch let error {
handler(.failure(error))
}
}
}
func update(entityName: String, attributes: [String: Any], predicate: NSPredicate? = nil) -> Observable<Void> {
return Observable.create { [weak self] observer in
guard let self = self
else { return Disposables.create() }
let backgroundContext = self.container.newBackgroundContext()
backgroundContext.perform {
let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: entityName)
request.predicate = predicate
do {
let context = self.container.viewContext
let result = try context.fetch(request)
guard let updateModel = result.first as? NSManagedObject
else { return }
for element in attributes {
updateModel.setValue(element.value, forKey: element.key)
}
try context.save()
observer.onCompleted()
} catch let error {
self.container.viewContext.rollback()
observer.onError(error)
}
}
return Disposables.create()
}
}
func fetch<DataType: NSManagedObject>() -> Observable<[DataType]> {
return Observable.create { [weak self] observer in
guard let self = self
else { return Disposables.create() }
let backgroundContext = self.container.newBackgroundContext()
backgroundContext.perform {
do {
let context = try self.container.viewContext.fetch(DataType.fetchRequest())
guard let context = context as? [DataType]
else { return }
observer.onNext(context)
} catch let error {
observer.onError(error)
}
}
return Disposables.create()
}
}
func fetch<DataType: NSManagedObject>(completion handler: @escaping (Result<[DataType], Error>) -> Void) {
let backgroundContext = container.newBackgroundContext()
backgroundContext.perform { [weak self] in
guard let self = self
else { return }
do {
let context = try self.container.viewContext.fetch(DataType.fetchRequest())
guard let context = context as? [DataType]
else { return }
handler(.success(context))
} catch let error {
handler(.failure(error))
}
}
}
func fetch<DataType: NSManagedObject>(entityName: String,
predicate: NSPredicate,
completion handler: @escaping (Result<[DataType], Error>) -> Void) {
let backgroundContext = container.newBackgroundContext()
backgroundContext.perform { [weak self] in
guard let self = self
else { return }
let request = NSFetchRequest<DataType>.init(entityName: entityName)
request.predicate = predicate
do {
let result = try self.container.viewContext.fetch(request)
handler(.success(result))
} catch let error {
handler(.failure(error))
}
}
}
func fetch<DataType: NSManagedObject>(entityName: String,
predicate: NSPredicate) -> Observable<[DataType]> {
return Observable.create { [weak self] observer in
guard let self = self
else { return Disposables.create() }
let backgroundContext = self.container.newBackgroundContext()
backgroundContext.perform {
let request = NSFetchRequest<DataType>.init(entityName: entityName)
request.predicate = predicate
do {
let result = try self.container.viewContext.fetch(request)
observer.onNext(result)
} catch let error {
observer.onError(error)
}
}
return Disposables.create()
}
}
func delete<DataType: NSManagedObject>(entityName: String,
predicate: NSPredicate,
completion handler: @escaping (Result<DataType, Error>) -> Void) {
let backgroundContext = container.newBackgroundContext()
backgroundContext.perform { [weak self] in
guard let self = self
else { return }
let request = NSFetchRequest<DataType>.init(entityName: entityName)
request.predicate = predicate
do {
let objects = try self.container.viewContext.fetch(request)
self.container.viewContext.delete(objects[0])
try self.container.viewContext.save()
handler(.success(objects[0]))
} catch let error {
handler(.failure(error))
}
}
}
func delete(entityName: String, completion handler: @escaping (Result<Void, Error>) -> Void) {
let backgroundContext = container.newBackgroundContext()
backgroundContext.perform { [weak self] in
guard let self = self
else { return }
let request = NSFetchRequest<NSFetchRequestResult>.init(entityName: entityName)
do {
let delete = NSBatchDeleteRequest(fetchRequest: request)
try self.container.viewContext.execute(delete)
handler(.success(()))
} catch let error {
handler(.failure(error))
}
}
}
func delete(entityName: String, predicate: NSPredicate) -> Observable<Void> {
return Observable.create { [weak self] observer in
guard let self = self
else { return Disposables.create() }
let backgroundContext = self.container.newBackgroundContext()
backgroundContext.perform {
let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: entityName)
request.predicate = predicate
do {
let objects = try self.container.viewContext.fetch(request)
guard let model = objects.first as? NSManagedObject
else { return }
self.container.viewContext.delete(model)
try self.container.viewContext.save()
observer.onCompleted()
} catch let error {
observer.onError(error)
}
}
return Disposables.create()
}
}
- 불러오기는 모두 다 불러오는 fetch & NSPredicate 사용하는 일부 fetch
- 저장은 일반적인 save & update 가능
- 삭제는 일부 delete & all delete