Skip to content

Instantly share code, notes, and snippets.

View steipete's full-sized avatar
🤖
beep boop

Peter Steinberger steipete

🤖
beep boop
View GitHub Profile
@steipete
steipete / Architecture.swift
Last active January 14, 2025 22:46
Detect if a process runs under Rosetta 2 on Apple Silicon M1 or native. Works for macOS and iOS.
@objc(PSTArchitecture) class Architecture: NSObject {
/// Check if process runs under Rosetta 2.
///
/// Use to disable tests that use WebKit when running on Apple Silicon
/// FB8920323: Crash in WebKit memory allocator on Apple Silicon when iOS below 14
/// Crash is in JavaScriptCore: bmalloc::HeapConstants::HeapConstants(std::__1::lock_guard<bmalloc::Mutex> const&)
@objc class var isRosettaEmulated: Bool {
// Issue is specific to Simulator, not real devices
#if targetEnvironment(simulator)
return processIsTranslated() == EMULATED_EXECUTION
@steipete
steipete / NSDictionary+CaseInsensitive.h
Last active December 2, 2020 01:56
Case Insensitive NSDictionary subclass. This seems like a lost art, so I'm sharing it here. License: MIT, http://pspdfkit.com/
/// Higher-order functions for `NSDictionary`.
@interface NSDictionary <KeyType, ObjectType> (PSPDFFoundation)
/// Converts the current dictionary into a case insensitive one.
@property (nonatomic, readonly) NSDictionary<NSString *, ObjectType> *pst_caseInsensitiveDictionary;
@end
@steipete
steipete / Default.xcconfig
Created November 6, 2020 14:18
Hack to exclude arm64 when building Mac Catalyst in Xcode 12.2
// Hack to exclude arm64 when building Mac Catalyst in Xcode 12.2
// If this is not set and we do not set macosx as SUPPORTED_PLATFORMS, then selecting Mac as target forces arm64.
// This can be worked around by setting ONLY_ACTIVE_ARCH to NO (slow) or using the EXCLUDED_ARCHS trick
// Inspired by https://github.com/Carthage/Carthage/issues/3019
EXCLUDED_ARCHS__IS_MACCATALYST_YES__NATIVE_ARCH_64_BIT_x86_64=arm64 arm64e armv7 armv7s armv6 armv8
EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__IS_MACCATALYST_$(IS_MACCATALYST)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT))
@steipete
steipete / URLCacheTest.swift
Last active August 21, 2024 11:18
Using URLCache with download tasks (NSURLCache & NSURLSessionDownloadTask)
import Foundation
import os.log
class URLCacheTest {
let logger = Logger(subsystem: "URLCacheTest", category: "main")
// HTTP HEADERS:
// Date: Wed, 04 Nov 2020 11:13:24 GMT
// Server: Apache
// Strict-Transport-Security: max-age=63072000; includeSubdomains; preload
@steipete
steipete / Fruta.crash
Last active October 25, 2020 14:50
Apple Fruta App crash on Big Sur Beta 10
Invalid products: com.example.apple-samplecode.fruta.unlock-recipes
2020-10-25 15:46:23.664364+0100 Fruta[25696:2730598] [SwiftUI] Modifying state during view update, this will cause undefined behavior.
2020-10-25 15:46:23.664705+0100 Fruta[25696:2730598] [SwiftUI] Modifying state during view update, this will cause undefined behavior.
2020-10-25 15:46:23.929321+0100 Fruta[25696:2730598] Metal API Validation Enabled
2020-10-25 15:46:23.967322+0100 Fruta[25696:2730598] VPA info: plugin is INTEL, AVD_id = 1080020, AVD_api.Create:0x1154fe95f
2020-10-25 15:47:46.728654+0100 Fruta[25696:2730598] [Layout] Unable to simultaneously satisfy constraints:
(
"<NSAutoresizingMaskLayoutConstraint:0x6000031f0aa0 h=-&- v=-&- _NSTextContentView:0x7f96e4de29b0.minX == 0 (active, names: '|':NSTextView:0x7f9685f95ac0 )>",
"<NSAutoresizingMaskLayoutConstraint:0x6000031f3020 h=-&- v=-&- H:[_NSTextContentView:0x7f96e4de29b0]-(380)-| (active, names: '|':NSTextView:0x7f9685f95ac0 )>",
"<NSAutoresizingMaskLayoutConstra
@steipete
steipete / AnchorButton.swift
Last active October 15, 2022 02:52
SwiftUI Button that wraps a hidden view to anchor popovers on it; can be used as a button in the navigation bar. https://pspdfkit.com/blog/2020/popovers-from-swiftui-uibarbutton/
struct AnchorButton<Content: View>: View {
typealias Action = (_ sender: AnyObject?) -> Void
let callback: Action
var content: Content
@StateObject private var viewWrapper = ViewWrapper(view: UIView(frame: .zero))
init(action: @escaping Action, @ViewBuilder label: () -> Content) {
self.callback = action
self.content = label()
}
@steipete
steipete / BarButtonWatcher.swift
Last active October 17, 2020 14:00
Helper to capture the last tapped bar button item in an UIKit or SwiftUI app. SwiftUI uses UIBarButtonItem under the hood in iOS 14 with the new toolbar API. Anchoring popovers from UIKit requires this as sender.
/// Helper to capture the last tapped bar button item in an UIKit or SwiftUI app.
final class BarButtonWatcher {
/// Singleton accessor. There can only be one currently tapped bar button item per process.
static let shared = BarButtonWatcher()
static private(set) weak var lastBarButtonItem: UIBarButtonItem? {
didSet {
// reset in next runloop
if lastBarButtonItem != nil {
DispatchQueue.main.async { self.lastBarButtonItem = nil }
@steipete
steipete / SwiftUIDocumentBrowserSpeedup.swift
Last active April 18, 2021 17:36
If saving is too slow for you in the new SwiftUI DocumentBrowser wrapper, here's a terrible trick to make it instant. (This is new API in iOS 14; Apple might change the underpinnings to not use UIDocument, so this might fail in future updates. InterposeKit fails gracefully and worst case you end up with the save delay). FB8748779
private func speedupDocumentSaving() throws {
// SwiftUI triggers updateChangeCount: when the binding changes,
// which triggers an autosave operation to eventually store the document.
// There's no direct way to access UIDocument (used inside SwiftUI.PlatformDocument)
// to speed up this process. It is noticable as it delays changing the thumbnail.
// While saving is triggered instantly when the application backgrounds,
// we still want to update the document immediately.
//
// We could apply this to SwiftUI.PlatformDocument for a more narrow tweak.
// We could also swizzle the NSTimer initializer, check for the target being PlatformDocument
extension UIHostingController {
convenience public init(rootView: Content, ignoreSafeArea: Bool) {
self.init(rootView: rootView)
if ignoreSafeArea {
disableSafeArea()
}
}
func disableSafeArea() {
import Foundation
import Combine
@available(iOS 13.0, *)
extension NSObject {
private struct AssociatedKeys {
static var disposeBag: UInt8 = 0
}
/// Stores a Combine AnyCancellable with the current object's disposeBag.