Swift:在 UITabView 之间传递数据并允许全局访问数据
Swift: Passing Data Between UITabViews & Allowing Global Access to Data
首先,让我解释一下我的应用程序及其流程。应用程序打开,用户创建配置文件(将所有数据存储在 [String: Any]
类型的字典中)。用户单击创建后,它将它们发送到控制台屏幕(显示用户输入的部分信息,例如通过 segue
显示他们的姓名)。有一个选项卡可以让他们编辑他们的个人资料(姓名、体重、地址等)。当用户编辑他们的信息(更改他们的姓名、体重等)时,它也应该更新控制台页面上显示的信息。
我的主要问题是,如何构造它以便数据对所有选项卡视图普遍可用。更具体地说,数据不是实例或数据的副本。我创建了一个名为 Person
的 class,其中存储了所有变量(firstName
、lastName
等)。我已经尝试在 UIViewController
class 声明之前将 person class 的实例声明为变量,但它不允许我使用 UITextField
.text
属性(因为它们还没有被创建...?)。
这是我的人class...
class Person {
var firstName: String
var lastName: String
var phoneNumber: String
var weight: Int
var gender: String
var streetAddress: String
var cityState: String
init(firstName: String, lastName: String, phoneNumber: String, weight: Int, gender: String, streetAddress: String, cityState: String) {
self.firstName = firstName
self.lastName = lastName
self.phoneNumber = phoneNumber
self.weight = weight
self.gender = gender
self.streetAddress = streetAddress
self.cityState = cityState
}
}
我也将 UITabBarController
子class编辑为 TabBarViewController
因为我读到你可以将数据发送到那个子classed viewController
并使其对所有嵌入的选项卡普遍可用。我只是不知道它是如何工作的。
很抱歉可能会问一个重复的问题...我有 look/researched 这个问题,但我还没有找到适合我的特定情况的解决方案。
更新代码以将数据保存为 CoreData
...
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let userInfo = PInfo(firstName: firstNameField.text, lastName: lastNameField.text, cityState: cityStateField.text, streetAddress: streetAddressField.text, gender: genderInputField.text, userWeight: 200)
save(withPersonInfo: userInfo, withContext: managedContext)
我能够访问各种 viewControllers
中的数据,但它会将其作为单个项目数组返回给我...理想情况下,我希望将它们作为 key:value
对,这样我就可以轻松地将它们设置为在 Edit Profile
viewController
.
中显示和编辑
谢谢!
一个解决方案是Delegates
。您获取数据的 class 将设置您的委托,以及希望获得该委托的任何其他人订阅该委托。
事实上:我认为使用 Delegate + CoreData
可能会让您免于麻烦;收听数据然后保存该数据。现在您的其他控制器将针对该用户场景进行快速获取(核心数据是如此之快,伙计:))
一些代码:
class PersonDetail: NSManagedObject { // this is how your coreData's Entity should look like
@NSManaged public var firstname: String?
@NSManaged public var lastname: String?
// add the other fields, such as weight
@nonobjc public class func fetchRequest() -> NSFetchRequest<PersonDetail> {
return NSFetchRequest<PersonDetail>(entityName: "PersonDetail")
}
}
// This struct would to get the data from the user
struct PInfo {
var firstname:String?
var lastname:String?
}
// this function would get an instance of that PInfo
// for example var p = PInfo(firstname:"Stack",lastname:"Overflow")
func save(withPersonInfo p:PInfo, withContext context:NSManagedObjectContext) {
let entityDescription = NSEntityDescription.entity(forEntityName: "PersonDetail", in: context)
let managedObject = NSManagedObject(entity: entityDescription!, insertInto: context) as! PersonDetail
// this is where I am passing data into the entity
managedObject.firstname = p.firstname
managedObject.lastname = p.lastname
try? context.save() // use the proper do {} catch, I was saving time lol :)
}
// when you fetch from coreData you have an instance of PInfo
func fetchSingleUser(withContext context:NSManagedObjectContext) -> PInfo {
let request:NSFetchRequest<PersonDetail> = PersonDetail.fetchRequest()
let coreData_items = try? context.fetch(request)
guard let items = coreData_items,
let firstItem = items.first // since we only have one user
else { fatalError("Error while querying") }
return PInfo(firstname: firstItem.firstname, lastname:firstItem.lastname)
}
一个非常简单的解决方案是为您的应用委托一个 person
属性 初始化为一个空的 Person。这解决了问题,因为 every class 可以访问 属性:
let p = (UIApplication.shared.delegate as! AppDelegate).person
此外,p
通过引用获取此 Person,因此对其属性的任何更改都会反映回 person
属性 本身,以供查看(和变异)下一个视图控制器。
一个更复杂、更令人满意的解决方案,因为只有 一个 用户要配置,将让 Person class 本身分配一个 shared
person 实例作为单例。 (在 SO 上搜索以了解如何在 Swift 中实现单例。)同样,该单例将普遍可用:
let p = Person.shared()
首先,让我解释一下我的应用程序及其流程。应用程序打开,用户创建配置文件(将所有数据存储在 [String: Any]
类型的字典中)。用户单击创建后,它将它们发送到控制台屏幕(显示用户输入的部分信息,例如通过 segue
显示他们的姓名)。有一个选项卡可以让他们编辑他们的个人资料(姓名、体重、地址等)。当用户编辑他们的信息(更改他们的姓名、体重等)时,它也应该更新控制台页面上显示的信息。
我的主要问题是,如何构造它以便数据对所有选项卡视图普遍可用。更具体地说,数据不是实例或数据的副本。我创建了一个名为 Person
的 class,其中存储了所有变量(firstName
、lastName
等)。我已经尝试在 UIViewController
class 声明之前将 person class 的实例声明为变量,但它不允许我使用 UITextField
.text
属性(因为它们还没有被创建...?)。
这是我的人class...
class Person {
var firstName: String
var lastName: String
var phoneNumber: String
var weight: Int
var gender: String
var streetAddress: String
var cityState: String
init(firstName: String, lastName: String, phoneNumber: String, weight: Int, gender: String, streetAddress: String, cityState: String) {
self.firstName = firstName
self.lastName = lastName
self.phoneNumber = phoneNumber
self.weight = weight
self.gender = gender
self.streetAddress = streetAddress
self.cityState = cityState
}
}
我也将 UITabBarController
子class编辑为 TabBarViewController
因为我读到你可以将数据发送到那个子classed viewController
并使其对所有嵌入的选项卡普遍可用。我只是不知道它是如何工作的。
很抱歉可能会问一个重复的问题...我有 look/researched 这个问题,但我还没有找到适合我的特定情况的解决方案。
更新代码以将数据保存为 CoreData
...
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let userInfo = PInfo(firstName: firstNameField.text, lastName: lastNameField.text, cityState: cityStateField.text, streetAddress: streetAddressField.text, gender: genderInputField.text, userWeight: 200)
save(withPersonInfo: userInfo, withContext: managedContext)
我能够访问各种 viewControllers
中的数据,但它会将其作为单个项目数组返回给我...理想情况下,我希望将它们作为 key:value
对,这样我就可以轻松地将它们设置为在 Edit Profile
viewController
.
谢谢!
一个解决方案是Delegates
。您获取数据的 class 将设置您的委托,以及希望获得该委托的任何其他人订阅该委托。
事实上:我认为使用 Delegate + CoreData
可能会让您免于麻烦;收听数据然后保存该数据。现在您的其他控制器将针对该用户场景进行快速获取(核心数据是如此之快,伙计:))
一些代码:
class PersonDetail: NSManagedObject { // this is how your coreData's Entity should look like
@NSManaged public var firstname: String?
@NSManaged public var lastname: String?
// add the other fields, such as weight
@nonobjc public class func fetchRequest() -> NSFetchRequest<PersonDetail> {
return NSFetchRequest<PersonDetail>(entityName: "PersonDetail")
}
}
// This struct would to get the data from the user
struct PInfo {
var firstname:String?
var lastname:String?
}
// this function would get an instance of that PInfo
// for example var p = PInfo(firstname:"Stack",lastname:"Overflow")
func save(withPersonInfo p:PInfo, withContext context:NSManagedObjectContext) {
let entityDescription = NSEntityDescription.entity(forEntityName: "PersonDetail", in: context)
let managedObject = NSManagedObject(entity: entityDescription!, insertInto: context) as! PersonDetail
// this is where I am passing data into the entity
managedObject.firstname = p.firstname
managedObject.lastname = p.lastname
try? context.save() // use the proper do {} catch, I was saving time lol :)
}
// when you fetch from coreData you have an instance of PInfo
func fetchSingleUser(withContext context:NSManagedObjectContext) -> PInfo {
let request:NSFetchRequest<PersonDetail> = PersonDetail.fetchRequest()
let coreData_items = try? context.fetch(request)
guard let items = coreData_items,
let firstItem = items.first // since we only have one user
else { fatalError("Error while querying") }
return PInfo(firstname: firstItem.firstname, lastname:firstItem.lastname)
}
一个非常简单的解决方案是为您的应用委托一个 person
属性 初始化为一个空的 Person。这解决了问题,因为 every class 可以访问 属性:
let p = (UIApplication.shared.delegate as! AppDelegate).person
此外,p
通过引用获取此 Person,因此对其属性的任何更改都会反映回 person
属性 本身,以供查看(和变异)下一个视图控制器。
一个更复杂、更令人满意的解决方案,因为只有 一个 用户要配置,将让 Person class 本身分配一个 shared
person 实例作为单例。 (在 SO 上搜索以了解如何在 Swift 中实现单例。)同样,该单例将普遍可用:
let p = Person.shared()