Line limit in TextEditor (SwiftUI) not working - xcode

I've seen a lot of answers that simply say to use the limit limit view modifier but it doesn't seem to work:
mport SwiftUI
struct TextEditorTest: View {
#State var text: String = "Type in here"
var body: some View {
VStack {
Text("Sample Text A")
TextEditor(text: $text)
.lineLimit(3)
Spacer()
}
}
}
struct TextEditorTest_Previews: PreviewProvider {
static var previews: some View {
TextEditorTest()
}
}

Related

"Result of 'MainView' initializer is unused" -- trying to filter NavigationView in SwiftUI

I am trying to piece together a custom NavigationView in SwiftUI with Buttons for filtering. In this simple step I am just trying to change '.navigationTitle(title)' through filtering with three buttons ('header1', 'header2', 'header3'), however it is not working.
You can find a visual of this code here
ContentView:
struct ContentView: View {
var body: some View {
MainView(filter: .header1)
}
}
MainView:
struct MainView: View {
enum SourceType {
case header1, header2, header3
}
#EnvironmentObject var sourceItems: SourceItems
let filter: SourceType
var body: some View {
NavigationView {
List {
HeaderView()
ForEach(0..<10) { sourceItem in
NavigationLink(destination: Text("Destination")) {
Text("Item: \(sourceItem)")
}
}
}
.listStyle(.inset)
.navigationTitle(title) // I am trying to make this change
}
}
var title: String {
switch filter {
case .header1:
return "Header 1"
case .header2:
return "Header 2"
case .header3:
return "Header 3"
}
}
}
struct MainView_Previews: PreviewProvider {
static var previews: some View {
MainView(filter: .header1)
.environmentObject(SourceItems())
}
}
HeaderView (This is where I get the warnings):
struct HeaderView: View {
#StateObject var sourceItems = SourceItems()
var body: some View {
HStack {
Button(action: {
MainView(filter: .header1)
}, label: {
Text("Header 1")
})
.buttonStyle(PlainButtonStyle())
Spacer()
Button(action: {
MainView(filter: .header2)
}, label: {
Text("Header 2")
})
.buttonStyle(PlainButtonStyle())
Spacer()
Button(action: {
MainView(filter: .header3)
}, label: {
Text("Header 3")
})
.buttonStyle(PlainButtonStyle())
}
.environmentObject(sourceItems)
}
}
The code runs but the buttons don't filter.
Thanks for any help (I am new to SwiftUI)!

Xcode: Button action between files/views

