• Stars
    star
    124
  • Rank 288,207 (Top 6 %)
  • Language
    Swift
  • License
    MIT License
  • Created almost 3 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

🕵️‍♂️ An elegant SwiftUI Form builder to create a searchable Settings and DebugMenu screens for iOS.

🕵️‍♂️ SherlockForms

What one man can invent Settings UI, another can discover its field.

-- Sherlock Forms

An elegant SwiftUI Form builder to create a searchable Settings and DebugMenu screens for iOS.

(Supports from iOS 14, except .searchable works from iOS 15)

Overview

Normal Searching Context Menu
UserDefaults App Info Device Info

This repository consists of 3 modules:

  1. SherlockForms: SwiftUI Form builder to enhance cell findability using iOS 15 .searchable.
    • Various form cells to automagically interact with .searchable, including Text, Button, Toggle, Picker, NavigationLink, etc.
    • "Copy text" from context menu by long-press
  2. SherlockDebugForms: Useful app/device info-views and helper methods, specifically for debugging purpose.
    • App Info view
    • Device Info view
    • UserDefaults Editor
    • TODO: File Browser
    • TODO: Console Logger
  3. SherlockHUD: Standalone, simple-to-use Notification View (Toast) UI used in SherlockForms

Examples

SherlockForms & SherlockDebugForms

From SherlockForms-Gallery app:

import SwiftUI
import SherlockDebugForms

/// NOTE: Each view that owns `SherlockForm` needs to conform to `SherlockView` protocol.
@MainActor
struct RootView: View, SherlockView
{
    /// NOTE:
    /// `searchText` is required for `SherlockView` protocol.
    /// This is the only requirement to define as `@State`, and pass it to `SherlockForm`.
    @State public var searchText: String = ""

    @AppStorage("username")
    private var username: String = "John Appleseed"

    @AppStorage("language")
    private var languageSelection: Int = 0

    @AppStorage("status")
    private var status = Constant.Status.online

    ... // Many more @AppStorage properties...

    var body: some View
    {
        // NOTE:
        // `SherlockForm` and `xxxCell` are where all the search magic is happening!
        // Just treat `SherlockForm` as a normal `Form`, and use `Section` and plain SwiftUI views accordingly.
        SherlockForm(searchText: $searchText) {

            // Simple form cells.
            Section {
                textCell(title: "User", value: username)
                arrayPickerCell(title: "Language", selection: $languageSelection, values: Constant.languages)
                casePickerCell(title: "Status", selection: $status)
                toggleCell(title: "Low Power Mode", isOn: $isLowPowerOn)

                sliderCell(
                    title: "Speed",
                    value: $speed,
                    in: 0.5 ... 2.0,
                    step: 0.1,
                    maxFractionDigits: 1,
                    valueString: { "x\($0)" },
                    sliderLabel: { EmptyView() },
                    minimumValueLabel: { Image(systemName: "tortoise") },
                    maximumValueLabel: { Image(systemName: "hare") },
                    onEditingChanged: { print("onEditingChanged", $0) }
                )

                stepperCell(
                    title: "Font Size",
                    value: $fontSize,
                    in: 8 ... 24,
                    step: 1,
                    maxFractionDigits: 0,
                    valueString: { "\($0) pt" }
                )
            }

            // Navigation Link Cell (`navigationLinkCell`)
            Section {
                navigationLinkCell(
                    title: "UserDefaults",
                    destination: { UserDefaultsListView() }
                )
                navigationLinkCell(
                    title: "App Info",
                    destination: { AppInfoView() }
                )
                navigationLinkCell(
                    title: "Device Info",
                    destination: { DeviceInfoView() }
                )
                navigationLinkCell(title: "Custom Page", destination: {
                    CustomView()
                })
            }

            // Buttons
            Section {
                buttonCell(
                    title: "Reset UserDefaults",
                    action: {
                        Helper.deleteUserDefaults()
                        showHUD(.init(message: "Finished resetting UserDefaults"))
                    }
                )

                buttonDialogCell(
                    title: "Delete All Contents",
                    dialogTitle: nil,
                    dialogButtons: [
                        .init(title: "Delete All Contents", role: .destructive) {
                            try await deleteAllContents()
                            showHUD(.init(message: "Finished deleting all contents"))
                        },
                        .init(title: "Cancel", role: .cancel) {
                            print("Cancelled")
                        }
                    ]
                )
            }
        }
        .navigationTitle("Settings")
        // NOTE:
        // Use `formCopyable` here to allow ALL `xxxCell`s to be copyable.
        .formCopyable(true)
    }
}

