Skip to content

Instantly share code, notes, and snippets.

View michzio's full-sized avatar

Michał Ziobro michzio

  • Cracow
View GitHub Profile
@michzio
michzio / WordsetCategoriesViewModel.swift
Last active December 12, 2021 10:33
SwiftUI MVVM architecture - ViewModel protocol
public protocol WordsetCategoriesViewModelInput {
func syncWordsetCategories()
}
public protocol WordsetCategoriesViewModelOutput: ObservableObject {
var error: Error? { get set }
var isLoading: Bool { get set }
@michzio
michzio / WordsetCategoriesViewModel.swift
Last active December 12, 2021 10:34
SwiftUI MVVM architecture - ViewModel
public protocol WordsetCategoriesViewModelProtocol: ObservableObject {
var error: Error? { get set }
var isLoading: Bool { get set }
func syncWordsetCategories()
}
public class WordsetCategoriesViewModel: WordsetCategoriesViewModelProtocol {
@michzio
michzio / WordsetCategoriesView.swift
Last active December 12, 2021 10:34
SwiftUI MVVM architecture - View
struct WordsetCategoriesView<VM: WordsetCategoriesViewModelProtocol>: View {
// MARK: - View Model
@StateObject private var viewModel: VM
// MARK: - Core Data
@FetchRequest private var categories: FetchResults<WordsetCategory>
init(viewModel: VM) {
_viewModel = viewModel
@michzio
michzio / LifeCycleView.swift
Created August 5, 2021 07:55
LifeCycleView in SwiftUI - listen lifecycle methods in swiftui view
public struct LifeCycleView: UIViewControllerRepresentable {
private let viewDidLoad: (() -> Void)?
private let viewWillAppear: ((Bool) -> Void)?
private let viewDidAppear: ((Bool) -> Void)?
private let viewWillDisappear: ((Bool) -> Void)?
private let viewDidDisappear: ((Bool) -> Void)?
public init(
viewDidLoad: (() -> Void)? = nil,
import SwiftUI
struct AdaptiveBottomSheet<SheetContent>: ViewModifier where SheetContent: View {
// MARK: - Binding
private var isPresented: Binding<Bool>
// MARK: - State
@State private var showBottomSheet : Bool = false
@State private var showBackground: Bool = false
@michzio
michzio / DeviceType
Created July 29, 2020 07:53
DeviceType
import UIKit
struct ScreenSize
{
static var SCREEN_WIDTH : CGFloat { UIScreen.main.bounds.size.width }
static var SCREEN_HEIGHT : CGFloat { UIScreen.main.bounds.size.height }
static var SCREEN_MAX_LENGTH : CGFloat { max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT) }
static var SCREEN_MIN_LENGTH : CGFloat { min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT) }
}
extension KeyboardAvoider {
func keyboardOffsets(isTabBar: Bool = true, offset: CGFloat = 0) -> (total: CGFloat, adjusted: CGFloat) {
let tabBarHeight = isTabBar ? UITabBarController().tabBar.frame.height : 0
let safeAreaHeight = UIApplication.shared.windows.first{ $0.isKeyWindow }?.safeAreaInsets.bottom ?? 0
let totalKeyboardOffset = self.keyboardRect.height
let keyboardOffset = totalKeyboardOffset > 0 ? totalKeyboardOffset - tabBarHeight - safeAreaHeight - offset : 0
return (totalKeyboardOffset, keyboardOffset)
extension List {
func attachKeyboardAvoider(_ keyboardAvoider: KeyboardAvoider, offset: CGFloat = 0) -> some View {
let (total, adjusted) = keyboardAvoider.keyboardOffsets(offset: offset)
return self
.padding(.bottom, total > 0 ? adjusted + 32 : 0)
}
}
private func updateSlideSize() {
guard let fieldRect = self.rects[editingField] else {
slideSize = .zero
slideSizePublisher.send(.zero)
return
}
guard keyboardRect != .zero else {
slideSize = .zero
final class KeyboardAvoider : ObservableObject {
private var _rects = [Int: CGRect]() {
didSet {
print("Keyboard Avoider rects changed: \(_rects.count)")
}
}
var rects: [Int: CGRect] {
set {
guard keyboardRect == .zero else {