Skip to content

Instantly share code, notes, and snippets.

View krzyzanowskim's full-sized avatar

Marcin Krzyzanowski krzyzanowskim

View GitHub Profile
import AppKit
import SwiftUI
/*
Text("Menu")
.popUpMenu {
NSMenuItem(title: "One", action: nil, keyEquivalent: "")
NSMenuItem(title: "Two", action: nil, keyEquivalent: "")
}
*/
struct VisualEffectView: NSViewRepresentable {
let material: NSVisualEffectView.Material
let blendingMode: NSVisualEffectView.BlendingMode
init(material: NSVisualEffectView.Material, blendingMode: NSVisualEffectView.BlendingMode = .withinWindow) {
self.material = material
self.blendingMode = blendingMode
}
func makeNSView(context: Context) -> NSVisualEffectView {
public struct OptionSetIterator<Element: OptionSet>: IteratorProtocol where Element.RawValue == Int {
private let value: Element
init(element: Element) {
self.value = element
}
private lazy var remainingBits = value.rawValue
private var bitMask = 1
@krzyzanowskim
krzyzanowskim / AsyncWaiter.swift
Last active June 25, 2022 12:25
Synchronously (well) wait for async Task value update https://twitter.com/krzyzanowskim/status/1523233140914876416
/// Wait for async operation to return value and call callback with the value
/// This class is intended to workaround/simplify async/await + actors isolation
/// https://twitter.com/krzyzanowskim/status/1523233140914876416
private class AsyncWaiter<T> {
var didReceiveValue: Bool = false
let value: (T) -> Void
let operation: () async throws -> T
init(_ value: @escaping (T) -> Void, operation: @escaping () async throws -> T) {
self.value = value
@krzyzanowskim
krzyzanowskim / String.stride.swift
Last active April 15, 2022 19:50
Stride String
extension String {
func stride(by distance: String.IndexDistance, substring: (String.SubSequence) -> Void) {
guard distance > 0, distance < count else {
substring(self[...])
return
}
var i = index(startIndex, offsetBy: distance, limitedBy: endIndex) ?? endIndex
var previ = startIndex
while i < endIndex {
struct SharingServicePicker: NSViewRepresentable {
@Binding var isPresented: Bool
var items: [Any] = []
func makeNSView(context: Context) -> NSView {
let view = NSView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}
@krzyzanowskim
krzyzanowskim / FB9959997_NSResponder_undoManager.md
Last active May 4, 2023 10:10
NSResponder.undoManager is not used (FB9959997)

According to documentation it's enough to override NSResponder.undoManager to provide custom NSUndoManager instance. I found it's not quite working:

  • Xcode Mac application template comes with Undo menu item bind to firstResponder.undo: despite NSResponder has no undo: selector defined. Unless first responder actually respond to undo: the Undo action doesn't work
  • NSFirstResponder.undoManager look up in responder chain and eventually it end up in NSWindow where the only place (that I found) that validate Undo menu item is NSWindow.validateUserInterfaceItem - that one, as turned out, only ever validate undo: action if first responder implements _getUndoManager: selector (quite private, isn't it?) - see attached disassembly

at this point 🤕 I start to think it's either documentation issue, or AppKit implementation issue. Anyway, I didn't found way to enable undo: action unless I implement one of these methods in my NSView. (notice: the view is first responder tha

@krzyzanowskim
krzyzanowskim / UTF16_to_bytes.swift
Last active March 7, 2022 23:09
Creates a string from the given bytes in the UTF16 encoding.
extension Array where Element == UInt16 {
/// Little-Endian UTF16 bytes
var bytes: [UInt8] {
flatMap {
[
UInt8($0.littleEndian & 0xFF),
UInt8(($0.littleEndian &>> 8) & 0xFF)
]
}
@krzyzanowskim
krzyzanowskim / CharacterSet+Character.swift
Last active February 28, 2022 20:02
Check whether CharacterSet contains Character
extension CharacterSet {
/// Check whether CharacterSet contains Character
func contains(_ character: Character) -> Bool {
character.unicodeScalars.allSatisfy(contains)
}
}
@krzyzanowskim
krzyzanowskim / NSRange+NSTextContentManager.swift
Created February 15, 2022 18:03
NSRange TextKit2 helpers
extension NSRange {
static let notFound = NSRange(location: NSNotFound, length: 0)
var isEmpty: Bool {
length == 0
}
init(_ textRange: NSTextRange, in textContentManager: NSTextContentManager) {
let offset = textContentManager.offset(from: textContentManager.documentRange.location, to: textRange.location)