To get started:

  1. Conform your Settings view to protocol SherlockView
  2. Add @State var searchText: String to your view
  3. Inside view's body, use SherlockForm (just like normal Form), and use various built-in form components:
    • Basic built-in cells
      • textCell
      • textFieldCell
      • textEditorCell
      • buttonCell
      • buttonDialogCell (iOS 15)
      • navigationLinkCell
      • toggleCell
      • arrayPickerCell
      • casePickerCell
      • datePickerCell
      • sliderCell
      • stepperCell
    • List
      • simpleList
      • nestedList
    • More customizable cells (part of ContainerCell)
      • hstackCell
      • vstackCell
  4. (Optional) Attach .formCellCopyable(true) to each cell or entire form.
  5. (Optional) Attach .enableSherlockHUD(true) to topmost view hierarchy to enable HUD

To customize cell's internal content view rather than cell itself, use .formCellContentModifier which may solve some troubles (e.g. context menu) when customizing cells.

SherlockHUD

import SwiftUI
import SherlockHUD

@main
struct MyApp: App
{
    var body: some Scene
    {
        WindowGroup {
            NavigationView {
                RootView()
            }
            .enableSherlockHUD(true) // Set at the topmost view!
        }
    }
}

@MainActor
struct RootView: View
{
    /// Attaching `.enableSherlockHUD(true)` to topmost view will allow using `showHUD`.
    @Environment(\.showHUD)
    private var showHUD: (HUDMessage) -> Void

    var body: some View
    {
        VStack(spacing: 16) {
            Button("Tap") {
                showHUD(HUDMessage(message: "Hello SherlockForms!", duration: 2, alignment: .top))
                // alignment = top / center / bottom (default)
                // Can also attach custom view e.g. ProgressView. See also `HUDMessage.loading`.
            }
        }
        .font(.largeTitle)
    }
}

See SherlockHUD-Demo app for more information.

Acknowledgement

License

MIT

More Repositories

1

SwiftRewriter

📝 Swift code formatter using SwiftSyntax.
Swift
825
star
2

RxAutomaton

🤖 RxSwift + State Machine, inspired by Redux and Elm.
Swift
715
star
3

Cassowary

An incremental linear constraint-solving algorithm (Auto Layout) in Swift.
Swift
501
star
4

Harvest

🌾 Harvest: Apple's Combine.framework + State Machine, inspired by Elm.
Swift
385
star
5

YIPopupTextView

facebook's post-like input text view for iOS (Beerware license)
Objective-C
245
star
6

YIFullScreenScroll

Pinterest-like scroll-to-fullscreen UI for iOS5+.
Objective-C
214
star
7

ReactiveAutomaton

🤖 ReactiveCocoa + State Machine, inspired by Redux and Elm.
Swift
207
star
8

Harvest-SwiftUI-Gallery

🖼 Gallery App for Harvest (Elm Architecture + Optics) + SwiftUI + Combine.
Swift
161
star
9

YIInnerShadowView

Inner-shadow UIView/CALayer for iOS.
Objective-C
155
star
10

YISplashScreen

Easy splash screen + animation maker for iOS5+.
Objective-C
141
star
11

Actomaton

🎭 Swift async/await & Actor-powered effectful state-management framework.
Swift
139
star
12

SwiftElm

Reactive + Automaton + VTree in Swift, inspired by Elm.
Swift
103
star
13

VTree

VirtualDOM for Swift (iOS, macOS)
Swift
91
star
14

RxProperty

A get-only `BehaviorRelay ` that is (almost) equivalent to ReactiveSwift's `Property`
Swift
85
star
15

FunRouter

Functional & type-safe URL routing example for http://2016.funswiftconf.com
Swift
82
star
16

Swizzle

Method-Swizzling for Swift.
Swift
81
star
17

Flexbox

Swift wrapper of facebook/yoga (CSS Flexbox layout engine).
Swift
76
star
18

Zelkova

Elm/React.js-like architecture in Swift, powered by ReactiveSwift and LayoutKit.
Swift
69
star
19

ReactiveCocoaCatalog

UI Catalog for ReactiveCocoa.
Swift
60
star
20

YISwipeShiftCaret

Swipe-to-shift text input caret for iOS (no private APIs)
Objective-C
47
star
21

DebugLog

DebugLog macro alternative for Swift.
Swift
44
star
22

HigherKindSwift

An experimental Higher Kinded Types in Swift.
Swift
44
star
23

Await

Swift port of C# Await using Cocoa's Run Loop mechanism.
Swift
43
star
24

MultibyteDescription

