Expected declaration when adding values to a Swift dictionary [duplicate] - swift

This question already has answers here:
swift compiler shows Expected declaration error? [duplicate]
(3 answers)
Expected Declaration Error using Swift
(1 answer)
Closed 5 years ago.
I get the error "expected declaration" on the last line when trying to add values to the dictionary tablesBooked.
class BookingSystem {
var tablesBooked = Dictionary<Int, String>()
var table = Table(tableID: 1 , tableCapacity: 2, status: "A")
var bookings = [Booking]()
tablesBooked.setValue(table.status, forKey: table.tableID)
}

You get this error because your line setValue cannot just live here inside your class without being inside a method. Of course here it really depends on what (and how) you want to accomplish, but you could put it in the init() method of your BookingSystem class, or you could build your own custom init().
Here is how it would look like:
import Foundation
class Booking {
// Some interesting things here
}
class Table : NSObject {
// MARK: Properties
var tableID: Int
var tableCapacity: Int
var status: String
// MARK: Initializers
init(tableID: Int, tableCapacity: Int, status: String) {
self.tableID = tableID
self.tableCapacity = tableCapacity
self.status = status
}
}
class BookingSystem {
// MARK: Properties
var tablesBooked = [Int: String]()
var table = Table(tableID: 1 , tableCapacity: 2, status: "A")
var bookings = [Booking]()
// MARK: Initializers
init() {
// I am not sure what you are trying to do here, but anyway you should add it in a custom method or your init. If I were to use the code in your example, you would add this here:
tablesBooked[table.tableID] = table.status
}
// ...
}
I added the Table class here on purpose, just to show you an example on how to create your own custom init.
Also, another thing worth mentioning here is that Swift Dictionaries don't have a setValue:forKey: method. Instead, to add an object to your Dictionary, you should use:
yourDictionnary["yourKey"] = yourValue
Hope it helps, and if you have any questions just feel free asking :)

Use init method:
class BookingSystem {
var tablesBooked = Dictionary<Int, String>()
var table = Table(tableID: 1 , tableCapacity: 2, status: "A")
var bookings = [Booking]()
init() {
tablesBooked.setValue(table.status, forKey: table.tableID)
}
}

Related

How can I access private property outside that class in Swift? [duplicate]

This question already has answers here:
Read-Only properties
(3 answers)
Closed 9 months ago.
Here I have a class and make its properties private to prevent from modifications by accident.
class Article {
private var lineIndex: [Int] = []
private var text: [String] = []
....
}
I know I can write a function like func text(_ index: Int) -> String to get its value at index. But when I call it, article1.text(2) would be weird. Because it's less clear to indicate 2 is an index than what an array does like article1.text[2]. So can I use getter or something else instead, while keeping the clear syntax like text[2]. It couldn't be better if you can offer some examples.
You can use one of these ways:
with private(set), which allows editable inside the class:
class Article {
private(set) var text: [String] = []
...
}
with get only computed property (this is the same like your get function)
class Article {
var _text: [String] {
return text
}
}

Can a struct have lazy properties [instantiation] in Swift?

Can a struct have lazy properties [instantiation] in Swift?
I cannot find any documentation saying yes or no. Everything only uses classes as examples.
If one can, can an example be found anywhere?
Thanks
Stan
Yes a struct can have a lazy property. Consider this example:
class Stuff {
var stuff: Int
init(value: Int) {
print("Stuff created with value \(value)")
stuff = value
}
}
struct HasLazy {
lazy var object = Stuff(value: 1)
var object2 = Stuff(value: 2)
}
func testIt() {
print("in testIt")
var haslazy = HasLazy()
print("done")
haslazy.object.stuff = 17
print("\(haslazy.object.stuff)")
print("final")
}
testIt()
Output:
in testIt
Stuff created with value 2
done
Stuff created with value 1
17
final
Notice that the property marked lazy is not initialized until after "done" prints when the property is first accessed.
See it in action here, and then try it without the lazy keyword.

Swift protocol settable property through a read-only property [duplicate]

