- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个简单的程序,可以让我监控 iOS 应用程序中的一些销售情况。基本上,我需要一种允许客户(作为字符串)的数据结构,并且对于每个客户,我需要能够保存一个或多个“销售”,每个销售由销售日期和价格组成。我将其实现为一个 Swift 字典,它在单例 Swift 类中读取和保存到 plist 文件,因为我需要从多个 View Controller 读取和写入相同的数据结构。这是数据类的代码:
import Foundation
import UIKit
class DataSingleton {
static let sharedDataSingleton = DataSingleton()
private(set) var allData = [String: [AnyObject]]()
private(set) var customers: [String] = []
init() {
let fileURL = self.dataFileURL()
if (NSFileManager.defaultManager().fileExistsAtPath(fileURL.path!)) {
allData = NSDictionary(contentsOfURL: fileURL) as! [String : [AnyObject]]
customers = allData.keys.sort()
}
}
func dataFileURL() -> NSURL {
let url = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
return url.first!.URLByAppendingPathComponent("data.plist")
}
func addCustomer(customerName: String) {
if !customers.contains(customerName) {
customers.append(customerName)
allData[customerName] = [[NSDate(), 0]]
saveData()
}
}
func addSale(customerName: String, date: NSDate, price: Int) {
allData[customerName]?.append([date, price])
saveData()
}
func saveData() {
let fileURL = self.dataFileURL()
let customerData = allData as NSDictionary
customerData.writeToURL(fileURL, atomically: true)
}
}
正如你所看到的,我使用了一个字典,其中客户名称是键,销售额是 AnyObject 的数组。我怀疑这是否是实现此目的的最佳和最优雅的方式,所以也许有人可以帮助我解决以下问题:
什么是更好的实现方法?将 sales 实现为一个结构体,然后使用该结构体的数组是否有意义?
创建新客户时,我需要使用占位符
allData[customerName] = [[NSDate(), 0]]
因为没有值的字典键不会被保存。有更好的方法吗?
为什么 allData.keys.sort()
会生成字符串数组,而 allData.keys
不会?这对我来说没有意义,因为排序函数似乎不应该更改类型。
在我的(表) View 中,每个单元格显示一个客户以及每个客户的总销售额。我想按销售总额对该表进行排序。当前代码(参见 3.)按字母顺序对客户进行排序。实现此目的的最佳方法是什么:按数据结构本身或 View Controller 中的总销售额对客户进行排序?有人可以提供代码如何最优雅地实现这种排序,也许使用排序函数和闭包?
最佳答案
看看您的代码编辑,看看它是否适合您的目的:
import Foundation
/// Allows any object to be converted into and from a NSDictionary
///
/// With thanks to [SonoPlot](https://github.com/SonoPlot/PropertyListSwiftPlayground)
protocol PropertyListReadable {
/// Converts to a NSDictionary
func propertyListRepresentation() -> NSDictionary
/// Initializes from a NSDictionary
init?(propertyListRepresentation:NSDictionary?)
}
/// Converts a plist array to a PropertyListReadable object
func extractValuesFromPropertyListArray<T:PropertyListReadable>(propertyListArray:[AnyObject]?) -> [T] {
guard let encodedArray = propertyListArray else {return []}
return encodedArray.map{$0 as? NSDictionary}.flatMap{T(propertyListRepresentation:$0)}
}
/// Saves a PropertyListReadable object to a URL
func saveObject(object:PropertyListReadable, URL:NSURL) {
if let path = URL.path {
let encoded = object.propertyListRepresentation()
encoded.writeToFile(path, atomically: true)
}
}
/// Holds the information for a sale
struct Sale {
let date:NSDate
let price:Int
}
/// Allows a Sale to be converted to and from an NSDictionary
extension Sale: PropertyListReadable {
/// Convert class to an NSDictionary
func propertyListRepresentation() -> NSDictionary {
let representation:[String:AnyObject] = ["date":self.date, "price":self.price]
return representation
}
/// Initialize class from an NSDictionary
init?(propertyListRepresentation:NSDictionary?) {
guard let values = propertyListRepresentation,
date = values["date"] as? NSDate,
price = values["price"] as? Int else { return nil }
self.init(date:date, price:price)
}
}
/// Singleton that holds all the sale Data
final class DataSingleton {
/// Class variable that returns the singleton
static let sharedDataSingleton = DataSingleton(dataFileURL: dataFileURL)
/// Computed property to get the URL for the data file
static var dataFileURL:NSURL? {
get {
let manager = NSFileManager.defaultManager()
guard let URL = manager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first?.URLByAppendingPathComponent("data.plist"),
path = URL.path else { return nil }
let data = NSKeyedArchiver.archivedDataWithRootObject([String:AnyObject]())
guard manager.fileExistsAtPath(path) &&
manager.createFileAtPath(path, contents: data, attributes: nil) else { return nil }
return URL
}
}
/// The dictionary holding all the sale data
private(set) var allData:[String: [Sale]]
/// Computed property to return all the customers
var customers:[String] { get { return Array(allData.keys) }}
/// Designated initializer
///
/// Made private to disallow additional copies of the singleton
private init() { allData = [:] }
/// Adds a customer to the data dictionary
func addCustomer(customerName: String) {
if allData[customerName] == nil {
allData[customerName] = []
saveData()
}
}
/// Adds a sale to the data dictionary, creating a new customer if neccesary
func addSale(customerName: String, date: NSDate, price: Int) {
addCustomer(customerName)
allData[customerName]?.append(Sale(date: date, price: price))
saveData()
}
// Saves the singleton to the plist file
private func saveData() {
if let fileURL = DataSingleton.dataFileURL {
saveObject(self, URL: fileURL)
}
}
}
/// Allows a DataSingleton to be converted to and from an NSDictionary
extension DataSingleton: PropertyListReadable {
/// Convert class to an NSDictionary
func propertyListRepresentation() -> NSDictionary {
return allData.reduce([String:[AnyObject]]()) {
var retval = $0
retval[$1.0] = $1.1.map {$0.propertyListRepresentation()}
return retval
}
}
/// Initialize class from a plist file
///
/// Made private to disallow additional copies of the singleton
private convenience init?(dataFileURL: NSURL?) {
guard let fileURL = dataFileURL,
path = fileURL.path where (NSFileManager.defaultManager().fileExistsAtPath(path)),
let data = NSDictionary(contentsOfFile: path) else { return nil }
self.init(propertyListRepresentation: data)
}
/// Initialize class from an NSDictionary
convenience init?(propertyListRepresentation:NSDictionary?) {
self.init() // satisfies calling the designated init from a convenience init
guard let values = propertyListRepresentation else {return nil}
allData = values.reduce([:]) {
var retvalue = $0
guard let key = $1.key as? String,
value = $1.value as? [AnyObject] else { return retvalue }
retvalue[key] = extractValuesFromPropertyListArray(value)
return retvalue
}
}
}
用法:
let data = DataSingleton.sharedDataSingleton
data?.addSale("June", date: NSDate(), price: 20)
data?.addSale("June", date: NSDate(), price: 30)
let data2 = DataSingleton.sharedDataSingleton
print(data2?.allData["June"])
// => Optional([Sale(date: 2016-03-10 04:31:49 +0000, price: 20), Sale(date: 2016-03-10 04:31:49 +0000, price: 30)])
要回答 3,您应该注意 allData.keys
的返回值。这是一个惰性集合,在您请求之前不会提取值。调用sort
它会提取所有值,因为没有它们就无法排序。因此,它返回一个常规的、非惰性的 Array
。您无需使用 sort
即可获得非惰性数组通过这样做:Array(allData.keys)
评论中您的其他问题:
1:希望能修复,我从 NSCoding
切换过来了因为它依赖于 NSObject
和NSData
。这意味着我们不能使用 struct
以其非常理想的value semantics等问题。
2:通过扩展添加功能是个好主意。这允许您保持代码划分,例如我添加了对 protocol
的合规性PropertyListReadable
在 extension
然后在那里添加必要的方法。
3:在此代码中allData
初始化于 init?(propertyListRepresentation:)
。那里有一个NSDictionary
被读取,每个客户及其销售额被解析为正确的数据结构。自从我改变Sale
来自class
到 struct
(感谢新的 protocol
PropertyListReadable
)我们可以声明它保存的变量和 init
方法是自动为我们生成的 init(date:NSDate, price:Int)
一个struct
喜欢 Sale
比 Dictionary
更好由于类型检查、自动完成、能够更好地注释 struct
并自动生成文档、验证值的可能性、添加附加功能的协议(protocol)等等。很难确切地知道旧的是什么 Dictionary
代表它何时被埋藏在代码中并具有具体的 struct
, enum
,或class
让您的生活变得更加轻松。
一个Dictionary
非常适合将键映射到值,但是当您想要将多个相互依赖的值保存在一起时,您需要查看 enum
, struct
或class
.
关于arrays - Swift 数组字典、数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35850308/
初学者 android 问题。好的,我已经成功写入文件。例如。 //获取文件名 String filename = getResources().getString(R.string.filename
我已经将相同的图像保存到/data/data/mypackage/img/中,现在我想显示这个全屏,我曾尝试使用 ACTION_VIEW 来显示 android 标准程序,但它不是从/data/dat
我正在使用Xcode 9,Swift 4。 我正在尝试使用以下代码从URL在ImageView中显示图像: func getImageFromUrl(sourceUrl: String) -> UII
我的 Ubuntu 安装 genymotion 有问题。主要是我无法调试我的数据库,因为通过 eclipse 中的 DBMS 和 shell 中的 adb 我无法查看/data/文件夹的内容。没有显示
我正在尝试用 PHP 发布一些 JSON 数据。但是出了点问题。 这是我的 html -- {% for x in sets %}
我观察到两种方法的结果不同。为什么是这样?我知道 lm 上发生了什么,但无法弄清楚 tslm 上发生了什么。 > library(forecast) > set.seed(2) > tts lm(t
我不确定为什么会这样!我有一个由 spring data elasticsearch 和 spring data jpa 使用的类,但是当我尝试运行我的应用程序时出现错误。 Error creatin
在 this vega 图表,如果我下载并转换 flare-dependencies.json使用以下 jq 到 csv命令, jq -r '(map(keys) | add | unique) as
我正在提交一个项目,我必须在其中创建一个带有表的 mysql 数据库。一切都在我这边进行,所以我只想检查如何将我所有的压缩文件发送给使用不同计算机的人。基本上,我如何为另一台计算机创建我的数据库文件,
我有一个应用程序可以将文本文件写入内部存储。我想仔细看看我的电脑。 我运行了 Toast.makeText 来显示路径,它说:/数据/数据/我的包 但是当我转到 Android Studio 的 An
我喜欢使用 Genymotion 模拟器以如此出色的速度加载 Android。它有非常好的速度,但仍然有一些不稳定的性能。 如何从 Eclipse 中的文件资源管理器访问 Genymotion 模拟器
我需要更改 Silverlight 中文本框的格式。数据通过 MVVM 绑定(bind)。 例如,有一个 int 属性,我将 1 添加到 setter 中的值并调用 OnPropertyChanged
我想向 Youtube Data API 提出请求,但我不需要访问任何用户信息。我只想浏览公共(public)视频并根据搜索词显示视频。 我可以在未经授权的情况下这样做吗? 最佳答案 YouTube
我已经设置了一个 Twilio 应用程序,我想向人们发送更新,但我不想回复单个文本。我只是想让他们在有问题时打电话。我一切正常,但我想在发送文本时显示传入文本,以确保我不会错过任何问题。我正在使用 p
我有一个带有表单的网站(目前它是纯 HTML,但我们正在切换到 JQuery)。流程是这样的: 接受用户的输入 --- 5 个整数 通过 REST 调用网络服务 在服务器端运行一些计算...并生成一个
假设我们有一个名为 configuration.js 的文件,当我们查看内部时,我们会看到: 'use strict'; var profile = { "project": "%Projec
这部分是对 Previous Question 的扩展我的: 我现在可以从我的 CI Controller 成功返回 JSON 数据,它返回: {"results":[{"id":"1","Sourc
有什么有效的方法可以删除 ios 中 CBL 的所有文档存储?我对此有疑问,或者,如果有人知道如何从本质上使该应用程序像刚刚安装一样,那也会非常有帮助。我们正在努力确保我们的注销实际上将应用程序设置为
我有一个 Rails 应用程序,它与其他 Rails 应用程序通信以进行数据插入。我使用 jQuery $.post 方法进行数据插入。对于插入,我的其他 Rails 应用程序显示 200 OK。但在
我正在为服务于发布请求的 API 调用运行单元测试。我正在传递请求正文,并且必须将响应作为帐户数据返回。但我只收到断言错误 注意:数据是从 Azure 中获取的 spec.js const accou
我是一名优秀的程序员,十分优秀!