A better way to NSLog multibyte string for OSX/iOS. (see also: http://qiita.com/items/85437eba2623f6ffbdbd)
Objective-C
41
star
25

YIDragScrollBar

Attaches draggable scroll bar on top of original UIScrollView for iOS5+, works like a drug.
Objective-C
37
star
26

Actomaton-Gallery

🖼 Gallery App for Actomaton (async/await + Elm Architecture) + SwiftUI.
Swift
30
star
27

YIDetectWindow

A subclass of UIWindow for detecting shake, status-bar-tap, long-press, touchBegan/Moved/Ended/Cancelled, via NSNotification.
Objective-C
29
star
28

FunAsync

⏳ Collection of Swift 5.5 async/await utility functions.
Swift
25
star
29

Harvest-SwiftUI-GameOfLife

🧬 Conway's Game of Life written in SwiftUI + Harvest
Swift
24
star
30

YIEmoji

NSString addition for iOS Emoji.
Objective-C
23
star
31

Swift-Intersection

Extensible records / intersection type in Swift.
Swift
21
star
32

SwiftUI-PhotoPicker

iOS 14 PHPickerViewController wrapper for SwiftUI with data loader support.
Swift
20
star
33

YIStrictEdgePanGesture

Never get angry with UINavigationController's interactivePopGestureRecognizer.
Objective-C
18
star
34

ImagePlaceholder

Yet another UIImage / NSImage placeholder written in Swift.
Swift
18
star
35

SwiftAndLogic

Sample code for iOSDC Japan 2019 and NSSpain 2019
Swift
16
star
36

OrientationKit

iOS device/interface/image/video orientation translation & detection using CoreMotion + SwiftUI + Combine.
Swift
14
star
37

ShapeLayerView

CAShapeLayer-backed UIView subclass that synchronizes with UIKit-internal animations, e.g. orientation change.
Swift
12
star
38

AsyncHotStream

♨️ A missing hot stream in Swift Concurrency.
Swift
12
star
39

YIEdgePanGestureRecognizer

A subclass of UIPanGestureRecognizer which only activates at the edge of the view.
Objective-C
12
star
40

Swift-Union

Poor man's untagged union type in Swift.
Swift
11
star
41

YIHideableTabBar

UITabBarController category to show/hide UITabBar for iOS.
Objective-C
11
star
42

Harvest-SwiftUI-VideoDetector

📹 Video image/text recognizers written in SwiftUI + Harvest + iOS Vision + SwiftyTesseract
Swift
11
star
43

YIVariableViewSize

Layout subviews first, then its container. Not using AutoLayout, works on iOS5+.
Objective-C
10
star
44

Swift-Lens-Example

Swift Lens example
Swift
9
star
45

FunOptics

🔍Simple functional Optics in Swift
Swift
9
star
46

AVFoundation-Combine

AVFoundation + Combine extensions
Swift
8
star
47

DDFileReader

Swift port of DDFileReader by Dave DeLong (http://stackoverflow.com/a/3711079/666371)
Swift
7
star
48

YILogHook

NSLog-Hook using _NSSetLogCStringFunction (private API)
Objective-C
7
star
49

AnyScheduler

iOS 13 Combine's type-erased AnyScheduler.
Swift
6
star
50

YITimeTracker

A simple time-tracking tool which can easily integrate with other libraries e.g. SVProgressHUD, MTStatusBarOverlay.
Objective-C
5
star
51

iOS6-ForwardAutorotate

UIKit-additions to forward iOS6 rotation methods.
Objective-C
5
star
52

MNIST-iOS-Demo

MNIST-iOS demo with PyTorch -> ONNX -> CoreML conversion
Swift
3
star
53

appstore-node-coffee

AppStore review scraper using node+CoffeeScirpt
CoffeeScript
3
star
54

YIRightTouchableToolbar

Bug fix for right UIBarButtonItem not responding at bottom toolbar in iOS 7.0.3.
Objective-C
3
star
55

iOS15-SwiftUI-Navigation-Bug

Demonstrates SwiftUI Navigation behavior change from iOS 14 to iOS 15 which disallows single-source-of-truth state management.
3
star
56

YICustomModal

Custom modal, mainly for iOS5 youtube-fullscreen-dismiss bug (see also: https://github.com/inamiy/ModalYoutubeIOS5Bug)
Objective-C
2
star
57

YIHorizontalTableView

Transformed-UITableView to achieve horizontal scrolling for iOS.
Objective-C
1
star
58

inamiy

Welcome to a special repository!
1
star
59

YIPickerActionSheet

UIActionSheet+UIPickerView for iOS
Objective-C
1
star
60

inamiy.github.com

1
star
61

ToAnyObject

Cocoa-friendly AnyObject (and JSON) minimal encoder using Mirror API.
Swift
1
star
62

YINilHandling

NSArray/NSDictionary categories to nullify/ignore nil value for iOS.
Objective-C
1
star
63

Log-YIHelper

log macros for iOS
C++
1
star
64

ModalYoutubeIOS5Bug

Modal+WebView+Youtube Bug, found in iOS5.1 (It's now OK in iOS6 beta 2)
Objective-C
1
star
65

iOS7-ToolbarTouchBug

Demo for right UIBarButtonItem not responding at bottom toolbar in iOS 7.0.3.
Objective-C
1
star
66

Test

Test
1
star
67

github-experiment

Shell
1
star