Why the code bellow does not change the string?
class Person {
var name = "Chris"
var age = 12
var male = true
var details, = [true, 100 , "good"]
}
family().details.append("friendly")
family().details //prints [1, 100, "good"]
Because you're accessing two different objects:
family().me.append("friendly")
This line creates an object, appending "friendly" to your [Any]
family().me //prints [1, 100, "good"]
Here you're printing the contents of a brand new object: me contains only 3 elements
If you want to see the change use the same object like so:
let f = family()
f.me.append("friendly")
f.me
Related
I have three dictionaries structured as [Int : Int]. Each dictionary is associated with an object. The key of the dictionary is a value of the object, and the value of the dictionary is how many object of that key should exist. One object holds all of these objects. So it would look at little like this.
class Cart {
var fruit: Fruit?
var cereal: Cereal?
var juice: Juice?
}
class Food {
var key: Int?
var text: String?
}
class Fruit: Food ...
class Cereal: Food ...
class Juice: Food ...
The idea is that the user has entered values for each possible option in text boxes and then a dictionary for each object is made. I need to make carts for every object, and each cart needs to holdas many objects as it can. If I have 6 fruits, 5 cereals, and 6 juices, then there should be 6 carts, one of them missing a cereal.
I have everything working up to figuring out how to actually put them together. Here's my loop.
for (key, value) in fruitValues {
for _ in 0..<value {
print(realm.objects(Fruit.self).filter("value == \(key)"))
}
}
How can I best loop through one array and get values from the others?
Here is my attempt to solve this, not the most compact solution but I couldn't figure out anything shorter. Assume our 3 dictionaries from the users selection
let dictFruit = [1: 2, 2: 4]
let dictCereal = [3: 5]
let dictJuice = [4: 3, 5:2, 6: 1]
for this example I use a dictionary as my Food types storage
let products = [1: Fruit(key: 1), 2: Fruit(key: 2), 3: Cereal(key: 3), 4:Juice(key: 4), 5:Juice(key: 5), 6:Juice(key: 6)]
First step is to flatten out the dictionaries to arrays of Food objects which is done with this function
func expandSelected<T: Food>(from dict: [Int: Int]) -> [T] {
return dict.reduce(into: []) {
if let food = products[$1.key] as? T {
$0.append(contentsOf: Array(repeating: food, count: $1.value))
}
}
}
Which I then used
let fruits: [Fruit] = expandSelected(from: dictFruit)
let juices: [Juice] = expandSelected(from: dictJuice)
let cereals: [Cereal] = expandSelected(from: dictCereal)
then for the last part I used an old fashioned for loop to create the Cart items
var carts = [Cart]()
for i in 0..<max(fruits.count, juices.count, cereals.count) {
let cart = Cart()
cart.cereal = cereals.count > i ? cereals[i] : nil
cart.fruit = fruits.count > i ? fruits[i] : nil
cart.juice = juices.count > i ? juices[i] : nil
carts.append(cart)
}
I'm working with Swift 3.
I would like to have this C syntax :
int myVar;
int *pointer = &myVar;
So modifying pointer or myVar does the same exact same thing.
Also I don't know if it makes any difference, but in my case myVar is an array containing elements of a class and pointer is a pointer to one element of this array.
The & also exists in Swift but can only be used as part of a parameter list (e.g. init, func, closure).
var i = 5
let ptr = UnsafeMutablePointer(&i)
print(ptr.pointee) // 5
// or
let ptr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
ptr.initialize(to: 5)
// or with a closure
let ptr: UnsafePointer = { $0 }(&i)
(Assuming I understand what you're asking for....)
Try the following code in a playground. It should print "99" three times.
class Row {
var rowNumber = 0
}
var rows = [Row]()
let testRow = Row()
testRow.rowNumber = 1
rows.append(testRow)
let selectedRow = rows[0]
selectedRow.rowNumber = 99
print(testRow.rowNumber)
print(selectedRow.rowNumber)
print(rows[0].rowNumber)
By default, there's no copying of objects as part of an assignment statement. If it were a struct, that would be different.
Adding a bit for completeness:
If you want a similar effect with scalar values instead of objects, Swift supplies various types of wrappers.
let intPointer = UnsafeMutablePointer<Int>.allocate(capacity: 8) // Should be 1, not 8 according to comment re: docs
let other = intPointer
other.pointee = 34
print(intPointer.pointee)
(Warning: I haven't used these wrappers for anything except experimenting in a playground. Don't trust it without doing some research.)
Same example as #Phillip. But I used struct. In this example rows[0] won't change:
struct Row {
var rowNumber = 0
}
var rows = [Row]()
var testRow = Row()
testRow.rowNumber = 1
rows.append(testRow)
var selectedRow = rows[0]
selectedRow.rowNumber = 99
print(testRow.rowNumber) // prints 1
print(selectedRow.rowNumber) // prints 99
print(rows[0].rowNumber) // prints 1
There are no C style pointers (Unsafe Pointer) as the question asks however objects are shared by reference and structures are by value:
Swift assign, pass and return a value by reference for reference type and by copy for Value Type
structures are always copied when they are passed around in your code, but classes are passed by reference.
For example
How to have pointers/ references to objects
class Song {
init(title: String, image: String, file: String, volume: Float, queuePlayer: AVQueuePlayer, playerLooper: AVPlayerLooper?) {
self.title = title
self.image = image
...
}
var title: String
var image: String
...
}
var aSong = Song(title: "", image: "", ...)
var arrOfSongReferences: [Song] = [Song]()
arrOfSongReferences.append(aSong)
var ptrToASong: Song = aSong
aSong = nil
// Due to Swift garbage collection ARC (Automatic Reference Counting), we still have references to the original aSong object so it won't be deleted
If data is struct you cannot do this
struct Song {
var title: String
var image: String
...
}
var aSong: Song = Song(title: "", image: "", ...)
var copyOfASong: Song = aSong
Method
You can also pass by reference into a function
// this would be inside a class, perhaps Player. It doesn't have to be a static btw
static func playSound(_ sound: inout Song, volume: Float = 0.0) {
if (sound.playerLooper == nil) {
...
}
}
// usage
Player.playSound(sound: &aSong)
I want to create a new array programmatically every round to store that rounds scores. So say I have
var roundNumber = 3
var team1Score = 5
var team2Score = 7
And I would store these in array
var scores = [Int]()
scores.append(team1Score)
scores.append(team2Score)
print (scores)
How would I dynamically change the name and then store the scores from that round so that I can load them at a later time. Or store that array into another array and create a new one so I can call upon it later and fill the new array with the current rounds scores without typing out every new array?
I prefer to use array of structs, something like below
struct Result {
let round: Int
let team1Score: Int
let team2Score: Int
}
var results = [Result]()
// round 1
let result = Result(round: 1, team1Score: 7, team2Score: 5)
results.append(result)
// round N or maybe could be done in loop
let resultN = Result(round: 2, team1Score: 17, team2Score: 10)
results.append(resultN)
class ScoreCard{
var round:Int?
var player1Score:Int?
var player2Score:Int?
}
var s = [ScoreCard]()
let scoreCard = ScoreCard()
scoreCard.round = 1
scoreCard.player1Score = 10
scoreCard.player2Score = 20
s.append(scoreCard)
This will do the job I guess.
You can use a dictionary and tuples for what you seem to be after.
Store the score of each round in a tuple:
var round1 = (team1score: 1, team2score: 3)
Then create a dictionary (dict) to store the tuple with the name you associated with it:
var scores: [String: (team1score: Int, team2score: Int)] = [:]
scores["1"] = round1
var anotherRound = (team1score: 12, team2score: 32)
scores["some round"] = anotherRound
print (scores)
You can define the dictionary to use the number of the round as the key, if that is what you need. Then the code would look like:
var round1 = (team1score: 1, team2score: 3)
var scores: [Int: (team1score: Int, team2score: Int)] = [:]
scores[1] = round1
var anotherRound = (team1score: 12, team2score: 32)
scores[4] = anotherRound
print (scores)
For doing stuff with the scores data, you can iterate easily:
for (round, score) in scores {
print("round \(round) had winner score \(max(score.team1score,score.team2score))")
}
This question already has answers here:
Swift: Creating an Array with a Default Value of distinct object instances
(2 answers)
Closed 6 years ago.
I'm trying to learn swift. When I do:
var myIntArray = [Int](count: 3, repeatedValue: 0)
myIntArray[0] = 1
myIntArray[1] = 11
myIntArray[2] = 111
// prints "my array: [1, 11, 111]"
NSLog("my int array: [%d, %d, %d]", myIntArray[0], myIntArray[1], myIntArray[2])
It works as expected, but when I wrap the int in a class like this:
class Foo {
var bar = 0
}
var myWrappedIntArray = [Foo](count: 3, repeatedValue: Foo())
myWrappedIntArray[0].bar = 1
myWrappedIntArray[1].bar = 11
myWrappedIntArray[2].bar = 111
// prints "my array: [111, 111, 111]"
NSLog("my wrapped int array: [%d, %d, %d]", myWrappedIntArray[0].bar, myWrappedIntArray[1].bar, myWrappedIntArray[2].bar)
It seems to modify the entire array when trying to modify a single element. What am I doing wrong here?
For this case it is better to use Struct:
struct Foo {
var bar = 0
}
var myWrappedIntArray = [Foo](count: 3, repeatedValue: Foo())
myWrappedIntArray[0].bar = 1
myWrappedIntArray[1].bar = 11
myWrappedIntArray[2].bar = 111
// prints "my array: [1, 11, 111]"
print("my wrapped int array: [%d, %d, %d]", myWrappedIntArray[0].bar, myWrappedIntArray[1].bar, myWrappedIntArray[2].bar)
In you're case you are working with reference type value such as [Foo]. But Struct is value typed and create each element of the array unique.
You are referencing to the same object in myWrappedIntArray[0].bar and myWrappedIntArray[n].bar.
Because of the constructor.
var myWrappedIntArray = [Foo](count: 3, repeatedValue: Foo())
You repeat Foo() reference for each element of the array instead of the creation of the new class for each index of the array.
This question already has an answer here:
Swift, get variable name from a string
(1 answer)
Closed 6 years ago.
Sequential variable names defined. I want to reach a variable relative to the corresponding value.
var code = 2 // 5, 6, ... // corresponding values
var name : String
var name1 : String = "Aaaaaa"
var name2 : String = "Bbbbbb"
// var name3
// var name4 ...
name = "name" + String(code) // name = "Bbbbb" ??
I do not get the results I wanted.
I hope i explained correctly. Thank you for your help.
Unlike in Objective-C, you can't access a variable by a String of its name in Swift. In your case, you might want to just use an array:
var code = 2 // 5, 6, ... // corresponding values
var names = ["Aaaaaa", "Bbbbbb"]
var name = names[code - 1] // "Bbbbbb"
If you really want to do it dynamically from a string name, you'll have to bridge to Objective-C, for example:
class SomeObject: NSObject {
var name1 : String = "Aaaaaa"
var name2 : String = "Bbbbbb"
func getName(code: Int) -> String {
let name = valueForKey("name" + String(code)) as! String // "Bbbbbb"
return name
}
}
SomeObject().getName(2) // "Bbbbbb"
Of course, by doing this, you lose a lot of the safety that Swift provides.