I have a button on top of a MKMapView. But the button does not get triggered when it's tapped on. Do you know what's missing?
MapView.swift
import SwiftUI
import UIKit
import MapKit
struct MapView: UIViewRepresentable {
func makeUIView(context: Context) -> MKMapView {
let mkMapView = MKMapView()
return mkMapView
}
func updateUIView(_ uiView: MKMapView, context: Context) { }
func makeCoordinator() -> Coordinator {
Coordinator()
}
class Coordinator: NSObject, MKMapViewDelegate { }
}
ContentView.swift
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
MapView()
Button(action: {
print("Tapped")
}) {
Image(systemName: "lock.fill")
}
}
}
}
Give it just a bit more internal space to be better recognizable. Here is fixed & tested variant (Xcode 12 / iOS 14):
struct TestButtonWithMap: View {
#State private var locked = true
var body: some View {
ZStack {
MapView()
Button(action: {
print("Tapped")
self.locked.toggle()
}) {
Image(systemName: locked ? "lock.fill" : "lock.open")
.padding() // << here !!
}
}
}
}
Related
I am trying to disable copy and paste functionality in a textField with the help of swift without using any separate cocoatouch class.
Can you suggest how to do it using Either keyboard extension or textfield extension.
Any response will be appreciated.
Create a custom TextField as use as follows
import SwiftUI
struct CustomeTextField: View {
#State var textStr = ""
var body: some View {
VStack(spacing: 10) {
Text("This is textfield:")
.font(.body)
.foregroundColor(.gray)
TextFieldWrapperView(text: self.$textStr)
.background(Color.gray)
.frame(width: 200, height: 50)
}
.frame(height: 40)
}
}
struct TextFieldWrapperView: UIViewRepresentable {
#Binding var text: String
func makeCoordinator() -> TFCoordinator {
TFCoordinator(self)
}
}
extension TextFieldWrapperView {
func makeUIView(context: UIViewRepresentableContext<TextFieldWrapperView>) -> UITextField {
let textField = UITextField()
textField.delegate = context.coordinator
return textField
}
func updateUIView(_ uiView: UITextField, context: Context) {
}
}
class TFCoordinator: NSObject, UITextFieldDelegate {
var parent: TextFieldWrapperView
init(_ textField: TextFieldWrapperView) {
self.parent = textField
}
func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
if action == #selector(UIResponderStandardEditActions.paste(_:)) {
return false
}
return canPerformAction(action: action, withSender: sender)
}
}
I have a UIViewController that I want presented from my SwiftUI view, the issue is that I need the UIViewController wrapped in a UINavigationController, how can I present that wrapped VC from my SwiftUI View?
This is what I've tried, it works for presenting the view controller but I do not know how to wrap it in a navigation controller:
struct ComposeTakeView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> ComposeTakeVC {
return ComposeTakeVC(nibName: "ComposeTakeVC", bundle: nil)
}
func updateUIViewController(_ uiViewController: ComposeTakeVC, context: Context) {
}
}
In the SwiftUI view:
.fullScreenCover(isPresented: $showComposeTake, content: {
ComposeTakeView()
})
I've also tried creating a new SwiftUI view with NavigationView and tool bar, but this does not show the tool bar button:
struct ComposeTakeNavView: View {
#Environment(\.presentationMode) var presentationMode
var body: some View {
NavigationView {
ComposeTakeView()
}
.toolbar {
Button {
presentationMode.wrappedValue.dismiss()
} label: {
Image(systemName: "xmark")
.foregroundColor(.black)
}
}
}
}
We can wrap it right inside representable and return just as base class, like
func makeUIViewController(context: Context) -> UIViewController {
let controller = ComposeTakeVC(nibName: "ComposeTakeVC", bundle: nil)
return UINavigationController(rootViewController: controller)
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
}
How do I add a seconds column to the UIDatePicker?
I am currently displaying this:
With this UIViewRepresentable in SwiftUI
struct DurationPicker: UIViewRepresentable {
#Binding var duration: TimeInterval
func makeUIView(context: Context) -> UIDatePicker {
let datePicker = UIDatePicker()
datePicker.datePickerMode = .countDownTimer
datePicker.addTarget(context.coordinator, action: #selector(Coordinator.updateDuration), for: .valueChanged)
return datePicker
}
func updateUIView(_ datePicker: UIDatePicker, context: Context) {
datePicker.countDownDuration = duration
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject {
let parent: DurationPicker
init(_ parent: DurationPicker) {
self.parent = parent
}
#objc func updateDuration(datePicker: UIDatePicker) {
parent.duration = datePicker.countDownDuration
}
}
}
Here is my view code for reference
struct ContentView: View {
#Binding var interval:TimeInterval
init( interval: Binding<TimeInterval> = .constant(0) ) {
_interval = interval
}
var body: some View {
NavigationView {
VStack {
Text("Hello, world!")
.padding()
DurationPicker(duration: $interval)
NavigationLink(destination: DetailView()) {
Text("Show Detail View")
}
}
}
}
}
I can't figure out how I might go about adding a seconds column, even though the official clock app on iOS displays one.
I am wondering if it's possible to combine a View and a UIViewControllerRepresentable in a same view.
I tried:
//Here I declare MyViewController:
class MyViewController: UIViewController {
override viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
}
}
struct MyViewControllerIntegrate: UIViewControllerRepresentable {
func makeUIViewController(context: UIViewControllerRepresentableContext<MyViewControllerIntegrate>) -> MyViewController {
return MyViewController()
}
func updateUIViewController(_ uiViewController: MyViewController, context: UIViewControllerRepresentableContext<MyViewControllerIntegrate>) {
}
}
struct MyView: View {
var body: some View {
Text("Hello StackOverflow!")
}
}
struct ContentView: View {
var body: some View {
MyView()
MyViewController()
.frame(height: 400)
}
}
Xcode shows me an error message:
Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type
Any hints? Thank you
Put them in Group (or in some stack, eg. VStack)
struct ContentView: View {
var body: some View {
Group {
MyView()
MyViewController()
.frame(height: 400)
}
}
}
Does somebody have all ready implemented a search bar using Apple component like UISearchBar with swiftui on tvos ?
I tried this UISearchBar(frame: .zero) but I got this error init(frame:)' is unavailable in tvOS
I only found solutions for ios.
The scheme of initial setup should be like below. Of course, the logic of searching/filtering/showing results is app specific.
import SwiftUI
import TVUIKit
struct SearchView: UIViewControllerRepresentable {
func makeUIViewController(context: UIViewControllerRepresentableContext<SearchView>) -> UINavigationController {
let controller = UISearchController(searchResultsController: context.coordinator)
controller.searchResultsUpdater = context.coordinator
return UINavigationController(rootViewController: UISearchContainerViewController(searchController: controller))
}
func updateUIViewController(_ uiViewController: UINavigationController, context: UIViewControllerRepresentableContext<SearchView>) {
}
func makeCoordinator() -> SearchView.Coordinator {
Coordinator()
}
typealias UIViewControllerType = UINavigationController
class Coordinator: UIViewController, UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
// do here what's needed
}
}
}
struct ContentView: View {
#State private var text: String = ""
var body: some View {
VStack {
SearchView()
Spacer()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}