135 lines
4.5 KiB
Swift
135 lines
4.5 KiB
Swift
//
|
|
// Array.swift
|
|
// Meta
|
|
//
|
|
// Created by david-swift on 26.05.24.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
extension Array: AnyView where Element == AnyView {
|
|
|
|
/// The array's view body is the array itself.
|
|
public var viewContent: Body { self }
|
|
|
|
/// Get the debug tree for an array of views.
|
|
/// - Parameter parameters: Whether the widget parameters should be visible in the tree.
|
|
/// - Returns: The tree.
|
|
public func getBodyDebugTree<ViewType>(parameters: Bool, type: ViewType.Type) -> String {
|
|
var description = ""
|
|
for view in self where view as? ViewType != nil {
|
|
let viewDescription: String
|
|
if let widget = view as? Widget {
|
|
viewDescription = widget.getViewDescription(parameters: parameters, type: type)
|
|
} else {
|
|
viewDescription = view.getDebugTree(parameters: parameters, type: type)
|
|
}
|
|
description += viewDescription + "\n"
|
|
}
|
|
if !description.isEmpty {
|
|
description.removeLast()
|
|
}
|
|
return description
|
|
}
|
|
|
|
/// Get a widget from a collection of views.
|
|
/// - Parameter modifiers: Modify views before being updated.
|
|
/// - Returns: A widget.
|
|
public func widget(modifiers: [(AnyView) -> AnyView]) -> Widget {
|
|
if count == 1, let widget = self[safe: 0]?.widget(modifiers: modifiers) {
|
|
return widget
|
|
} else {
|
|
var modified = self
|
|
for (index, view) in modified.enumerated() {
|
|
for modifier in modifiers {
|
|
modified[safe: index] = modifier(view)
|
|
}
|
|
}
|
|
// TODO: Is wrapper correct choice?
|
|
return Wrapper { modified }
|
|
}
|
|
}
|
|
|
|
/// Update a collection of views with a collection of view storages.
|
|
/// - Parameters:
|
|
/// - storage: The collection of view storages.
|
|
/// - modifiers: Modify views before being updated.
|
|
/// - updateProperties: Whether to update properties.
|
|
public func update(_ storage: [ViewStorage], modifiers: [(AnyView) -> AnyView], updateProperties: Bool) {
|
|
for (index, element) in enumerated() {
|
|
if let storage = storage[safe: index] {
|
|
element
|
|
.widget(modifiers: modifiers)
|
|
.updateStorage(storage, modifiers: modifiers, updateProperties: updateProperties)
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension Array where Element == String {
|
|
|
|
/// Get the C version of the array.
|
|
var cArray: UnsafePointer<UnsafePointer<CChar>?>? {
|
|
let cStrings = self.map { $0.utf8CString }
|
|
let cStringPointers = cStrings.map { $0.withUnsafeBufferPointer { $0.baseAddress } }
|
|
let optionalCStringPointers = cStringPointers + [nil]
|
|
var optionalCStringPointersCopy = optionalCStringPointers
|
|
optionalCStringPointersCopy.withUnsafeMutableBufferPointer { bufferPointer in
|
|
bufferPointer.baseAddress?.advanced(by: cStrings.count).pointee = nil
|
|
}
|
|
let flatArray = optionalCStringPointersCopy.compactMap { $0 }
|
|
let pointer = UnsafeMutablePointer<UnsafePointer<CChar>?>.allocate(capacity: flatArray.count + 1)
|
|
for (index, element) in flatArray.enumerated() {
|
|
pointer.advanced(by: index).pointee = element
|
|
}
|
|
pointer.advanced(by: flatArray.count).pointee = nil
|
|
return UnsafePointer(pointer)
|
|
}
|
|
|
|
}
|
|
|
|
extension Array {
|
|
|
|
/// Accesses the element at the specified position safely.
|
|
/// - Parameters:
|
|
/// - index: The position of the element to access.
|
|
///
|
|
/// Access and set elements the safe way:
|
|
/// ```swift
|
|
/// var array = ["Hello", "World"]
|
|
/// print(array[safe: 2] ?? "Out of range")
|
|
/// ```
|
|
public subscript(safe index: Int?) -> Element? {
|
|
get {
|
|
if let index, indices.contains(index) {
|
|
return self[index]
|
|
}
|
|
return nil
|
|
}
|
|
set {
|
|
if let index, let value = newValue, indices.contains(index) {
|
|
self[index] = value
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension Array where Element: Identifiable {
|
|
|
|
/// Accesses the element with a certain id safely.
|
|
/// - Parameters:
|
|
/// - id: The child's id.
|
|
///
|
|
/// Access and set elements the safe way:
|
|
/// ```swift
|
|
/// var array = ["Hello", "World"]
|
|
/// print(array[safe: 2] ?? "Out of range")
|
|
/// ```
|
|
public subscript(id id: Element.ID) -> Element? {
|
|
self[safe: firstIndex { $0.id == id }]
|
|
}
|
|
|
|
}
|