新手 Swift:我不确定为什么不显示用户的名字? Swift UI
New To Swift: Im not sure why the names of the users are not displaying? Swift UI
所以我创建了这个项目来学习 Swift Ui 但我被卡住了。我不明白为什么 HomeView 不显示联系人姓名。我创建了 ContactModel 来存储联系人详细信息,并创建了 ContactViewModel 来存储 userDefaults.I 中的所有联系人,并将信息存储在 UserDefaults 中,但由于某种原因它无法正常工作。我添加了 Xcode 项目中的所有文件。感谢您的帮助!
@main
struct ContactsAppApp: App {
@StateObject var contactViewModel: ContactViewModel = ContactViewModel()
var body: some Scene {
WindowGroup {
NavigationView{
ContentView()
}
.environmentObject(contactViewModel)
}
}
}
struct ContentView: View {
var body: some View {
TabView{
HomeView()
.tabItem {
Image(systemName: "house")
.foregroundColor(.white)
Text("home")
}
AddContactView()
.tabItem{
Image(systemName: "laptopcomputer")
Text("work")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct ContactModel: Identifiable, Codable {
let id: String
let name: String
let phoneNumber: String
let email: String
init(id: String = UUID().uuidString, name: String, phoneNumber: String, email: String) {
self.id = id
self.name = name
self.phoneNumber = phoneNumber
self.email = email
}
func updateCompletion() -> ContactModel {
return ContactModel(id: id, name: name, phoneNumber: phoneNumber, email: email)
}
}
class ContactViewModel: ObservableObject {
@Published var items: [ContactModel] = [] {
didSet {
saveItems()
}
}
let itemsKey: String = "items_list"
init() {
getItems()
}
func getItems() {
guard
let data = UserDefaults.standard.data(forKey: itemsKey),
let savedItems = try? JSONDecoder().decode([ContactModel].self, from: data)
else { return }
self.items = savedItems
}
func deleteItem(indexSet: IndexSet) {
items.remove(atOffsets: indexSet)
}
func moveItem(from: IndexSet, to: Int) {
items.move(fromOffsets: from, toOffset: to)
}
func addItem(name: String, phoneNumber: String, email: String) {
let newItem = ContactModel(name: name, phoneNumber: phoneNumber, email: email)
items.append(newItem)
}
func updateItem(item: ContactModel) {
if let index = items.firstIndex(where: { [=16=].id == item.id }) {
items[index] = item.updateCompletion()
}
}
func saveItems() {
if let encodedData = try? JSONEncoder().encode(items) {
UserDefaults.standard.set(encodedData, forKey: itemsKey)
}
}
}
import SwiftUI
struct HomeView: View {
@EnvironmentObject var contactViewModel: ContactViewModel
var body: some View {
NavigationView {
VStack {
HStack{
Text("Contacts")
.font(.system(size: 35, weight: .bold))
.padding(.leading,30)
.padding(.top,20)
.foregroundColor(.white)
Spacer()
}
Spacer()
ScrollView{
ForEach(contactViewModel.items) { item in
contactWidget(name: item.name)
}
}
.padding(.top,20)
Button(action: {
print("touched")
}, label: {
NavigationLink(destination: AddContactView().navigationBarBackButtonHidden(true)) {
HStack{
ZStack{
RoundedRectangle(cornerRadius: 40)
.frame(width: 200, height: 50)
.foregroundColor(.blue)
Text("Add Contact")
.foregroundColor(.white)
}
}
}
.navigationBarHidden(true)
})
}
.background(.black)
}
.navigationBarHidden(true)
}
}
struct contactWidget : View{
let name: String
var body: some View{
ZStack {
RoundedRectangle(cornerRadius: 20)
.frame(width: 350, height: 100)
.foregroundColor(.gray)
HStack {
Image(systemName: "person")
.resizable()
.clipShape(Circle())
.frame(width: 40, height: 40)
Text(name)
.font(.system(size: 18, weight: .semibold))
Spacer()
HStack{
Circle()
.frame(width: 40, height: 40)
.foregroundColor(.orange)
Circle()
.frame(width: 40, height: 40)
.foregroundColor(.blue)
Circle()
.frame(width: 40, height: 40)
.foregroundColor(.pink)
}
}
.padding(.leading,40)
.padding(.trailing,30)
}
}
}
struct HomeView_Previews: PreviewProvider {
static var previews: some View {
NavigationView{
HomeView()
}
.environmentObject(ContactViewModel())
}
}
import SwiftUI
struct AddContactView: View {
@EnvironmentObject var contactViewModel: ContactViewModel
@State var contactName: String = ""
@State var phoneNumber: String = ""
@State var email: String = ""
var body: some View {
NavigationView {
VStack {
HStack{
Text("Contacts")
.font(.system(size: 35, weight: .bold))
.padding(.leading,30)
.padding(.top,20)
.foregroundColor(.white)
Spacer()
}
TextField("Enter name", text: $contactName)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
TextField("Enter Phone Number", text: $phoneNumber)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
TextField("Enter Email", text: $email)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
Text(contactName)
.foregroundColor(.white)
Spacer()
.padding(.top,20)
Button(action: {
contactViewModel.addItem(name: contactName, phoneNumber: phoneNumber, email: email)
contactName = ""
phoneNumber = ""
email = ""
}, label: {
NavigationLink(destination: HomeView().navigationBarBackButtonHidden(true)) {
HStack{
ZStack{
RoundedRectangle(cornerRadius: 40)
.frame(width: 200, height: 50)
.foregroundColor(.blue)
Text("Done")
.foregroundColor(.white)
}
}
}
.navigationBarHidden(true)
})
}
.background(.black)
}
.navigationBarHidden(true)
}
}
struct AddContactView_Previews: PreviewProvider {
static var previews: some View {
NavigationView{
AddContactView()
}
.environmentObject(ContactViewModel())
}
}
“...HomeView 不显示联系人姓名...”的原因是
因为 AddContactView
中的按钮标签内有 NavigationLink(destination: HomeView()....
。也就是说,点击被 NavigationLink
并在不执行按钮操作的情况下转到 HomeView
添加联系人, contactViewModel.addItem( ...)
。所以重组你的代码
NavigationLink
在它之外。
下面的示例代码应该可以解决您的问题。
struct AddContactView: View {
@EnvironmentObject var contactViewModel: ContactViewModel
@State var contactName: String = ""
@State var phoneNumber: String = ""
@State var email: String = ""
@State var goHome = false // <-- here
var body: some View {
NavigationView {
VStack {
HStack{
Text("Contacts")
.font(.system(size: 35, weight: .bold))
.padding(.leading,30)
.padding(.top,20)
.foregroundColor(.white)
Spacer()
}
TextField("Enter name", text: $contactName)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
TextField("Enter Phone Number", text: $phoneNumber)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
TextField("Enter Email", text: $email)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
Text(contactName).foregroundColor(.white)
Spacer().padding(.top,20)
Button(action: {
contactViewModel.addItem(name: contactName, phoneNumber: phoneNumber, email: email)
contactName = ""
phoneNumber = ""
email = ""
goHome = true // <-- here
}, label: {
HStack{
ZStack{
RoundedRectangle(cornerRadius: 40)
.frame(width: 200, height: 50)
.foregroundColor(.blue)
Text("Done")
.foregroundColor(.white)
}
}
})
// -- here
NavigationLink(destination: HomeView().navigationBarBackButtonHidden(true), isActive: $goHome) {
EmptyView()
}.navigationBarHidden(true)
}
.background(.black)
}
.navigationBarHidden(true)
}
}
类似HomeView
中的按钮,或者去掉Button
部分,只保留NavigationLink
所以我创建了这个项目来学习 Swift Ui 但我被卡住了。我不明白为什么 HomeView 不显示联系人姓名。我创建了 ContactModel 来存储联系人详细信息,并创建了 ContactViewModel 来存储 userDefaults.I 中的所有联系人,并将信息存储在 UserDefaults 中,但由于某种原因它无法正常工作。我添加了 Xcode 项目中的所有文件。感谢您的帮助!
@main
struct ContactsAppApp: App {
@StateObject var contactViewModel: ContactViewModel = ContactViewModel()
var body: some Scene {
WindowGroup {
NavigationView{
ContentView()
}
.environmentObject(contactViewModel)
}
}
}
struct ContentView: View {
var body: some View {
TabView{
HomeView()
.tabItem {
Image(systemName: "house")
.foregroundColor(.white)
Text("home")
}
AddContactView()
.tabItem{
Image(systemName: "laptopcomputer")
Text("work")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct ContactModel: Identifiable, Codable {
let id: String
let name: String
let phoneNumber: String
let email: String
init(id: String = UUID().uuidString, name: String, phoneNumber: String, email: String) {
self.id = id
self.name = name
self.phoneNumber = phoneNumber
self.email = email
}
func updateCompletion() -> ContactModel {
return ContactModel(id: id, name: name, phoneNumber: phoneNumber, email: email)
}
}
class ContactViewModel: ObservableObject {
@Published var items: [ContactModel] = [] {
didSet {
saveItems()
}
}
let itemsKey: String = "items_list"
init() {
getItems()
}
func getItems() {
guard
let data = UserDefaults.standard.data(forKey: itemsKey),
let savedItems = try? JSONDecoder().decode([ContactModel].self, from: data)
else { return }
self.items = savedItems
}
func deleteItem(indexSet: IndexSet) {
items.remove(atOffsets: indexSet)
}
func moveItem(from: IndexSet, to: Int) {
items.move(fromOffsets: from, toOffset: to)
}
func addItem(name: String, phoneNumber: String, email: String) {
let newItem = ContactModel(name: name, phoneNumber: phoneNumber, email: email)
items.append(newItem)
}
func updateItem(item: ContactModel) {
if let index = items.firstIndex(where: { [=16=].id == item.id }) {
items[index] = item.updateCompletion()
}
}
func saveItems() {
if let encodedData = try? JSONEncoder().encode(items) {
UserDefaults.standard.set(encodedData, forKey: itemsKey)
}
}
}
import SwiftUI
struct HomeView: View {
@EnvironmentObject var contactViewModel: ContactViewModel
var body: some View {
NavigationView {
VStack {
HStack{
Text("Contacts")
.font(.system(size: 35, weight: .bold))
.padding(.leading,30)
.padding(.top,20)
.foregroundColor(.white)
Spacer()
}
Spacer()
ScrollView{
ForEach(contactViewModel.items) { item in
contactWidget(name: item.name)
}
}
.padding(.top,20)
Button(action: {
print("touched")
}, label: {
NavigationLink(destination: AddContactView().navigationBarBackButtonHidden(true)) {
HStack{
ZStack{
RoundedRectangle(cornerRadius: 40)
.frame(width: 200, height: 50)
.foregroundColor(.blue)
Text("Add Contact")
.foregroundColor(.white)
}
}
}
.navigationBarHidden(true)
})
}
.background(.black)
}
.navigationBarHidden(true)
}
}
struct contactWidget : View{
let name: String
var body: some View{
ZStack {
RoundedRectangle(cornerRadius: 20)
.frame(width: 350, height: 100)
.foregroundColor(.gray)
HStack {
Image(systemName: "person")
.resizable()
.clipShape(Circle())
.frame(width: 40, height: 40)
Text(name)
.font(.system(size: 18, weight: .semibold))
Spacer()
HStack{
Circle()
.frame(width: 40, height: 40)
.foregroundColor(.orange)
Circle()
.frame(width: 40, height: 40)
.foregroundColor(.blue)
Circle()
.frame(width: 40, height: 40)
.foregroundColor(.pink)
}
}
.padding(.leading,40)
.padding(.trailing,30)
}
}
}
struct HomeView_Previews: PreviewProvider {
static var previews: some View {
NavigationView{
HomeView()
}
.environmentObject(ContactViewModel())
}
}
import SwiftUI
struct AddContactView: View {
@EnvironmentObject var contactViewModel: ContactViewModel
@State var contactName: String = ""
@State var phoneNumber: String = ""
@State var email: String = ""
var body: some View {
NavigationView {
VStack {
HStack{
Text("Contacts")
.font(.system(size: 35, weight: .bold))
.padding(.leading,30)
.padding(.top,20)
.foregroundColor(.white)
Spacer()
}
TextField("Enter name", text: $contactName)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
TextField("Enter Phone Number", text: $phoneNumber)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
TextField("Enter Email", text: $email)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
Text(contactName)
.foregroundColor(.white)
Spacer()
.padding(.top,20)
Button(action: {
contactViewModel.addItem(name: contactName, phoneNumber: phoneNumber, email: email)
contactName = ""
phoneNumber = ""
email = ""
}, label: {
NavigationLink(destination: HomeView().navigationBarBackButtonHidden(true)) {
HStack{
ZStack{
RoundedRectangle(cornerRadius: 40)
.frame(width: 200, height: 50)
.foregroundColor(.blue)
Text("Done")
.foregroundColor(.white)
}
}
}
.navigationBarHidden(true)
})
}
.background(.black)
}
.navigationBarHidden(true)
}
}
struct AddContactView_Previews: PreviewProvider {
static var previews: some View {
NavigationView{
AddContactView()
}
.environmentObject(ContactViewModel())
}
}
“...HomeView 不显示联系人姓名...”的原因是
因为 AddContactView
中的按钮标签内有 NavigationLink(destination: HomeView()....
。也就是说,点击被 NavigationLink
并在不执行按钮操作的情况下转到 HomeView
添加联系人, contactViewModel.addItem( ...)
。所以重组你的代码
NavigationLink
在它之外。
下面的示例代码应该可以解决您的问题。
struct AddContactView: View {
@EnvironmentObject var contactViewModel: ContactViewModel
@State var contactName: String = ""
@State var phoneNumber: String = ""
@State var email: String = ""
@State var goHome = false // <-- here
var body: some View {
NavigationView {
VStack {
HStack{
Text("Contacts")
.font(.system(size: 35, weight: .bold))
.padding(.leading,30)
.padding(.top,20)
.foregroundColor(.white)
Spacer()
}
TextField("Enter name", text: $contactName)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
TextField("Enter Phone Number", text: $phoneNumber)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
TextField("Enter Email", text: $email)
.frame(width: 330, height: 30)
.padding()
.background(.white)
.cornerRadius(10)
Text(contactName).foregroundColor(.white)
Spacer().padding(.top,20)
Button(action: {
contactViewModel.addItem(name: contactName, phoneNumber: phoneNumber, email: email)
contactName = ""
phoneNumber = ""
email = ""
goHome = true // <-- here
}, label: {
HStack{
ZStack{
RoundedRectangle(cornerRadius: 40)
.frame(width: 200, height: 50)
.foregroundColor(.blue)
Text("Done")
.foregroundColor(.white)
}
}
})
// -- here
NavigationLink(destination: HomeView().navigationBarBackButtonHidden(true), isActive: $goHome) {
EmptyView()
}.navigationBarHidden(true)
}
.background(.black)
}
.navigationBarHidden(true)
}
}
类似HomeView
中的按钮,或者去掉Button
部分,只保留NavigationLink