I have three classes A, B and C. A has a resource called rA. What I am trying to achieve is that all of those instances have a reference to the exact same resource.
So to concrete in Swift terms:
Class A has a property called foo:
private var foo : [Bar] = [Bar]() // shared resource
Class B has a property called foo which is passed into the initializer as an inout parameter:
private var foo : [Bar]!
init(inout foo:[Bar]){
self.foo = foo
}
Class C is analogous to Class B
How come, if I pass foo from Class A to Class B (or C) the address changes ?
In A I would pass it to B (or C) like so:
let b = B(foo: &self.foo)
When I print the address after initialization of foo in A it gives me a different address than after assignment in B.
class A{
private var foo = [Bar]()
func someFunc(){
NSLog("\n\n [A] \(unsafeAddressOf(self.foo))\n\n") // different from output in B
let b = B(foo: &self.foo)
}
}
class B{
private var foo: [Bar]!
init(inout foo: [Bar]){
self.foo = foo
NSLog("\n\n [B] \(unsafeAddressOf(self.foo))\n\n")
}
}
Any ideas why this is the case ?
Swift arrays are value types, therefore in
self.foo = foo
you assign the value of foo to self.foo. This are two independent arrays now
(even if the actual elements are copied only when one of the arrays is mutated).
Also you cannot take the address of a Swift array with unsafeAddressOf() because
that function takes an AnyObject parameter which is an instance of a class, i.e.
a value type. In
unsafeAddressOf(self.foo)
the Swift compiler actually bridges the Swift array to an NSArray. As demonstrated
in Swift, Strings and Memory Addresses,
this may or may not result in the same object when done repeatedly. In any case,
the printed address is not the storage location of the Swift array.
If you need a real reference which you can pass around then you can wrap the array in a class.
Using NS(Mutable)Array might also be an option, but then you lose many Swift features.
Related
I’m confused by a line of code found in the Metal example where the memory pointer is bound to a type.
uniforms = UnsafeMutableRawPointer(uniformBuffer.contents()).bindMemory(to: Uniforms.self, capacity: 1)
My confusion is the .self after the Uniforms type. Uniforms is a struct defined in an Objective-C file and the code wont run without .self being in the call. Why is that necessary?
The .self returns the metatype instance for the corresponding type. Think of it as a typesafe type identifier (e.g., way safer than using a string for that). You can then safely call the available initializers, static methods, static properties on such metatype instance.
For instance, you could store it in a variable as well:
let metatype: Uniforms.Type = Uniforms.self
and Uniforms.Type is the actual metatype (i.e., the type's type).
Metatype crash course. A very quick example to get a feel of how this meta stuff might be actually useful:
class Super {
let id: Int
required init(id: Int) { self.id = id }
}
class SubA: Super { ... }
class SubB: Super { ... }
let subclass: Super.Type = SubA.self
and then, later on, use subclass to create an instance without hardcoding the actual subclass type name:
let obj = subclass.init(id: 123) // new SubA instance.
In Swift, .self could be used on a type to extract its meta type or on an instance of a type. Example, use .self to get the meta type and pass it to the API:
self.tableView.registerClass(
UITableViewCell.self, forCellReuseIdentifier: "myUIViewCell")
I'm using an enum variable called BuildingType in a class initializer (of a class called Building).
This enum is defined outside the class because I want to use it also in other places.
The autocomplete for this enum is not working properly when initializing the variable typeOfBuilding.
Example code:
enum BuildingType {
case Flat, House, Villa
}
class Building {
var type : BuildingType = BuildingType.House
var floors : Int = 1
init(typeOfBuilding : BuildingType, numFloors : Int) {
self.type = typeOfBuilding
self.floors = numFloors
}
}
var myBuilding : Building = Building(typeOfBuilding: BuildingType.Flat , numFloors: 3)
So if I type "... typeOfBuilding: BuildingType." (when initializing myBuilding) 'floors' and 'type' are shown, and not the enum values.
I must be doing something wrong here but what?
This is a pretty weird bug
It occurs when you attempt to pass an enum into an argument of an initialiser, autocomplete will fail and instead of suggesting the enum cases after typing Enum., it will list the instance members of the class you’re calling the initialiser on. If you try and use the single dot syntax (.Case), autocomplete will also fail, but instead of displaying the list of instance members, it simply won't display anything.
I initially thought it may have had something to do with the naming of your enum and class (BuildingType & Building), but this is not the case.
This bug only appears to be present in initialisers with multiple arguments (one of which being an enum). I couldn’t reproduce this issue with single argument initialisers.
The reproducibility appears to depend on whether the initialiser is 'complete'. I'm considering an initialiser to be 'complete' if it has all argument names and values (except the enum) defined. For example:
// Incomplete (foo is one argument of many)
let baz = Baz(foo: Foo.
// Semi-Complete (before you assign the second parameter a value)
let baz = Baz(foo: Foo., string: <String Placeholder>)
// Complete
let baz = Baz(foo: Foo., string: "")
// Complete (note the lack of the last bracket)
let baz = Baz(param: 0, foo: Foo.
Here is my test setup (Xcode 7.3, Swift 2.2):
enum Foo {
case Bar
}
class Baz {
var iReallyShouldntBeDisplayedHere = 0
init(foo:Foo, string:String) {}
init(foo: Foo) {}
}
And here is a list of cases where I've found the bug does & doesn't occur:
// Enum is the only argument
// CORRECT: accepting the initialiser's autocomplete (so it's 'complete'), then typing "Foo." brings up autocomplete options for enum cases
let baz = Baz(foo: Foo.)
// CORRECT: typing the initialiser yourself (so it's 'incomplete'), then typing "Foo." in the first parameter brings up autocomplete options for enum cases
let baz2 = Baz(foo: Foo.
// Enum is one argument of many
// INCORRECT: accepting the initialiser's autocomplete (so it's 'semi-complete'), then typing "Foo." in the first parameter brings up Baz's instance members ("iReallyShouldntBeDisplayedHere")
let baz3 = Baz(foo: Foo., string: <String Placeholder>)
// CORRECT: typing the initialiser yourself (so it's 'incomplete'), and typing "Foo." in the first parameter brings up enum cases
let baz4 = Baz(foo: Foo.
// Single dot syntax (where enum is one argument of many)
// CORRECT: typing the initialiser yourself (so it's 'incomplete'), and typing "." in the first parameter brings up enum cases
let baz5 = Baz(foo:.
// CORRECT: accepting the initialiser's autocomplete (so it's 'semi-complete'), then typing "." in the first parameter brings up enum cases
let baz6 = Baz(foo:., string: <String Placeholder>)
// INCORRECT: modifying the foo: argument once the initialiser is 'complete' by typing "." in the first parameter doesn't generate the autocomplete list
let baz7 = Baz(foo:., string: "")
I also tried this where foo: is the last argument, but the initialiser always has to be complete in that case, so it always fails. I did try with initialisers that take 3 arguments, but it appears to have the same behaviour as an initialiser with 2 arguments.
If anyone knows of any more cases where this bug can be reproduced, I'd love to know!
There are some posts for how to write code for static constant and static variable in Swift. But it is not clear when to use static constant and static variable rather than constant and variable. Can someone explain?
When you define a static var/let into a class (or struct), that information will be shared among all the instances (or values).
Sharing information
class Animal {
static var nums = 0
init() {
Animal.nums += 1
}
}
let dog = Animal()
Animal.nums // 1
let cat = Animal()
Animal.nums // 2
As you can see here, I created 2 separate instances of Animal but both do share the same static variable nums.
Singleton
Often a static constant is used to adopt the Singleton pattern. In this case we want no more than 1 instance of a class to be allocated.
To do that we save the reference to the shared instance inside a constant and we do hide the initializer.
class Singleton {
static let sharedInstance = Singleton()
private init() { }
func doSomething() { }
}
Now when we need the Singleton instance we write
Singleton.sharedInstance.doSomething()
Singleton.sharedInstance.doSomething()
Singleton.sharedInstance.doSomething()
This approach does allow us to use always the same instance, even in different points of the app.
There are some posts for how to write code for static constant and static variable in Swift. But it is not clear when to use static constant and static variable rather than constant and variable. Can someone explain?
When you define a static var/let into a class (or struct), that value will be shared among all the instances (or values).
static variables/class are variables can be accessed without need of creation of any instance/object.
class Human {
static let numberOfEyes = 2 //human have only 2 eyes
static var eyeDefect = false //whether human have side-effect or not. he can have defect later so its variable
//other variables and functions
}
//you can access numberOfEyes like below no object of Human is created
print(Human.numberOfEyes)
print(Human.eyeDefect)
//Object of Human
let john = Human()
I think you know difference between constant and variable. In short, constant is that whose value never changes; numberOfEyes in above example and variable is that whose value changes; eyeDefect in above example.
static constant or variables are placed in memory(RAM) separate then the Objects. i.e. numberOfEyes have different memory space allocated than John object, its not inside John.
now, when to use static constants/variables:
When you use singleton design pattern: static let sharedInstance = APIManager()
class APIManager(){
static let sharedInstance = APIManager()
//Your other variables/functions here below
}
//Use it as to get singleton instance of APIManager from anywhere in your application
let instanceOfAPIManager = APIManager.sharedInstance
When you need value of anything that is globally the same without need to make instance of the class under which it is defined like numberOfEyes in human class.
Use of static variables/constants are not much recommended because of memory issues because once it's instantiated/assigned, it remains in memory until your application gets removed from the memory. I have found till now the best place to use static variables/constants is only while making singleton pattern and sometimes pointers for other normal variables and constants don't use static because: memory issue, it will be difficult to run unit testing in your code with static variables/constants. Not recommended to use as like in Human class also. instead use them as just constant or variables and access them by making instance.
class Human {
let numberOfEyes = 2 //human have only 2 eyes
var eyeDefect = false //whether human have side-effect or not. he can have defect later so its variable
//other variables and functions
}
//you can access numberOfEyes like below if you need just those values.
print(Human().numberOfEyes)
print(Human().eyeDefect)
Static constants and variables do belong to the class itself, not to a particular instance. A class can also have static methods that can be called without creating an instance of a class.
So when you have a class MyClass with a static var x, you can also access it through MyClass.x directly. x will be shared among all instances of a class
This is more of an important comment:
class Person {
static var name = "Static John" // a property of Person 'type'
var name = "Alex" // a property of Person 'instance'
var nonStaticName = "Peter"
static var staticName = "Sara"
static func statFunc() {
let x = Person.name // Static John
let y = name // Static John or Alex?! Static John!!!!
let r = staticName // Sara
let k = nonStaticName // ERROR: instance member 'nonStaticName' cannot be used on type 'Person'
// The compiler is like: I'm referring to the `nonStaticName` property of which instance?! There is no instance! Sorry can't do!
}
func nonStaticFunc() {
let x = Person.name // Static John
let y = name // Static John or Alex?! Alex!!! Because we're in a instance scope...
let k = nonStaticName // Obviously works
let r = staticName // ERROR: static member 'staticName' cannot be used on instance of type 'Person'. Person.staticName will work
}
}
Interesting observations:
First:
static var name = "Static John" // a property of Person 'type'
var name = "Alex" // a property of Person 'instance'
creates no conflicts.
Second:
You can't ever use instance variables inside static variables. You can use static variables inside instance functions if you refer to it by prefixing it with the type ie do Person.name, whereas
static variables can be accessed inside static functions with or without prefixing the type ie Person.staticName or staticName both work.
I am quite new in Swift. And I create a class(for example):
class Fraction{
var a: Int
init(a:Int){
self.a = a
}
func toString() -> String{
return "\(self.a)"
}
}
and I also build a in other class function:
class func A_plusplus(f:Fraction){
f.a++
}
Then in the executive class I write:
var object = Fraction(a:10)
print("before run func = " + object.toString())
XXXclass.A_plusplus(object)
print("after ran func =" + object.toString() )
So the console output is
before run func = 10; after ran func =11
The question is how can I just send a copy of the "object" to keep its value which equal to 10
And if functions are always pass-by-reference, why we still need the keyword: "inout"
what does difference between A_plusplus(&object)//[if I make the parameter to be a inout parameter] and A_plusplus(object)
Universally, I don't want to use struct. Although this will solve my
problem exactly, I do pass-by-value rarely.So I don't want program's
copying processes slow my user's phone down :(
And It seems conforming the NSCopying protocol is a good option.But
I don't know how to implement the function:
func copyWithZone(zone:
NSZone)-> AnyObject? correctly
If your class is subclass of NSObject,better to use NSCopying
class Fraction:NSObject,NSCopying{
var a:Int
var b:NSString?
required init(a:Int){
self.a = a
}
func toString() -> String{
return "\(self.a)"
}
func copyWithZone(zone: NSZone) -> AnyObject {
let theCopy=self.dynamicType.init(a: self.a)
theCopy.b = self.b?.copy() as? NSString
return theCopy
}
}
class XXXclass{
class func A_plusplus(f:Fraction){
f.a++
f.b = "after"
}
}
var object = Fraction(a:10)
object.b = "before"
print("before run func = " + object.toString())
print(object.b!) //“Before”
XXXclass.A_plusplus(object.copy() as! Fraction)
print("after ran func =" + object.toString() )
print(object.b!)//“Before”
If it is just a common swift class,You have to create a copy method
class Fraction{
var a: Int
init(a:Int){
self.a = a
}
func toString() -> String{
return "\(self.a)"
}
func copy()->Fraction{
return Fraction(a: self.a)
}
}
class XXXclass{
class func A_plusplus(f:Fraction){
f.a++
}
}
var object = Fraction(a:10)
print("before run func = " + object.toString())
XXXclass.A_plusplus(object.copy())
print("after ran func =" + object.toString() )
To make it clear,you have to know that there are mainly two types in swift
Reference types. Like Class instance,function type
Value types,Like struct and others(Not class instance or function type)
If you pass in a Reference types,you pass in the copy of Reference,it still point to the original object.
If you pass in a Copy type,you pass in the copy of value,so it has nothing to do with the original value
Let us talk about inout,if you use it,it pass in the same object or value.It has effect on Value type
func add(inout input:Int){
input++
}
var a = 10
print(a)//10
add(&a)
print(a)//11
Swift has a new concept so called "struct"
You can define Fraction as struct (Not class)
And
struct Fraction{
...
}
var object = Fraction(a:10)
var object1 = object //then struct in swift is value type, so object1 is copy of object (not reference)
And if you use struct then try to use inout in A_plusplus function
Hope this will help you.
how can I just send a copy of the "object" to keep its value which equal to 10
In Swift classes and functions are always passed by reference. Structs, enums and primitive types are passed by value. See this answer.
You can't pass an object by value. You would have to manually copy it before passing it by reference (if that's what you really want).
Another way is to turn your class into a struct, since it would then be passed by value. However, keep in mind there a few other differences between classes and structs, and it might not necessarily be what you want.
And if functions are always pass-by-reference, why we still need the keyword: "inout"
According to the swift documentation, inout is used when
you want a function to modify a parameter’s value, and you want those changes to persist after the function call has ended, define that parameter as an in-out parameter instead.
So in practice with inout you can pass a value type (such as struct or primitive) by reference. You shouldn't really use this very often. Swift provides tuples, that could be used instead.
what does difference between A_plusplus(&object)//[if I make the parameter to be a inout parameter] and A_plusplus(object)
There is no difference for your A_plusplus function. In that function you don't modify the parameter f itself, you modify the f.a property.
The following example shows the effect of using inout when passing a class object. Both functions are the same, differing only in its parameter definition.
class Person {
var name: String
init(name: String) { self.name = name }
}
var me = Person(name: "Lennon") // Must be var to be passed as inout
// Normal object by reference with a var
func normalCall(var p: Person) {
// We sure are able to update p's properties,
// and they will be reflected back to me
p.name = "McCartney"
// Now p points to a new object different from me,
// changes won't be reflected back to me
p = Person(name: "Ringo")
}
// Inout object reference by value
func inoutCall(inout p: Person) {
// We still can update p's properties,
p.name = "McCartney"
// p is an alias to me, updates made will persist to me
p = Person(name: "Ringo")
}
print("\(me.name)") //--> Lennon
normalCall(me)
print("\(me.name)") //--> McCartney
inoutCall(&me)
print("\(me.name)") //--> Ringo
In normalCall p and me are different variables that happen to point to the same object. When you instantiate and assign a new object to p, they no longer refer to the same object. Hence, further changes to this new object will not be reflected back to me.
Stating that p is a var argument just means that its value can change throughout the function, it does not mean the new value will be assigned to what was passed as argument.
On the other hand, in inoutCall you can think of p and me as aliases. As such, assigning a new object to p is the exact same as assigning a new object to me. Any and every change to p is persisted in me after the function ends.
I am currently reading The Swift Programming Language, and when it reaches to Type Properties, it says “You define type properties for value types with the static keyword, and type properties for class types with the class keyword. ” But what static means and what id does? I just can't get a clue.
Type properties are properties that are associated with the type, meaning you don't need an actual instance of the class or struct to access them. static is used to define such a property in structs. For example:
struct Constants {
static let pi = 3.1416
static let e = 2.71828
let phi = 1.618
}
println(Constants.pi) // prints "3.1416"
println(Constants.e) // prints "2.71828"
println(Constants.phi) // Error: 'Constants.Type' does not have a member named 'phi'
println(Constants().phi) // prints "1.618" when we create an instance