This question already has an answer here:
Swift: Failed to assign value to a property of protocol?
(1 answer)
Closed 6 years ago.
Can someone please tell me why Swift has to call the setter of a property when it's only being used to access an object (a protocol) in order to set one of its properties? This first example shows the error I get if I don't declare the indirect object as settable:
protocol AProtocol {
var name: String { get set }
}
class AnImplementation: AProtocol {
var name = ""
}
class AParent {
var test = AnImplementation()
}
class AChild {
var parent: AParent!
var test: AProtocol {
get { return parent.test }
// Note: Not settable
}
}
var parent = AParent()
var child = AChild()
child.parent = parent
child.test.name = "Hello world!" // Error: Cannot assign to property : 'test' is a get-only property
print(child.test.name)
If I give it a setter, it compiles and works but it calls the setter:
protocol AProtocol {
var name: String { get set }
}
class AnImplementation: AProtocol {
var name = ""
}
class AParent {
var test = AnImplementation()
}
class AChild {
var parent: AParent!
var test: AProtocol {
get { return parent.test }
set(newTest) { print("Shouldn't be here!") }
}
}
var parent = AParent()
var child = AChild()
child.parent = parent
child.test.name = "Hello world!"
print(child.test.name)
Output is:
Shouldn't be here!
Hello world!
I'm not sure what I'm not understanding here. I assume I can just give it an empty setter, but I'd like to understand the reason for it.
Any information is much appreciated!
Change your protocol declaration to this:
protocol AProtocol:class {
var name: String { get set }
}
Otherwise, it is taken by default as a value type. Changing a value type's property replaces the value type instance (as shown by the setter observer). And you can't do that if the reference is a let reference.
This is probably caused by the fact that the compiler doesn't know whether AChild.test is a class or a value type. With classes there is no problem but with value types assigning to name would also create an assignment to test (value-copy behavior). Marking APProtocol as class protocol will fix the problem.
To expand, when the compiler is not sure whether test is a value or a class type, it will use the following rewrite of child.test.name = "Hello world!":
var tmp = child.test
tmp.test = "Hello world!"
child.test = tmp
because that will work for both class and value types.

Swift SpriteKit use struct instead of class to render sprites

I have been updating my game recently to use more value types. I am still not 100% confident with weak and unowned in some cases so I went the struct way to avoid strong reference cycles. As per apples newer keynotes it seems value types are they way to go for the most part anyway.
I have never seen an example where structs are used to render sprites in a spriteKit game so I wonder what the drawbacks are.
I understand that they are copied and not referenced but for my usage it seems to work.
So basically is there something I need to watch out for when doing this
struct Flag {
let post: SKSpriteNode
let flag: SKSpriteNode
init(postImage: String, flagImage: String) {
post = SKSpriteNode(imageNamed: postImage)
// other set ups for post sprite
flag = SKSpriteNode(imageNamed: flagImage)
// other set ups for flag sprite
post.addChild(flag)
}
func animate() {
// code to animate flag
}
}
Than in my SKScenes I simply add them as usual
let flag = Flag(postImage: "FlagPostImage", flagImage: "FlagImage")
flag.post.position = ...
addChild(flag.post)
flag.animate()
Now even if I create multiple flags in the same scene I seem to have no problems with this way.
I am just curious because I have never really seen an example like this so I wonder if I am missing something, like performance drawbacks etc.
Thanks for any help.
Personally I avoid creating Structs that contain Classes. Because Structs copy, each and every copy that get's passed around your app will increase the reference count of the Classes. This makes it harder to manage them instead of easier.
It is also useful to take a look at how UIKit uses Structs. A UIView is an object but has many defining properties that are Structs. For example it's frame.
Drop the code below in a playground to see some effects of this behaviour.
The protocol is just to get some meaningful feedback form the playground.
protocol IDLookable : CustomPlaygroundQuickLookable {
var id : Int { get set }
}
extension IDLookable {
func customPlaygroundQuickLook() -> PlaygroundQuickLook {
return PlaygroundQuickLook.AttributedString(NSAttributedString(string: "\(self.dynamicType) with id : \(self.id)"))
}
}
class MyClass : IDLookable {
var id : Int = 0
init(id : Int) {
self.id = id
}
}
struct MyContainerStruct : IDLookable {
var id : Int = 0
var object : MyClass
init(id : Int, object:MyClass) {
self.id = id
self.object = object
}
}
class Scope {
// ref count = 1
var object = MyClass(id: 11)
var structContainer : MyContainerStruct
init() {
// ref count = 2
structContainer = MyContainerStruct(id: 222, object: object)
messWithAClassInAStruct()
}
func messWithAClassInAStruct() {
// ref count = 3
var structContainerTwo = structContainer
structContainerTwo.id = 333
structContainerTwo.object // 11
// altering the object in one struct will obvously update all references
structContainerTwo.object.id = 1
structContainer.object // 1
structContainerTwo.object // 1
}
}
let test = Scope()
One pattern that does make it easy to work with Reference Types in Value Types is to store them as weak optionals in the Value Types. This means that something will need to have a strong reference but chances are that some Class will be responsible for creating the Structs this is a good place to keep that strong reference.
struct MyContainerStruct : IDLookable {
var id : Int = 0
weak var object : MyClass?
init(id : Int, object:MyClass) {
self.id = id
self.object = object
}
}
class Scope {
// ref count = 1
var object = MyClass(id: 11)
var structContainer : MyContainerStruct
init() {
// ref count = 1
structContainer = MyContainerStruct(id: 222, object: object)
messWithAClassInAStruct()
}
func messWithAClassInAStruct() {
// ref count = 1
var structContainerTwo = structContainer
structContainerTwo.id = 333
structContainerTwo.object // 11
}
}
let test = Scope()

