Skip to content

Instantly share code, notes, and snippets.

View steipete's full-sized avatar

Peter Steinberger steipete

View GitHub Profile
@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.
public var byteRange: [Range<UInt64>]? {
// Guaranteed to be in pairs. Example:
// - 0 : 0
// - 1 : 71826
// - 2 : 83948
// - 3 : 34223
guard let boxedRange = __byteRange else { return nil }
let range = boxedRange.map { $0.uint64Value }
var ranges: [Range<UInt64>] = []
@steipete
steipete / OSLogTest.swift
Created August 24, 2020 10:35
Sample code to access OSLogStore on iOS and macOS.
let subsystem = "com.steipete.LoggingTest"
func getLogEntries() throws -> [OSLogEntryLog] {
// FB8269189: OSLogStore does not work iOS.
let logStore = try OSLogStore(scope: .currentProcessIdentifier)
let oneHourAgo = logStore.position(date: Date().addingTimeInterval(-3600))
#if os(macOS)
let allEntries = try logStore.getEntries(at: oneHourAgo)
#else
@steipete
steipete / OSLogStream.swift
Last active November 7, 2023 22:25
Access streaming OSLogStore at runtime with SPI. (FB8519418) https://steipete.com/posts/logging-in-swift/
//
// OSLogStream.swift
// LoggingTest
//
// Created by Peter Steinberger on 24.08.20.
//
// Requires importing https://github.com/apple/llvm-project/blob/apple/master/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h via bridging header
import Foundation
// TODO: FB8068393 Remove once this properly landed in Big Sur.
// These Strings are missing as of b2 (Linker Error)
extension NSToolbarItem.Identifier {
static let primarySeparator = NSToolbarItem.Identifier(rawValue: "NSToolbarPrimarySidebarTrackingSeparatorItem")
static let supplementarySeparator = NSToolbarItem.Identifier(rawValue: "NSToolbarSupplementarySidebarTrackingSeparatorItem")
}
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x00007fff3cdc3c01 SwiftUI`outlined consume of SwiftUI.GraphicsImage.Contents + 1
frame #1: 0x00007fff3d5ba75c SwiftUI`static SwiftUI.GraphicsImage.== infix(SwiftUI.GraphicsImage, SwiftUI.GraphicsImage) -> Swift.Bool + 412
frame #2: 0x00007fff3cf68b41 SwiftUI`static SwiftUI.Image.Resolved.== infix(SwiftUI.Image.Resolved, SwiftUI.Image.Resolved) -> Swift.Bool + 465
frame #3: 0x00007fff45a81acf AttributeGraph`AGDispatchEquatable + 15
* frame #4: 0x00007fff45a6e114 AttributeGraph`AG::LayoutDescriptor::compare(unsigned char const*, unsigned char const*, unsigned char const*, unsigned long, unsigned int) + 1637
frame #5: 0x00007fff45a7a40e AttributeGraph`AGGraphSetOutputValue + 445
frame #6: 0x00007fff3d17f12e SwiftUI`generic specialization <SwiftUI.Image> of SwiftUI.(EnvironmentReadingChild in _FB65686E4F4C246132C16AE349C5E43C).updateValue() -> () + 1838
frame #7: 0x00007fff3d28edef SwiftUI
import XCTest
public enum TestWaitResult {
case wait, success
}
public enum WaitTimeoutCondition {
case fail, skip
}