ℹ️ This article is also available on his blog.
Layout and Drawing are two different things:
- Layout defines only the positions and sizes of all views on screen.
- Drawing specifies how each view is rendered (how it looks).
@available(iOS 15.0, *) | |
struct TwinkleView:View { | |
private func position(in proxy: GeometryProxy, sparkle:Sparkle) -> CGPoint { | |
let radius = min(proxy.size.width, proxy.size.height) / 2.0 | |
let drawnRadius = (radius - 5) * sparkle.position.x | |
let angle = Double.pi * 2.0 * sparkle.position.y | |
let x = proxy.size.width * 0.5 + drawnRadius * cos(angle) | |
let y = proxy.size.height * 0.5 + drawnRadius * sin(angle) |
// MARK: - TCAView | |
public protocol TCAView: View where Body == WithViewStore<ScopedState, ScopedAction, Content> { | |
associatedtype ViewState | |
associatedtype ViewAction | |
associatedtype ScopedState | |
associatedtype ScopedAction | |
associatedtype Content |
class FirebaseCoordinator { | |
static let shared = FirebaseCoordinator() | |
static let initialize: Void = { | |
/// We modify Google Firebase (and eventually Analytics) to load the mac-specific plist at runtime. | |
/// Google enforces that we have a file named "GoogleService-Info.plist" in the app resources. | |
/// This is unfortunate since we need two different files based on iOS and Mac version | |
/// One solution is a custom build step that copies in the correct file: | |
/// https://stackoverflow.com/questions/37615405/use-different-googleservice-info-plist-for-different-build-schemes | |
/// However, this is basically impossible since Catalyst doesn't set any custom build variables, so detection is extremely difficult. | |
/// We swizzle to modify the loading times. |
ℹ️ This article is also available on his blog.
Layout and Drawing are two different things:
import UIKit | |
import AVKit | |
class VideoView: UIView { | |
// video layer that will stream the url | |
private let videoLayer = AVPlayerLayer() | |
// pan gesture used for scrubbing | |
private let panGesture = UIPanGestureRecognizer() |
The libdispatch is one of the most misused API due to the way it was presented to us when it was introduced and for many years after that, and due to the confusing documentation and API. This page is a compilation of important things to know if you're going to use this library. Many references are available at the end of this document pointing to comments from Apple's very own libdispatch maintainer (Pierre Habouzit).
My take-aways are:
You should create very few, long-lived, well-defined queues. These queues should be seen as execution contexts in your program (gui, background work, ...) that benefit from executing in parallel. An important thing to note is that if these queues are all active at once, you will get as many threads running. In most apps, you probably do not need to create more than 3 or 4 queues.
Go serial first, and as you find performance bottle necks, measure why, and if concurrency helps, apply with care, always validating under system pressure. Reuse
// Douglas Hill, February 2018 | |
import Foundation | |
/// Returns a localised string with the key as an enum case so the compiler checks it exists. | |
/// The enum should be automatically generated using UpdateLocalisedStringKeys.swift. | |
public func localisedString(_ key: LocalisedStringKey) -> String { | |
return Bundle.main.localizedString(forKey: key.rawValue, value: nil, table: nil) | |
} |