Skip to content

Instantly share code, notes, and snippets.

import Combine
import SwiftUI
import WebKit
@Observable final class WebViewContent: NSObject {
let id = UUID()
var url: URL?
var title: String?
import ConcurrencyExtras
private struct ObservationTrackingState: Sendable {
var isCancelled: Bool = false
var updateTaskID: UUID?
}
public func withObservationTracking<T>(_ apply: @escaping () -> T) -> AsyncThrowingStream<T, any Error> {
let (stream, continuation) = AsyncThrowingStream.makeStream(of: T.self)
import Foundation
// Foundation.CharacterSet should be called "UnicodeScalarSet"
// this operates on actual Characters
// TODO: Equatable doesn't work right: for instance defining a range vs defining a set with the same values will not be equal
indirect enum CharacterSet: Sendable, Hashable {
case closedRange(ClosedRange<Character>)
case set(Set<Character>)
@davbeck
davbeck / WKUIDelegate.m
Last active September 28, 2023 06:59
Boilerplate implementation of WKUIDelegate to support Javascript alerts.
#pragma mark - WKUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)())completionHandler
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil
message:message
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
completionHandler();
// example of what the macros could be expanded into for XCTestCase
final class PostsCoordinatorTests: XCTestCase {
func test_addPost() async throws {
let coordinator = PostsCoordinator()
coordinator.createPost()
XCTAssert(coordinator.postCount == 1)
}
func test_hasExistingPosts_countsPosts() async throws {
@davbeck
davbeck / README.md
Created June 19, 2019 22:07
A wrapper for UICollectionViewDiffableDataSource that also handles updates to data

UICollectionViewDiffableDataSource does an excellent job of handling changes to data and updating the items accordingly. However, there seems to be no good way to handle updates to existing items. If you follow the samples that Apple provides and define Equatable and Hashable to use an id instead of the complete models value, value changes won't cause the collection view to update those cells. If you leave Equatable as it should be and have it compare all values of a model, the cell will update, but it will completely replace the old cell, causing an undesirable "flash".

UICollectionViewComparableDataSource wraps a UICollectionViewDiffableDataSource and will check for items that have been updated, but not removed or added.

This allows us to make updates to a cell without completely reloading it. This is especially usefull if your cells have some sort of temporary state.

This is just an expirement. Use at your own risk.

@davbeck
davbeck / DisplayLink.swift
Created July 20, 2019 18:42
A Combine Publisher version of CADisplayLink.
import Foundation
struct Weak<Value: AnyObject> {
weak var value: Value?
init(_ value: Value) {
self.value = value
}
}
@davbeck
davbeck / assets.rb
Last active January 18, 2023 01:35
Automatic Enum-based Xcassets in Swift
#!/usr/bin/env ruby
require "active_support"
def assetCatalogsAtPath(path)
results = []
contents = Dir.entries(path)
import UIKit
import Combine
public extension Task {
/// Keep a reference to a task that can be cancelled.
func store(in set: inout Set<AnyCancellable>) {
set.insert(AnyCancellable {
self.cancel()
})
}