SwiftUI barcode does not show - ios

I need to create a barcode based on existing text.I found many solutions to this problem, but none worked, instead of a barcode I saw just a white rectangle. Here is non-working code, but maybe it will help you to find solution
struct TestBarCodeView: View {
var body: some View {
VStack {
BarCodeView(barcode: "1234567890")
.scaledToFit()
.padding().border(Color.red)
}
}
}
struct BarCodeView: UIViewRepresentable {
let barcode: String
func makeUIView(context: Context) -> UIImageView {
UIImageView()
}
func updateUIView(_ uiView: UIImageView, context: Context) {
uiView.image = UIImage(barcode: barcode)
}
}

you need to return a fully initialised view in makeUIView.
From the docs:
Creates the view object and configures its initial state.
The following code works for me:
struct BarCodeView: UIViewRepresentable {
let barcode: String
func makeUIView(context: Context) -> UIImageView {
let imageView = UIImageView()
imageView.image = UIImage(barcode: barcode)
return imageView
}
func updateUIView(_ uiView: UIImageView, context: Context) {
}
}
The updateUIView function does nothing, since the barcode property does not change.

Related

Hide Tools In PKCanvasView In SwiftUI

I have an iOS app which needs to capture user's signature
UI should be like this
I tried this using pencilKit as follows but,
It shows all the tools I don't need them to be visible
SwiftUIView
struct HandSignatureView: View {
var body: some View {
VStack {
Text("Place Your Signature Here")
.font(.title2)
.foregroundColor(.blue)
SignaturePadView()
}
.preferredColorScheme(.light)
}
}
UIViewRepresentable
struct SignaturePadView : UIViewRepresentable {
var canvasView = PKCanvasView()
let picker = PKToolPicker.init()
func makeUIView(context: Context) -> PKCanvasView {
self.canvasView.tool = PKInkingTool(.pen, color: .black, width: 15)
self.canvasView.becomeFirstResponder()
return canvasView
}
func updateUIView(_ uiView: PKCanvasView, context: Context) {
picker.addObserver(canvasView)
picker.setVisible(true, forFirstResponder: uiView)
DispatchQueue.main.async {
uiView.becomeFirstResponder()
}
}
}
This is the output I Got
picker.setVisible(false, forFirstResponder: uiView)
Hides tools but it draws nothing
If there's any good library I can use please be kind enough to share
Any Help will be appreciated Thank You !

Send data changes from UIKit, Wrapped inside UIViewRepresentable, to SwiftUI, and Rich Text Editor problem

I am working on a SwiftUI project, the functionalities it required is to make a Rich Text Editor on IOS.
The approach I am following is fairly simple, I used cbess/RichTextEditor link originally written in UIKit and import it into SwiftUI. To run the imported UIView, I wrap the view inside one UIViewRpresentable and add it into the ContentView struct of SwiftUI.
Now, I want to publish the data inside UIView and assign it to one of #state ContentView owns.
The code structure look similar to this:
For the ContentView (SwiftUI)
struct ContentView: View {
#State var textHtml: String = "" //I want all changes come from UIView be stored inside this
var body: some View {
VStack {
Cbess(
frameEditor: CGRect(x: 0, y: 40, width: 360, height: 400)
)
}
}
}
For the UiViewRepresentable
struct Cbess : UIViewRepresentable{
let frameEditor : CGRect
func makeUIView(context: Context) -> UIView {
let frameEditor = RichEditorView(frame: frameEditor)
let uiView : UIView = UIView()
uiView.addSubview(editorView)
return uiView
}
func updateUIView(_ uiView: UIView, context: Context) {
}
}
For the UiView(Simplified)
#objcMembers open class RichEditorView: UIView, {
var contentHTML : String // This variable get updated regularly
}
One additional question is that I want to make a Rich Text Editor by solely SwiftUI. How can I achieve it? Can you give me some keywords? Some Repo?
Any help is very appreciated! Thanks for read this whole question.
Use #Binding and delegate.
UIViewRepresentable view
struct Cbess : UIViewRepresentable {
#Binding var textHtml: String
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> RichEditorView {
let editorView = RichEditorView()
editorView.delegate = context.coordinator
return editorView
}
func updateUIView(_ uiView: RichEditorView, context: Context) {
}
class Coordinator: NSObject, RichEditorDelegate {
var parent: Cbess
init(_ parent: Cbess) {
self.parent = parent
}
// Use delegate here
func richEditor(_ editor: RichEditorView, contentDidChange content: String) {
self.parent.textHtml = content
print(content)
}
}
}
Your content view:
struct ContentView: View {
#State var textHtml: String = ""
var body: some View {
VStack {
Cbess(textHtml: $textHtml)
.frame(width: 360, height: 400)
Text("Print----\n\(textHtml)")
}
}
}

SIGABRT when navigating from ARView with cameraMode = `nonAR` to a regular AR mode ARView

