Skip to content

Instantly share code, notes, and snippets.

Avatar

Cyril Chandelier cyrilchandelier

View GitHub Profile
View MediaProgressBar.swift
import UIKit
@IBDesignable final class MediaProgressBar: UIControl {
// MARK: - Configuration
@IBInspectable var isThumbVisible: Bool = true {
didSet {
thumbView.alpha = isThumbVisible ? 1.0 : 0.0
}
}
@cyrilchandelier
cyrilchandelier / MinimumTouchAreaButton.swift
Created Sep 23, 2019
A Swift UIButton extension to ensure the hit-zone is at least 44x44
View MinimumTouchAreaButton.swift
import UIKit
class MinimumTouchAreaButton: UIButton {
override func hitTest(_ point: CGPoint, with _: UIEvent?) -> UIView? {
guard !isHidden, isUserInteractionEnabled, alpha > 0 else {
return nil
}
let expandedBounds = bounds.insetBy(dx: min(bounds.width - 44.0, 0), dy: min(bounds.height - 44.0, 0))
return expandedBounds.contains(point) ? self : nil
}
@cyrilchandelier
cyrilchandelier / OptionalAssignment.swift
Last active Sep 19, 2019
A Swift operator to only assign a value when the right operand is not nil
View OptionalAssignment.swift
import Foundation
precedencegroup OptionalAssignment {
associativity: right
}
infix operator ?=: OptionalAssignment
public func ?= <T>(variable: inout T, value: T?) {
if let unwrapped = unwrap(any: value) ?? nil {
@cyrilchandelier
cyrilchandelier / UICollectionView+Registration.swift
Created Sep 2, 2019
UICollectionView extension to easily register/dequeue cells
View UICollectionView+Registration.swift
import UIKit
protocol UICollectionViewRegisterable {
static var cellIdentifier: String { get }
static var cellNib: UINib { get }
}
extension UICollectionView {
func register(type: UICollectionViewRegisterable.Type) {
register(type.cellNib, forCellWithReuseIdentifier: type.cellIdentifier)
@cyrilchandelier
cyrilchandelier / UIScrollView+Bounce.swift
Created Aug 21, 2019
An extension to detect if scrollview is bouncing
View UIScrollView+Bounce.swift
extension UIScrollView {
var isBouncing: Bool {
return isBouncingTop || isBouncingBottom
}
var isBouncingTop: Bool {
return contentOffset.y < topInsetForBouncing - contentInset.top
}
var isBouncingBottom: Bool {
@cyrilchandelier
cyrilchandelier / AppDelegate.swift
Created Apr 22, 2018
Detecting organic vs. local notification vs. remote notification app launches
View AppDelegate.swift
func applicationDidBecomeActive(_ application: UIApplication) {
let notificationController = NotificationController.shared
// Track app launch if the notificationController didn't already do it
if !notificationController.handledLaunchAnalytics {
Analytics.trackAppLaunched(source: .Organic)
}
}
@cyrilchandelier
cyrilchandelier / BaseAppDelegate.swift
Created Apr 22, 2018
AppDelegate superclass to handle first launch detection and upgrade detection
View BaseAppDelegate.swift
//
// BaseAppDelegate.swift
//
// Created by Cyril Chandelier on 21/04/2018.
// Copyright © 2018 Cyril Chandelier. All rights reserved.
//
import UIKit
class BaseAppDelegate: UIResponder, UIApplicationDelegate {
@cyrilchandelier
cyrilchandelier / UILabel+Stylesheet.h
Created Oct 22, 2015
Stylesheet like IBInspectable labels
View UILabel+Stylesheet.h
//
// UILabel+Stylesheet.h
// Stylesheet
//
// Created by Cyril Chandelier on 21/10/15.
// Copyright © 2015 CyrilChandelier. All rights reserved.
//
#import <UIKit/UIKit.h>
@cyrilchandelier
cyrilchandelier / NSString+CJK.h
Last active Oct 30, 2015
Asian characters detection
View NSString+CJK.h
#import <Foundation/Foundation.h>
@interface NSString (CJK)
/**
Detect if the string contains Chinese, Japanese or Korean characters
@return YES if the string contains CJK characters, NO otherwise
*/