Skip to content

Instantly share code, notes, and snippets.

View AndreyAnt's full-sized avatar

Andrey Antropov AndreyAnt

View GitHub Profile
@AndreyAnt
AndreyAnt / AvatarImageView.swift
Last active June 25, 2022 09:53
Implementation Idea of rounded corners image view.
import UIKit
@IBDesignable class AvatarImageView: UIImageView {
@IBInspectable var shadowRadius: CGFloat = 10.0 {
didSet {
setNeedsDisplay()
}
}
@IBInspectable var shadowColor: UIColor = .black {
@AndreyAnt
AndreyAnt / PincodeKeyboard.swift
Created July 18, 2019 08:50
Attempt to create RxWay PincodeKeyboard
import UIKit
import RxSwift
import RxCocoa
enum PincodeButtonValue {
case digit(value: Int)
case touchId
case backspace
}
public typealias DecodableError = Error & Decodable
// Реактивное расширение, которое позволяет добавить дополнительный парсинг ошибки от сервера, которая приходит обернутой в JSON
extension PrimitiveSequence where Trait == RxSwift.SingleTrait, Element == Moya.Response {
public func check<DecodableError: Error & Decodable>(
for errorType: DecodableError.Type,
decoder: JSONDecoder = JSONDecoder()
) -> RxSwift.Single<Element> {
flatMap { response in
do {
let error = try decoder.decode(DecodableError.self, from: response.data)
/// Обертка ошибки, позволяющая превратить протоколизированный тип, в конкретный
private struct DecodableErrorWrapper: Decodable {
// Статический ключ по которому будем передавать тип
fileprivate static let typeKey = CodingUserInfoKey(rawValue: "decodableErrorType")!
// Ошибка реализующая протокол, но без конкретного типа
fileprivate let error: DecodableError
// Кастомный декодер инициализатор
init(from decoder: Decoder) throws {
// Вытаскиваем тип ошибки и кастим его в DecodableError
guard let errorType: DecodableError.Type = decoder.userInfo[DecodableErrorWrapper.typeKey] as? DecodableError.Type else {
#if DEBUG
_ = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
.map { _ in RxSwift.Resources.total }
.distinctUntilChanged()
.subscribe(onNext: { print("♦️ Resource count \($0)") })
#endif
@AndreyAnt
AndreyAnt / PropertyWrappersGeekbrains.swift
Created May 4, 2020 11:27
Gist for geekbrains lecture №5. SwiftUI course
class MyClass {
@Logged(formatString: "HH:mm dd.MM.yyyy") var myProperty = 0
init() {
print(type(of: _myProperty))
print(type(of: $myProperty))
print(type(of: myProperty))
}
}
extension Reactive where Base: UIViewController {
var viewWillAppear: Observable<Bool> {
return base.rx.methodInvoked(#selector(UIViewController.viewWillAppear(_:)))
.map { $0[0] as! Bool }
}
}
var keyboardHeight: CGFloat {
let windows = UIApplication.shared.windows
guard let keyboardWindowClass = NSClassFromString("UIRemoteKeyboardWindow"),
let keyboardWindow = windows.first(where: { $0.isKind(of: keyboardWindowClass) }),
let rootViewController = keyboardWindow.rootViewController,
let keyboardViewClass = NSClassFromString("UIInputSetHostView"),
let keyboardView = rootViewController.view.subviews.first(where: { $0.isKind(of: keyboardViewClass) }) else { return 0 }
return keyboardView.frame.height
func swizzleReplacingCharacters() {
let originalMethod = class_getInstanceMethod(
NSString.self, #selector(NSString.replacingCharacters(in:with:)))
let swizzledMethod = class_getInstanceMethod(
NSString.self, #selector(NSString.swizzledReplacingCharacters(in:with:)))
guard let original = originalMethod, let swizzled = swizzledMethod else {
return
}
import Combine
import ObjectiveC
import UIKit
private var eventSubjectKey = "viewcontroller_lifecycle_subject"
private var swizzlingPerformed = false
private final class LifecycleSubjectBag: NSObject {
let viewDidLoadSubject = PassthroughSubject<Void, Never>()
let viewWillAppearSubject = PassthroughSubject<Bool, Never>()