Xcode complete beginner
Trying to make searchbar appear in different view than where the button is placed. When pressing magnifying-glass (button placed in ContentView), I want the text to appear in FeedView. How? #Published/ObservedObject/State...?? I have no knowledge just like to play around and learn. So 1. press magnifying-glass 2. makes the text appear (needs to be in different views)
ContentView:
import SwiftUI
struct ContentView: View {
#State private var doSearch = false
var body: some View {
Button {
doSearch.toggle()
} label: {
Image(systemName: "magnifyingglass")
.foregroundColor(Color(.black))
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
FeedView:
import SwiftUI
struct FeedView: View {
#State private var doSearch = false
var body: some View {
HStack {
if doSearch {
Text("search bar here")
}
}
}
}
Images:
ContentView
FeedView

SwiftUI presenting sheet with Binding variable doesn't work when first presented

I'm trying to present a View in a sheet with a #Binding String variable that just shows/binds this variable in a TextField.
In my main ContentView I have an Array of Strings which I display with a ForEach looping over the indices of the Array, showing a Button each with the text of the looped-over-element.
The Buttons action is simple: set an #State "index"-variable to the pressed Buttons' Element-index and show the sheet.
Here is my ContentView:
struct ContentView: View {
#State var array = ["first", "second", "third"]
#State var showIndex = 0
#State var showSheet = false
var body: some View {
VStack {
ForEach (0 ..< array.count, id:\.self) { i in
Button("\(array[i])") {
showIndex = i
showSheet = true
}
}
// Text("\(showIndex)") // if I uncomment this line, it works!
}
.sheet(isPresented: $showSheet, content: {
SheetView(text: $array[showIndex])
})
.padding()
}
}
And here is the SheetView:
struct SheetView: View {
#Binding var text: String
#Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
TextField("text:", text: $text)
Button("dismiss") {
presentationMode.wrappedValue.dismiss()
}
}.padding()
}
}
The problem is, when I first open the app and press on the "second" Button, the sheet opens and displays "first" in the TextField. I can then dismiss the Sheet and press the "second" Button again with the same result.
If I then press the "third" or "first" Button everything works from then on. Pressing any Button results in the correct behaviour.
Preview
Interestingly, if I uncomment the line with the Text showing the showIndex-variable, it works from the first time on.
Is this a bug, or am I doing something wrong here?
You should use custom Binding, custom Struct for solving the issue, it is complex issue. See the Example:
struct ContentView: View {
#State private var array: [String] = ["first", "second", "third"]
#State private var customStruct: CustomStruct?
var body: some View {
VStack {
ForEach (array.indices, id:\.self) { index in
Button(action: { customStruct = CustomStruct(int: index) }, label: {
Text(array[index]).frame(width: 100)
})
}
}
.frame(width: 300, height: 300, alignment: .center)
.background(Color.gray.opacity(0.5))
.sheet(item: $customStruct, content: { item in SheetView(text: Binding.init(get: { () -> String in return array[item.int] },
set: { (newValue) in array[item.int] = newValue }) ) })
}
}
struct CustomStruct: Identifiable {
let id: UUID = UUID()
var int: Int
}
struct SheetView: View {
#Binding var text: String
#Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
TextField("text:", text: $text)
Button("dismiss") {
presentationMode.wrappedValue.dismiss()
}
}.padding()
}
}
I had this happen to me before. I believe it is a bug, in that until it is used in the UI, it doesn't seem to get set in the ForEach. I fixed it essentially in the same way you did, with a bit of subtlety. Use it in each Button as part of the Label but hide it like so:
Button(action: {
showIndex = i
showSheet = true
}, label: {
HStack {
Text("\(array[i])")
Text(showIndex.description)
.hidden()
}
})
This doesn't change your UI, but you use it so it gets properly updated. I can't seem to find where I had the issue in my app, and I have changed the UI to get away from this, but I can't remember how I did it. I will update this if I can find it. This is a bit of a kludge, but it works.
Passing a binding to the index fix the issue like this
struct ContentView: View {
#State var array = ["First", "Second", "Third"]
#State var showIndex: Int = 0
#State var showSheet = false
var body: some View {
VStack {
ForEach (0 ..< array.count, id:\.self) { i in
Button(action:{
showIndex = i
showSheet.toggle()
})
{
Text("\(array[i])")
}.sheet(isPresented: $showSheet){
SheetView(text: $array, index: $showIndex)
}
}
}
.padding()
}
}
struct SheetView: View {
#Binding var text: [String]
#Binding var index: Int
#Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
TextField("text:", text: $text[index])
Button("dismiss") {
presentationMode.wrappedValue.dismiss()
}
}.padding()
}
}
In SwiftUI2 when calling isPresented if you don't pass bindings you're going to have some weird issues.
This is a simple tweak if you want to keep it with the isPresented and make it work but i would advise you to use the item with a costum struct like the answer of swiftPunk
This is how I would do it. You'll lose your form edits if you don't use #State variables.
This Code is Untested
struct SheetView: View {
#Binding var text: String
#State var draft: String
#Environment(\.presentationMode) var presentationMode
init(text: Binding<String>) {
self._text = text
self._draft = State(initialValue: text.wrappedValue)
}
var body: some View {
VStack {
TextField("text:", text: $draft)
Button("dismiss") {
text = draft
presentationMode.wrappedValue.dismiss()
}
}.padding()
}
}

