【问题标题】:iOS architecture: Object with many optionalsiOS 架构:具有许多选项的对象
【发布时间】:2018-11-05 10:01:56
【问题描述】:

这是一个相当具体的情况,所以我会尝试解释尽可能多的细节。

我正在制作一个应该获取预订列表的应用程序,可以在其中添加新预订,或点击现有预订并获得有关预订详细信息可编辑的预订的“详细”视图,然后保存它的选项。

REST API 已经在 C# 中完成,并且没有关于什么可以和不能为 null 的文档(nil,在 Swift 的情况下)。所以我最终得到:

    struct Reservation: Codable {
var objectID: String?
var objectName: String?
var objectPrefix: String?
var reservationNumber: String?
var grownUPS: Int?
var teens: Int?
var children: Int?
var babies: Int?
var reservationDate: String?
var dateInserted: String?
var toDate:String?
var fromDate: String?
var price: Int?
var owner: String?
var note: String?
var agencyName: String?
var renterNote: String?
var reservationID: String?
    // 20 more properties

init(objectID: String? = nil,
         partnerID: String? = nil,
         objectName: String? = nil,
    // 20 more properties        
    )
    {

    self.objectID = objectID
    self.objectName = objectName
 // 20 more properties

}

所以当我点击一个对象时,我传递了一个 Reservation 对象,检查每个字段,如果不是 nil 则设置为 TextField。点击保存后,我会从所有 TextField、DatePickers 等中更新模型,然后根据是新的预订还是现有的编辑进行网络发布或提出请求。

如果我点击添加,我会传递一个空的 Reservation 对象,因此“详细信息”页面上的所有字段都是空的,并在单击“保存”按钮时进行验证。

到目前为止它可以工作,但它周围看起来“反 Swift”。很多选项,很多守卫/展开,“master”和“details”视图之间的紧密耦合,在闭包中设置从网络检索的数据(实际的 Alamofire 调用是隐藏的,但我不确定什么会是 nil,所以我必须使用 nil-check/chaining 将每个属性设置为它的 TextField)。

关于如何改进这一点的任何架构技巧? 所有关于这方面的教程都是一种简单的、本地的、非可选的方法,让一切看起来都很闪亮。

请记住,我没有任何文档可以为 null(之前通过 Web 或内部桌面应用程序输入的数据)。

【问题讨论】:

  • 你试过在结构中给一个初始值,你能做到吗?

标签: ios swift model-view-controller master-detail


【解决方案1】:

我能想到的一件事是通过定义默认值来删除某些属性的可选性,例如var babies: Int = 0,或者如果您使用的是 Swift 的可解码器,您可以执行类似的操作

babies = (try? container.decode(Int.self, forKey: .babies)) ?? 0

因此您不必将 babies 变量设为可选

根据评论编辑: ?? aka coalescing nil 运算符将尝试解开左侧的可选值,如果它是 nil,它将返回右侧的值,在这种情况下为 0

【讨论】:

  • 如果他不能给出默认值怎么办?,你也能解释一下'??'为他声明更多,他如何检查如果。值不是来自服务器,考虑到服务器可能会给他 0 结果,他如何检查它以放置一个空的文本字段等。
  • 它确实会解决选项问题,但它可能会导致另一个问题,当他需要检查每个选项的实际值以在他的 UI 中实现它时,在你的情况下,婴儿可能是 0,但是如果实际响应是 0 并且他需要实现并向用户表明他有 0 个婴儿,如果它是 nil,他必须删除婴儿字段!
  • 这是可能的,但我试图避免它,因为其他应用程序可能会像婴儿一样检查!= null {做某事},如果我在那里编辑并保存 0,它可能会搞乱逻辑其他应用。编辑:正是托比所说的。
  • @Tobi 对于那些特殊情况,他当然可以将其保留为可选。但是上面的建议对于大多数情况都会很方便。
  • 但他说他无法判断它是否会为零或根本没有提供任何文件
【解决方案2】:

我认为您不应该为可选项和可选项展开而烦恼。

optionals 的强大功能之一是,任何使用您的代码的人都知道,这个东西可能会将nil 作为它的值

展开逻辑,您使用 guardsnil 合并或任何其他展开技术来描述您的业务逻辑。事实上,你有“大”模型是,IMO,只是一个应该被接受的事实。在您的代码保持可靠、可读、可测试和可理解,不会造成不必要的副作用等之前,一切正常。

您可以通过在展开等方面添加另一个抽象级别来“解决”这个问题。但是,IMO,应该非常小心地进行,并且只针对真正的好处

【讨论】:

  • 我会说它会影响可读性和可靠性,我的 ViewController 中有很多这样的代码。 ` ReservationService().getOc​​cupations(objectID: self.reservation.objectDC ?? "", dateFrom: self.reservation.fromDate ?? "", dateTo: self.reservation.toDate ?? "", reservationId: self.reservation.reservationID ?? "") { 中的响应 letoccupModel = response.first self.AvailabilityLabel.text =occupationModel.occupationStatusDescription } `
  • @ZN123 我认为至少可以通过这样的更改来改进它:let objId = reservation.objectDC ?? "" 让 dateFrom = reservation.fromDate ?? "" ... ReservationService().getOc​​cupations(objectID: objId, dateFrom: dateFrom, ...) 或者通过更改ReservationService().getOccupations 方法签名以接受一个结构作为参数。有多种方法可以提高可读性,而无需任何外部或难以获得的工具。
  • @ZN123 现在可能是引入ViewModels 的合适时机,它将处理所有解包以及将API 请求置于ViewController 之外。
  • @ZN123 让您的生活更轻松的小扩展,extension Optional where Wrapped == String { /// Abbreviation for Unwrapped /// Starts with u, ends with d and 7 letters in between. public var u7d: String { return self ?? "" } }
  • 用法:let hello: String? = "Hello" print(hello.u7d)
【解决方案3】:

SwiftyJson 正好解决您所面临的问题。它非常有效地以一种非常 Swifty 的方式处理大量对象的可选链接和展开。

如果某些类型转换失败,它不会中断,但会给出一个空值,这样您的应用就可以在不检查每个变量的情况下运行。

这是提供的基本转换示例。有关详细信息,请查看他们的文档。

// Getting a double from a JSON Array
let name = json[0].double

// Getting an array of string from a JSON Array
let arrayNames =  json["users"].arrayValue.map({$0["name"].stringValue})

// Getting a string from a JSON Dictionary
let name = json["name"].stringValue

// Getting a string using a path to the element
let path: [JSONSubscriptType] = [1,"list",2,"name"]
let name = json[path].string

// Just the same
let name = json[1]["list"][2]["name"].string

// Alternatively
let name = json[1,"list",2,"name"].string

【讨论】:

  • 是吗?你能举例说明我的模型会是什么样子吗?
猜你喜欢
  • 1970-01-01
  • 2021-03-12
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 2012-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多