如果我创建一个没有的swift结构init,那么我可以调用编译器生成的默认成员初始化器,如下所示:
struct OrderFill {
let price:Int
let qty: Int
let timeStamp: NSDate
}
let o = OrderFill(price: 2, qty: 1, timeStamp: someDate)
Run Code Online (Sandbox Code Playgroud)
我想要做的是创建一个方便的init方法来从字典反序列化,然后字典链接到默认的成员init.就像是
struct OrderFill {
let price:Int
let qty: Int
let timeStamp: NSDate
init(dict:[String:AnyObject]) throws {
self.init(
price: dict["price"] as! Int
qty: dict["qty"] as! Int
timeStamp: try parseDate(dict["ts"] as! String)
}
}
let o = OrderFill(someDict)
Run Code Online (Sandbox Code Playgroud)
当我尝试编写这段代码时,编译器(Xcode 7.2)在调用中给出了错误"额外参数'数量',好像它没有看到默认的成员并试图递归调用 init(dictionary)
我可以编写自己的成员init,或者我可以直接从我的分配属性init(dictionary),但如果我可以链接调用它会很好.有没有办法在swift中做到这一点?
考虑以下:
struct SomeStruct {}
var foo: Any!
let bar: SomeStruct = SomeStruct()
foo = bar // Compiles as expected
var fooArray: [Any] = []
let barArray: [SomeStruct] = []
fooArray = barArray // Does not compile; Cannot assign value of type '[SomeStruct]' to type '[Any]'
Run Code Online (Sandbox Code Playgroud)
我一直试图找到这背后的逻辑,但没有运气.值得一提的是,如果将结构更改为类,则可以完美地运行.
总是可以添加一个变通方法并映射fooArray的每个对象并将它们转换为Any类型,但这不是问题.我正在寻找一个解释为什么这样做的样子.
有人可以解释一下吗?
我有一个类(A),它有一个struct变量(S).在这个类的一个函数中,我在struct变量上调用一个mutating函数,这个函数需要一个闭包.此闭包的主体检查struct变量的name属性.
结构的变异函数依次调用某个类(B)的函数.这个类的函数再次关闭.在这个闭包的主体中改变结构,即更改name属性,并调用第一个类提供的闭包.
当我们检查struct的name属性时调用第一个类(A)闭包时,它永远不会被更改.
但是在第2步中,如果我使用结构(C)而不是类B,我会看到内部类A的闭包结构实际上已经改变了.以下是代码:
class NetworkingClass {
func fetchDataOverNetwork(completion:()->()) {
// Fetch Data from netwrok and finally call the closure
completion()
}
}
struct NetworkingStruct {
func fetchDataOverNetwork(completion:()->()) {
// Fetch Data from netwrok and finally call the closure
completion()
}
}
struct ViewModelStruct {
/// Initial value
var data: String = "A"
/// Mutate itself in a closure called from a struct
mutating func changeFromStruct(completion:()->()) {
let networkingStruct = NetworkingStruct()
networkingStruct.fetchDataOverNetwork {
self.data = "B"
completion()
}
} …Run Code Online (Sandbox Code Playgroud) 我在 Swift 中创建了一个“锁”,并为我的 Swift 类创建了一个使用该锁的 Atomic 属性包装器,因为 Swift 缺少 ObjC 的atomic属性属性。
当我在启用线程清理器的情况下运行我的测试时,它总是捕获使用我的 Atomic 属性包装器的属性上的数据竞争。
唯一有效的是将属性包装器的声明更改为一个类而不是一个结构体,这里的主要问题是:为什么它有效!
我print在属性包装器中添加了s 并添加了 lockinit来跟踪创建的对象数量,它与 struct/class 相同,尝试在另一个项目中重现该问题,但也没有用。但是我会添加与问题类似的文件,并让我知道它为什么起作用的任何猜测。
锁
public class SwiftLock {
init() { }
public func sync<R>(execute: () throws -> R) rethrows -> R {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
return try execute()
}
}
Run Code Online (Sandbox Code Playgroud)
原子属性包装器
@propertyWrapper struct Atomic<Value> {
let lock: SwiftLock
var value: Value
init(wrappedValue: Value, lock: SwiftLock=SwiftLock()) {
self.value = wrappedValue
self.lock = …Run Code Online (Sandbox Code Playgroud) 我很清楚Swift中值类型和引用类型之间的区别,并且意识到值类型被设计为不可变的用法.但结构特别有能力改变自己,这是我的担忧.如何有效地使用这些变异的struct值类型,以便它们保持其状态或变化.
我的问题是,在iOS应用程序的MVVM设计中应该将模型视为类还是结构?由于视图模型包含模型/模型列表,并且这些模型实例可以随时间变化(例如,视图模型从Web服务请求获取更多模型实例并添加到其模型数组中),视图控制器的视图模型如何更新这种变化.这是一个伪示例,但首先是一些注意事项和简要说明:
例:
查看型号:
struct DummyViewModel {
private var ints:[Int] = []
var count: Int {
return ints.count
}
init() {}
mutating func fetchData(completionHandler:(NSError? ) -> Void) {
Networking.getDataFromRemote() { response in
self.ints.append(1)
completionHandler(nil)
}
}
}
Run Code Online (Sandbox Code Playgroud)
查看控制器:
class DummyViewController: UIViewController{
private var dummyViewModel: DummyViewModel?
override func viewDidLoad() {
super.viewDidLoad()
/// Setup the view model
dummyViewModel = DummyViewModel()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
loadData()
}
} …Run Code Online (Sandbox Code Playgroud) 我正在使用Swift 4并尝试解析一些JSON数据,这些数据显然在某些情况下可以为同一个键具有不同的类型值,例如:
{
"type": 0.0
}
Run Code Online (Sandbox Code Playgroud)
和
{
"type": "12.44591406"
}
Run Code Online (Sandbox Code Playgroud)
我实际上坚持定义我,struct因为我无法弄清楚如何处理这种情况,因为
struct ItemRaw: Codable {
let parentType: String
enum CodingKeys: String, CodingKey {
case parentType = "type"
}
}
Run Code Online (Sandbox Code Playgroud)
投掷"Expected to decode String but found a number instead.",当然,
struct ItemRaw: Codable {
let parentType: Float
enum CodingKeys: String, CodingKey {
case parentType = "type"
}
}
Run Code Online (Sandbox Code Playgroud)
因此投掷"Expected to decode Float but found a string/data instead.".
在定义我的时候如何处理这个(和类似的)情况struct呢?
我正在尝试修改数组中的结构元素。我发现您可以通过按索引访问(迭代)结构来做到这一点,但如果您使用“for in”循环或 forEach{},则不能。
struct Person
{
var age = 0
var name = "James"
}
var personArray = [Person]()
personArray += [Person(), Person(), Person()]
personArray.forEach({$0.age = 10}) // error: "Cannot assign to property: '$0' is immutable"
for person in personArray {
person.age = 10 // error: "Cannot assign to property: 'person' is a 'let' constant"
}
for index in personArray.indices {
personArray[index].age = 10 // Ok
}
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下吗?
我喜欢swift中的值语义,但我担心变异函数的性能.假设我们有以下内容struct
struct Point {
var x = 0.0
mutating func add(_ t:Double){
x += t
}
}
Run Code Online (Sandbox Code Playgroud)
现在假设我们创建一个Point并将其变异为:
var p = Point()
p.add(1)
Run Code Online (Sandbox Code Playgroud)
现在内存中的现有结构变异,或者被struct替换为新的实例
self = Point(x:self.x+1)
Run Code Online (Sandbox Code Playgroud) 我喝了Swift中的struct / value koolaid。现在我有一个有趣的问题,我不知道该如何解决。我有一个结构是一个容器,例如
struct Foo {
var bars:[Bar]
}
Run Code Online (Sandbox Code Playgroud)
在对此进行编辑时,我会创建副本,以便保留撤消堆栈。到目前为止,一切都很好。就像显示的好教程一样。不过,我与此人一起使用了一些派生属性:
struct Foo {
var bars:[Bar]
var derivedValue:Int {
...
}
}
Run Code Online (Sandbox Code Playgroud)
在最近的分析中,我注意到a)计算派生Value的计算是一种昂贵/冗余的b)在各种用例中并不总是必须进行计算。
按照我经典的OOP方式,我会将其设置为记忆/惰性变量。基本上,在调用之前将其设置为零,对其进行一次计算并存储,然后在以后的调用中返回所述结果。由于我遵循的是“制作副本以进行编辑”模式,因此不变性不会被破坏。
但是我无法弄清楚如果是struct则如何应用这种模式。我可以做这个:
struct Foo {
var bars:[Bar]
lazy var derivedValue:Int = self.computeDerivation()
}
Run Code Online (Sandbox Code Playgroud)
它起作用,直到结构引用该值本身,例如
struct Foo {
var bars:[Bar]
lazy var derivedValue:Int = self.computeDerivation()
fun anotherDerivedComputation() {
return self.derivedValue / 2
}
}
Run Code Online (Sandbox Code Playgroud)
此时,编译器会抱怨,因为anotherDerivedComputation正在引起接收方的更改,因此需要进行标记mutating。使访问器被标记为变异只是感觉不对。但是对于咧嘴笑,我尝试了一下,但是这带来了一系列新的问题。现在任何我有表达的地方
XCTAssertEqaul(foo.anotherDerivedComputation(), 20)
Run Code Online (Sandbox Code Playgroud)
编译器抱怨,因为参数隐式是一个不变的let值,而不是var。
我是否缺少一种具有延迟/惰性/缓存成员的结构的模式?
意图:
通过Coinmarketcap API接收加密货币价格数据,将其解码为 SWIFT 中的自定义结构,并可能将该数据存储在数据库(CoreData 或 SQLite)中。
语境:
我收到以下错误JSONDecoder().decode:
Error serializing json: typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "status", intValue: nil), _DictionaryCodingKey(stringValue: "credit_count", intValue: nil)], debugDescription: "Expected to decode Dictionary<String, Any> but found a number instead.", underlyingError: nil))
Run Code Online (Sandbox Code Playgroud)
问题:
编码:
import UIKit
import PlaygroundSupport
// Defining structures
struct RootObject: Decodable {
let status: [String: StatusObject?]
let data: DataObject?
}
struct StatusObject: Decodable {
let credit_count: Int?
let elapsed: Int?
let error_code: Int?
let timestamp: String? …Run Code Online (Sandbox Code Playgroud) swift ×10
swift-structs ×10
ios ×3
arrays ×2
json ×2
mvvm ×2
memoization ×1
mutable ×1
performance ×1
struct ×1
swift2.2 ×1
swift4 ×1
value-type ×1