Add TextField
This commit is contained in:
parent
1b5e49486e
commit
7dd0c8aae0
|
@ -49,12 +49,7 @@ playground.xcworkspace
|
|||
.build/
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||
#
|
||||
# Pods/
|
||||
Pods/
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from the Xcode workspace
|
||||
# *.xcworkspace
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
2.6.4
|
|
@ -0,0 +1,3 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
gem "cocoapods", "1.8.4"
|
|
@ -0,0 +1,83 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.1)
|
||||
activesupport (4.2.11.1)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
algoliasearch (1.27.1)
|
||||
httpclient (~> 2.8, >= 2.8.3)
|
||||
json (>= 1.5.1)
|
||||
atomos (0.1.3)
|
||||
claide (1.0.3)
|
||||
cocoapods (1.8.4)
|
||||
activesupport (>= 4.0.2, < 5)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.8.4)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 1.2.2, < 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-stats (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.4.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
fourflusher (>= 2.3.0, < 3.0)
|
||||
gh_inspector (~> 1.0)
|
||||
molinillo (~> 0.6.6)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (~> 1.4)
|
||||
xcodeproj (>= 1.11.1, < 2.0)
|
||||
cocoapods-core (1.8.4)
|
||||
activesupport (>= 4.0.2, < 6)
|
||||
algoliasearch (~> 1.0)
|
||||
concurrent-ruby (~> 1.1)
|
||||
fuzzy_match (~> 2.0.4)
|
||||
nap (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.4)
|
||||
cocoapods-downloader (1.3.0)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.0)
|
||||
cocoapods-stats (1.1.0)
|
||||
cocoapods-trunk (1.4.1)
|
||||
nap (>= 0.8, < 2.0)
|
||||
netrc (~> 0.11)
|
||||
cocoapods-try (1.1.0)
|
||||
colored2 (3.1.2)
|
||||
concurrent-ruby (1.1.5)
|
||||
escape (0.0.4)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
httpclient (2.8.3)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (2.2.0)
|
||||
minitest (5.13.0)
|
||||
molinillo (0.6.6)
|
||||
nanaimo (0.2.6)
|
||||
nap (1.1.0)
|
||||
netrc (0.11.0)
|
||||
ruby-macho (1.4.0)
|
||||
thread_safe (0.3.6)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
xcodeproj (1.13.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.2.6)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
cocoapods (= 1.8.4)
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.3
|
|
@ -20,6 +20,7 @@
|
|||
C0C6D697238E007100DA6285 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C0C6D696238E007100DA6285 /* Preview Assets.xcassets */; };
|
||||
C0C6D69A238E007100DA6285 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C0C6D698238E007100DA6285 /* LaunchScreen.storyboard */; };
|
||||
C0C6D6A0238E00D300DA6285 /* Introspect.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0687012238DE85D00DAFD3D /* Introspect.framework */; };
|
||||
E0B11E0609FFA04A7B6A1418 /* Pods_IntrospectExamples.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5785749C354BCF848BC4EAD9 /* Pods_IntrospectExamples.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -33,6 +34,9 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
5785749C354BCF848BC4EAD9 /* Pods_IntrospectExamples.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_IntrospectExamples.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9BBE78DB32CCDC560004DB54 /* Pods-IntrospectExamples.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IntrospectExamples.debug.xcconfig"; path = "Target Support Files/Pods-IntrospectExamples/Pods-IntrospectExamples.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
B826284199E111BBEA21E76B /* Pods-IntrospectExamples.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IntrospectExamples.release.xcconfig"; path = "Target Support Files/Pods-IntrospectExamples/Pods-IntrospectExamples.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C0687012238DE85D00DAFD3D /* Introspect.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Introspect.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C0687015238DE85D00DAFD3D /* Introspect.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Introspect.h; sourceTree = "<group>"; };
|
||||
C0687016238DE85D00DAFD3D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
@ -73,12 +77,23 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C0C6D6A0238E00D300DA6285 /* Introspect.framework in Frameworks */,
|
||||
E0B11E0609FFA04A7B6A1418 /* Pods_IntrospectExamples.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
0534532308DF3E515053BF9F /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9BBE78DB32CCDC560004DB54 /* Pods-IntrospectExamples.debug.xcconfig */,
|
||||
B826284199E111BBEA21E76B /* Pods-IntrospectExamples.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C0687008238DE85D00DAFD3D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -87,6 +102,7 @@
|
|||
C0C6D68C238E006B00DA6285 /* IntrospectExamples */,
|
||||
C0687013238DE85D00DAFD3D /* Products */,
|
||||
C0C6D69F238E00D300DA6285 /* Frameworks */,
|
||||
0534532308DF3E515053BF9F /* Pods */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
@ -146,6 +162,7 @@
|
|||
C0C6D69F238E00D300DA6285 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5785749C354BCF848BC4EAD9 /* Pods_IntrospectExamples.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
|
@ -204,9 +221,11 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C0C6D69E238E007100DA6285 /* Build configuration list for PBXNativeTarget "IntrospectExamples" */;
|
||||
buildPhases = (
|
||||
9C6427CDD5EF4F1EAC75C7F9 /* [CP] Check Pods Manifest.lock */,
|
||||
C0C6D687238E006B00DA6285 /* Sources */,
|
||||
C0C6D688238E006B00DA6285 /* Frameworks */,
|
||||
C0C6D689238E006B00DA6285 /* Resources */,
|
||||
EC4E9FC6E0E62CFD8A53623A /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -286,6 +305,48 @@
|
|||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
9C6427CDD5EF4F1EAC75C7F9 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-IntrospectExamples-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
EC4E9FC6E0E62CFD8A53623A /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-IntrospectExamples/Pods-IntrospectExamples-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-IntrospectExamples/Pods-IntrospectExamples-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-IntrospectExamples/Pods-IntrospectExamples-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
C068700E238DE85D00DAFD3D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
|
@ -548,6 +609,7 @@
|
|||
};
|
||||
C0C6D69C238E007100DA6285 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9BBE78DB32CCDC560004DB54 /* Pods-IntrospectExamples.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
|
@ -567,6 +629,7 @@
|
|||
};
|
||||
C0C6D69D238E007100DA6285 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B826284199E111BBEA21E76B /* Pods-IntrospectExamples.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
<key>Introspect.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
<key>IntrospectExamples.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
<integer>3</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Introspect.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,12 +1,16 @@
|
|||
import SwiftUI
|
||||
|
||||
public enum Introspect {
|
||||
public static func findChild<AnyViewType: UIView>(ofType type: AnyViewType.Type, in root: UIView) -> AnyViewType? {
|
||||
|
||||
public static func findChild<AnyViewType: UIView>(
|
||||
ofType type: AnyViewType.Type,
|
||||
in root: UIView
|
||||
) -> AnyViewType? {
|
||||
for subview in root.subviews {
|
||||
if let tableView = subview as? AnyViewType {
|
||||
return tableView
|
||||
} else if let tableView = findChild(ofType: type, in: subview) {
|
||||
return tableView
|
||||
if let typed = subview as? AnyViewType {
|
||||
return typed
|
||||
} else if let typed = findChild(ofType: type, in: subview) {
|
||||
return typed
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -22,11 +26,44 @@ public enum Introspect {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
public static func findHostingView(from entry: UIView) -> UIView? {
|
||||
var superview = entry.superview
|
||||
while let s = superview {
|
||||
if NSStringFromClass(type(of: s)).contains("UIHostingView") {
|
||||
return s
|
||||
}
|
||||
superview = s.superview
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
public static func findViewHost(from entry: UIView) -> UIView? {
|
||||
var superview = entry.superview
|
||||
while let s = superview {
|
||||
if NSStringFromClass(type(of: s)).contains("ViewHost") {
|
||||
return s
|
||||
}
|
||||
superview = s.superview
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Allows to safely access an array element by index
|
||||
// Usage: array[safe: 2]
|
||||
private extension Array {
|
||||
public subscript(safe index: Int) -> Element? {
|
||||
guard index >= 0, index < endIndex else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self[index]
|
||||
}
|
||||
}
|
||||
|
||||
public struct IntrospectionView<ViewType: UIView>: UIViewRepresentable {
|
||||
|
||||
|
||||
let selector: (UIView) -> ViewType?
|
||||
let customize: (ViewType) -> Void
|
||||
|
||||
|
@ -39,7 +76,9 @@ public struct IntrospectionView<ViewType: UIView>: UIViewRepresentable {
|
|||
}
|
||||
|
||||
public func makeUIView(context: UIViewRepresentableContext<IntrospectionView>) -> UIView {
|
||||
return UIView(frame: .zero)
|
||||
let view = UIView(frame: .zero)
|
||||
view.accessibilityLabel = "IntrospectionUIView<\(ViewType.self)>"
|
||||
return view
|
||||
}
|
||||
|
||||
public func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<IntrospectionView>) {
|
||||
|
@ -93,8 +132,8 @@ public struct IntrospectionViewController<ViewControllerType: UIViewController>:
|
|||
extension View {
|
||||
public func introspectTableView(customize: @escaping (UITableView) -> ()) -> some View {
|
||||
return background(IntrospectionView(
|
||||
selector: { viewHost in
|
||||
Introspect.findAncestor(ofType: UITableView.self, from: viewHost)
|
||||
selector: { introspectionView in
|
||||
Introspect.findAncestor(ofType: UITableView.self, from: introspectionView)
|
||||
},
|
||||
customize: customize
|
||||
))
|
||||
|
@ -106,5 +145,27 @@ extension View {
|
|||
customize: customize
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
public func introspectTextField(customize: @escaping (UITextField) -> ()) -> some View {
|
||||
return self.background(IntrospectionView(
|
||||
selector: { introspectionView in
|
||||
guard let viewHost = Introspect.findViewHost(from: introspectionView) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let container = viewHost.superview,
|
||||
let viewHostIndex = container.subviews.firstIndex(of: viewHost),
|
||||
let textFieldContainer = container.subviews[safe: viewHostIndex + 1]
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return Introspect.findChild(
|
||||
ofType: UITextField.self,
|
||||
in: textFieldContainer
|
||||
)
|
||||
},
|
||||
customize: customize
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,12 +61,17 @@ struct NavigationExample: View {
|
|||
}
|
||||
|
||||
struct SimpleElementsExample: View {
|
||||
@State private var selection = 0
|
||||
@State private var test = ""
|
||||
var body: some View {
|
||||
HStack {
|
||||
Image(systemName: "folder")
|
||||
.introspectImageView { imageView in
|
||||
|
||||
TextField("Red", text: $test)
|
||||
.introspectTextField { textField in
|
||||
textField.layer.backgroundColor = UIColor.red.cgColor
|
||||
}
|
||||
|
||||
TextField("Green", text: $test)
|
||||
.introspectTextField { textField in
|
||||
textField.layer.backgroundColor = UIColor.green.cgColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
platform :ios, "13.0"
|
||||
inhibit_all_warnings!
|
||||
use_frameworks!
|
||||
|
||||
# Disable sending stats (takes too much time)
|
||||
ENV["COCOAPODS_DISABLE_STATS"] = "true"
|
||||
|
||||
target "IntrospectExamples"
|
||||
pod "Reveal-SDK", "24", :configurations => ['Debug']
|
|
@ -0,0 +1,16 @@
|
|||
PODS:
|
||||
- Reveal-SDK (24)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Reveal-SDK (= 24)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- Reveal-SDK
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Reveal-SDK: 5d7e56b8f018c0a88b3a2c10bf68d598bbd3b071
|
||||
|
||||
PODFILE CHECKSUM: 3558c3b60c01e8cff4f7b0ac1bd6ef19441afc81
|
||||
|
||||
COCOAPODS: 1.8.4
|
|
@ -9,13 +9,13 @@ SwiftUI | UIKit | Introspect
|
|||
--- | --- | ---
|
||||
List | UITableView | `.introspectTableView()` on a list child
|
||||
NavigationView | UINavigationController | `.introspectNavigationController()` on a navigation child
|
||||
TextField | UITextField | `.introspectTextField()`
|
||||
|
||||
|
||||
### Not implemented
|
||||
|
||||
SwiftUI | UIKit
|
||||
--- | ---
|
||||
TextField | UITextField
|
||||
Toggle | UISwitch
|
||||
Slider | UISlider
|
||||
Button | UIButton
|
||||
|
|
Loading…
Reference in New Issue