Skip to content

Instantly share code, notes, and snippets.

View yonat's full-sized avatar

Yonat Sharon yonat

View GitHub Profile
@yonat
yonat / CheckboxButton.swift
Last active March 1, 2024 07:02
Simplest iOS Checkbox (UIKit)
import UIKit
/// Checkbox with title. When checked, `isSelected` is `true`.
class CheckboxButton: UIButton {
/// Handler called when the checkbox is checked or unchecked
var onCheck: ((Bool) -> Void)?
/// - Parameters:
/// - title: Text shown next to the checkbox
/// - color: Color for both checkbox and title
@yonat
yonat / generate_push_certificate.sh
Created July 11, 2023 08:25
Generate push certificate using fast lane, and create additional p12 for use in the Keychain Access app
# Generate push certificates.
# Usage: generate_push_certificate <app-bundle-id> <user-email> <cert-password>
generate_push_certificate() {
app=$1
user=$2
password=$3
fastlane pem -a "$app" -u "$user" -p "$password"
convert_push_certificate_to_keychain_format "production_${app}_ios.p12" "$password"
}
@yonat
yonat / send_push.sh
Last active July 15, 2023 02:54
Send Apple push notification from terminal
#!/bin/sh
show_help() {
echo ""
echo " $(basename "$0") - Send push notification to an iOS device."
echo ""
echo " Usage:"
echo " $(basename "$0") [options] <app-bundle-id> <cert-file.p12> <cert-password> <push-token>"
echo ""
echo " Options:"
@yonat
yonat / ResizableAsyncImage.swift
Created February 21, 2023 05:59
SwiftUI AsyncImage that fits its image into a frame
import SwiftUI
/// AsyncImage that fits its image into a frame, shows spinner while loading, and an error if it occurs
struct ResizableAsyncImage: View {
let url: URL?
let imageContentMode: ContentMode
let maxWidth: CGFloat?
let maxHeight: CGFloat?
var body: some View {
@yonat
yonat / Fastfile
Last active March 16, 2022 13:22
Change any Xcode build setting in fastlane
desc "Change a value in xcodeproj file."
desc "Usage: fastlane change_build_value xcodeproj:<file-name> name:<build-setting> from:<old-value> to:<new-value>"
lane :change_build_value do |options|
xcodeproj = options[:xcodeproj]
name = options[:name]
from = options[:from]
to = options[:to]
optional_quotes = '"\\{0,1\\}'
replacement_expression = "s/#{name} = #{optional_quotes}#{from}#{optional_quotes};/#{name} = #{to};/g"
@yonat
yonat / UserDefaultsPropertyWrapper.swift
Created March 5, 2021 09:26
Property wrapper for `UserDefaults.standard` backed value
import Foundation
/// Property wrapper for `UserDefaults.standard` backed value
@propertyWrapper
struct UserDefault<Value: UserDefaultsValue> {
let key: String
let defaultValue: Value
let container: UserDefaults
@yonat
yonat / zoom-dl.sh
Last active April 25, 2021 05:31
Download zoom recordings
#!/bin/sh
# courtesy of https://github.com/ytdl-org/youtube-dl/issues/23573#issuecomment-631115716
url="${1%%\?*}"
jar=$(mktemp)
mp4=$(curl -s -c "$jar" "$url" | grep video/mp4 | grep -o 'https:[^"]*')
file=$(echo "$mp4" | grep -o "[^/? ]*\.mp4")
echo "Downloading $file"
//
// ContentView.swift
// Stacketude
//
// Created by Yonat Sharon on 06/01/2020.
// Copyright © 2020 Yonat Sharon. All rights reserved.
//
import SwiftUI
@yonat
yonat / Binding+Extensions.swift
Last active December 13, 2019 12:01
Random collection of Swift utilities
import SwiftUI
extension Binding {
/// Execute block when value is changed.
///
/// Example:
///
/// Slider(value: $amount.didSet { print($0) }, in: 0...10)
func didSet(execute: @escaping (Value) ->Void) -> Binding {
return Binding(
@yonat
yonat / String+substr.swift
Created September 3, 2016 07:03
Perl style substring for Swift String
extension String {
/**
Perl style substring
- parameter offset: Negative offset starts that far back from the end of the string
- parameter length: Negative length leaves that many characters off the end of the string. Omit to return everything through the end of the string.
*/
func substr(offset: Int, length: Int = 0) -> String {
let start = offset < 0 ? endIndex.advancedBy(offset, limit: startIndex) : startIndex.advancedBy(offset, limit: endIndex)
let end = length > 0 ? start.advancedBy(length, limit: endIndex) : endIndex.advancedBy(length, limit: startIndex)