Send data to next view - SwiftUI

So I have been trying to get a simple pass of data working with SwiftUI.
Basically the below script prints out a list of items (in a HStack) I then have each one linked to our Podcast() view.
What I am trying to do is pass through the podcast name to the next view. How do I achieve
this? As all the examples are about int which I am not using am using a String.
import SwiftUI
import RemoteImage
struct ContentView: View {
#State private var showAlert = false
#State var posts: [Program] = []
var body: some View {
NavigationView {
if posts.isEmpty {
Text("Loading")
} else {
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .bottom, spacing: 10) {
ForEach(posts) { post in
//return
NavigationLink(destination: Podcasts()){
RemoteImage(type: .url(URL(string:post.icon)!), errorView: { error in
Text(error.localizedDescription)
}, imageView: { image in
image
.resizable()
.renderingMode(.original)
/* .clipShape(Circle())
.shadow(radius: 10)
.overlay(Circle().stroke(Color.red, lineWidth: 5))*/
.aspectRatio(contentMode: .fit)
.frame(width:200, height:200)
}, loadingView: {
Text("Loading ...")
})
}
}
}.frame(height: 200)
}.frame(height: 200)
}
}.onAppear {
Api().getPosts { (posts) in
self.posts = posts
}
}.navigationBarTitle(Text("Home"))
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
The podcast View
import SwiftUI
struct Podcasts: View {
var body: some View {
NavigationView{
Text("Hello")
}.navigationBarTitle(Text("Podcast"))
}
}
struct Podcasts_Previews: PreviewProvider {
static var previews: some View {
Podcasts()
}
}
Pass post as constructor argument, like
ForEach(posts) { post in
//return
NavigationLink(destination: Podcasts(post: post)){
so now
struct Podcasts: View {
let post: Program
var body: some View {
// !! DON'T ADD SECOND NAVIGATION VIEW IN STACK
// !! - THERE MUST BE ONLY ONE
Text(post.name)
.navigationBarTitle(Text("Podcast"))
}
}

'Font' is not convertible to 'Font?' Swift UI

apparently I'm having this error that says 'Font is not convertible to 'Font?' in the code. Any suggestions ? Thanks! Here is the code below. I'm not sure exactly what's causing the issue. Everything seems to be fine before this.
import SwiftUI
struct ContentView: View {
#Environment(\.managedObjectContext) var managedObjectContext
#FetchRequest(fetchRequest: ToDoItem.getAllToDoItems()) var toDoItems:FetchedResults<ToDoItem>
#State private var newTodoItem = ""
var body: some View {
NavigationView {
List{
Section(header: Text("What's next ?")) {
HStack{
TextField("New Item", text: self.$newTodoItem)
Button(action: {
let toDoItem = ToDoItem(context: self.managedObjectContext)
toDoItem.Title = self.newTodoItem
toDoItem.createdAt = Date()
do {
try self.managedObjectContext.save()
} catch {
print(error)
}
self.newTodoItem = ""
}){
Image(systemName: "plus.circle.fill")
.foregroundColor(.green)
.imageScale(.large)
}
}
}.font(.headline)
Section(header: Text("To Do's")) {
ForEach(self.toDoItems) {todoItem in
ToDoItemView(title: todoItem.title!, createdAt: "\(todoItem.createdAt!)")
}
}
}
.navigationBarTitle(Text("My List"))
.navigationBarItems(trailing: EditButton())
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
To make it compilable you need explicitly specify type here
}.font(Font.headline)
and here
.foregroundColor(Color.green)
The problem is inside the Button action:
toDoItem.Title = self.newTodoItem
Change Title to title.
In general, when you get weird error messages in SwiftUI, just try to comment out lines until the error goes away. This will help you find the problematic code.

Resources