I'm using SwiftUI and RealityKit to make an AR app. I am trying to transition from a nonAR camera mode ARView to a regular ARView using a NavigationLink, but I'm running into a SIGABRT and see the following error whenever I select the link:
validateTextureDimensions, line 1227: error 'MTLTextureDescriptor has width (4294967295) greater than the maximum allowed size of 16384.'
I've reproduced this behavior in a fresh RealityKit app with these simple views:
// ContentView (nonAR ARView)
import SwiftUI
import RealityKit
struct ContentView : View {
var body: some View {
NavigationView {
VStack {
ARViewContainer().edgesIgnoringSafeArea(.all)
NavigationLink(destination: ContentView2()) {
Text("Go!")
}
}
}
}
}
struct ARViewContainer: UIViewRepresentable {
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero, cameraMode: .nonAR, automaticallyConfigureSession: true)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) {}
}
// ContentView2 (AR ARView)
import SwiftUI
import RealityKit
struct ContentView2: View {
var body: some View {
return ARViewContainer2().edgesIgnoringSafeArea(.all)
}
}
struct ARViewContainer2: UIViewRepresentable {
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) {}
}
It seems like some cleanup needs to be performed with the first nonAR ARView before navigating but I'm not sure what the best way to manage that is. I saw the answer in this post and I tried adding a #Binding to ARViewContainer that I set in the parent view to flag to that the uiview should be removed in updateUIView before navigating, but I'm still hitting the crash :/ Any help here would be greatly appreciated!
I ended up resolving this for the time being by using a SceneKit view in place of the nonAR AR view.

How to find a SwiftUI view with custom tag or accessibility identifier?

Here's the sample code (using Introspect package):
import SwiftUI
import Introspect
struct ContentView: View {
let tag = 123
let id = "abc"
var body: some View {
ScrollView {
Text("Hello, world!")
.tag(tag)
.accessibility(identifier: id)
}.introspectScrollView { (scrollView) in
/// - Note: find with tag
if scrollView.viewWithTag(tag) != nil {
print("OK")
} else {
print("NOT OK")
}
/// - Note: find with accessibilityIdentifier
if findViewWithID(id, in: scrollView) != nil {
print("OK")
} else {
print("NOT OK")
}
}
}
func findViewWithID(_ id: String, in uiView: UIView) -> UIView? {
if uiView.accessibilityIdentifier == id {
return uiView
}
for view in uiView.subviews {
if let view = findViewWithID(id, in: view) {
return view
}
}
return nil
}
}
Why is tag or accessibilityIdentifier not propagated properly to the underlying view hierarchy?
Anyway, workaround for this turned out to be quite simple:
since "tagging" a view works just fine with UIKit view (even when wrapped in UIViewRepresentable) this simple wrapper comes to help:
struct TagView: UIViewRepresentable {
let tag: Int
func makeUIView(context: Context) -> UIView {
let uiView = UIView()
uiView.tag = tag
return uiView
}
func updateUIView(_ uiView: UIView, context: Context) {
uiView.tag = tag
}
}
then instead of trying to tag SwiftUI view directly, we can just add it to a ZStack containing the previous wrapper of a tagged UIKit view, which can later be found in the view hierarchy using viewWithTag(_:):
ZStack {
TagView(tag: 123)
Text("Hello, world!")
}

How to make a UIViewRepresentable #ViewBuilder work with dynamic content?

Is it possible to make a UIViewRepresentable view which takes a ViewBuilder argument work with dynamic content such as ForEach loops?
I have the following UIViewRepresentable view which I’m using to drop down to UIKit and get some custom UIScrollView behaviour:
struct CustomScrollView<Content:View>: UIViewRepresentable {
private let content: UIView
private let scrollView = CustomUIScrollView()
init(#ViewBuilder content: () -> Content) {
self.content = UIHostingController(rootView: content()).view
self.content.backgroundColor = .clear
}
func makeUIView(context: Context) -> UIView {
scrollView.addSubview(content)
// ...
return scrollView
}
func updateUIView(_ uiView: UIView, context: Context) {}
}
This works fine with static content as follows:
var body: some View {
CustomScrollView {
VStack {
ForEach(1..<50) { number in
Text(String(number))
}
}
}
}
But it fails with dynamic content, showing a blank view:
var body: some View {
CustomScrollView {
VStack {
ForEach(self.numbers) { number in
Text(String(number))
}
}
}
}
I understand that this is because when makeUIView() is called my dynamic data is empty, and it is later filled or updated. I evaluate my UIViewRepresentable’s content at init, and don’t update it in updateUIView().
How do you go about updating dynamic child content in updateUIView()? I tried capturing the #ViewBuilder parameter as an #escaping closure and evaluating it every time updateUIView() is called, which seems like the right solution (albeit inefficient?), but no luck so far.
Evaluation of #ViewBuilder fails because you mutating the wrong copy of the struct here
func updateUIView(_ uiView: UIView, context: Context) {}
You should mutate uiView's subviews directly with the content()
Updated Answer: Removed solution with a coordinator, because in some cases it works not as expected
The following might be helpful. It is not clear how absent CustomUIScrollView behaves (probably the issue is there), but using standard UIScrollView works with dynamic ForEach. Tested with Xcode 11.4 / iOS 13.4
struct CustomScrollView<Content:View>: UIViewRepresentable {
private let content: UIView
private let scrollView = UIScrollView()
init(#ViewBuilder content: () -> Content) {
self.content = UIHostingController(rootView: content()).view
self.content.backgroundColor = .clear
}
func makeUIView(context: Context) -> UIView {
content.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(content)
let constraints = [
content.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
content.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
content.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
content.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
content.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
]
scrollView.addConstraints(constraints)
return scrollView
}
func updateUIView(_ uiView: UIView, context: Context) {}
}
struct TestCustomScrollView: View {
private var items = Array(repeating: "Test", count: 50)
var body: some View {
CustomScrollView {
VStack {
ForEach(Array(items.enumerated()), id: \.0) { i, item in
Text("\(item) - \(i)")
}
}
}
}
}

Resources