Differences between "static var" and "var" in Swift

What is the main difference between "static var" and "var" in Swift? Can someone explain this difference to me, possibly with a little example?
static var belongs to type itself while var belongs to instance (specific value that is of specific type) of type. For example:
struct Car {
static var numberOfWheels = 4
var plateNumber: String
}
Car.numberOfWheels = 3
let myCar = Car(plateNumber: "123456")
All cars has same amount of wheels. An you change it on type Car itself.
In order to change plate number you need to have instance of Car. For example, myCar.
I'll give you a very nice Swifty example based on this post. Though this is a bit more sophisticated.
Imagine you have a project in which you have 15 collectionViews in your app. For each you have to set the cellIdentifier & nibName. Do you really want to rewrite all code for your that 15 times?
There is a very POP solution to your problem:
Let's help ourselves by writing a protocol which returns a string version of our ClassName
protocol ReusableView: class {
static var defaultReuseIdentifier: String { get }
}
extension ReusableView where Self: UIView {
static var defaultReuseIdentifier: String {
return String(Self)
}
}
extension BookCell : ReusableView{
}
The same for the nibName of each custom cell you have created:
protocol NibLoadableView: class {
static var nibName: String { get }
}
extension NibLoadableView where Self: UIView {
static var nibName: String {
return String(Self)
}
}
extension BookCell: NibLoadableView {
}
so now where ever I need nibName I would just do
BookCell.nibName
And where ever I need cellIdentifier I would just do:
BookCell.defaultReuseIdentifier
Now specifically to your question. Do you think we need to change the cellIdentifier per each new instance of BookCell?! No! All cells of BookCell will have the same identifier. It's not something that would change per instance. As a result it's been made static
While I did answer your question, the solution to reducing the number of lines for the 15 collectionViews can still be significantly improved so do see the blog post linked.
That blog post has actually been turned into a video by NatashaTheRobot
A static var is property variable on a struct versus an instance of the struct. Note that static var can exist for an enum too.
Example:
struct MyStruct {
static var foo:Int = 0
var bar:Int
}
println("MyStruct.foo = \(MyStruct.foo)") // Prints out 0
MyStruct.foo = 10
println("MyStruct.foo = \(MyStruct.foo)") // Prints out 10
var myStructInstance = MyStruct(bar:12)
// bar is not
// println("MyStruct.bar = \(MyStruct.bar)")
println("myStructInstance = \(myStructInstance.bar)") // Prints out 12
Notice the difference? bar is defined on an instance of the struct. Whereas foo is defined on the struct itself.