Cannot Access .size withAttributes: from String - ios

I have a String extension:
func iconName(identifier: String) -> String
{
return self.library()[identifier]
}
and I'm doing this inside a UIImage extension:
let icon = String.iconName("myiconname")
var iconSize = icon.size(withAttributes: someAttributes)
I get an error:
Value of type '(String) -> String' has no member 'size'
I have tried to switch this around many different ways and I get the same (or similar) error each time.
The thing is it does have a member size. I can do this with no error:
var myString = "testing"
myString.size(withAttributes: attributes)
Anyone know what is going on with the Value of type '(String) -> String'?

The method
size(withAttributes:)
is an instance method inside NSString not String
see here in Docs
So , you can change signature of the method to
func iconName(identifier: String) -> NSString {....}
//
You should not use
let icon = String.iconName("myiconname") // here String is a generic type
as extension is designated to be used with an object like
let icon = "someStringValue".iconName("myiconname")

I would not use a String extension here because the return is of type (String) -> String which is not the same as type String and the extension will not allow you to cast its type. I assume you chose an extension to make it globally accessible but there are other options. You can make the function itself global (which I don't find attractive), you can make the function static within a regular class or struct, you can make the struct static, you can do the singleton pattern, you can store the function in the app delegate and call it there--you have a list of options to make properties and methods "global".
Because all that this method does is take a String and convert it into a modified String, no need for singleton, and so I would most likely create a global class with static properties.
class Globals {
static func iconName(_ identifier: String) -> String {
return "slickDaddy"
}
}
let icon = Globals.iconName("myIconName")
var iconSize = icon.size(withAttributes: [NSAttributedStringKey.backgroundColor: UIColor.blue])
print(iconSize) // prints (58.01953125, 13.8)
You can call this method from anywhere in the app. Certainly consider all of the other iterations I mentioned above and use the one that suits you best. Furthermore, even if you could do this in an extension, I personally wouldn't. This is a business method used in very special cases, not a method that modifies the style of a String that is used all over the app (which is what I think extensions should be primarily used for).

Related

Can #dynamicMemberLookup be used to call methods?

In the documentation for #dynamicMemberLookup it says,
Apply this attribute to a class, structure, enumeration, or protocol to enable members to be looked up by name at runtime.
If I'm not mistaken, instance methods are considered members of a struct / class. However, when I try to call a function dynamically I get an error saying:
Dynamic key path member lookup cannot refer to instance method foo()
To reproduce the problem:
struct Person {
var name: String
var age: Int
func greet() {
print("hello, my name is \(name)")
}
}
#dynamicMemberLookup
struct Wrapper {
var value: Person
subscript<T>(dynamicMember keypath: KeyPath<Person, T>) -> T {
value[keyPath: keypath]
}
}
let person = Person(name: "John Doe", age: 21)
let wrapper = Wrapper(value: person)
wrapper.greet() // << Error: Dynamic key path member lookup cannot refer to instance method `greet()`
// Or
let function = wrapper.greet // << Error: Dynamic key path member lookup cannot refer to instance method `greet()`
function()
How can I dynamically call greet() using #dynamicMemberLookup? Is there any way to achieve what I'm trying to do?
Thanks in advance!
No, dynamicMemberLookup does not work for methods. As the signature of the subscript suggests, it only works for things that can be represented as a KeyPath. Method calls cannot be part of a key path. :(
Key-Path Expression
A key-path expression refers to a property or subscript of a type.
The path consists of property names, subscripts, optional-chaining
expressions, and forced unwrapping expressions. Each of these key-path
components can be repeated as many times as needed, in any order.
At compile time, a key-path expression is replaced by an instance of
the KeyPath class.
I suspect the reason why it is called "dynamic member lookup" is because it also works with subscripts. The alternative of dynamicPropertyOrSubscriptLookup is rather a mouthful isn't it?
One rather hacky fix would be to change greet into a computed property:
var greet: () -> Void { {
print("hello, my name is \(name)")
} }
If greet has had parameters, you could also change it into a subscript, but I think that is an even uglier solution.

Swift compile time errors when using generics and accessing dictionary's values

Below I have a class, B, with a generic type and the generic type has a subclass type constraint. In a separate class, A, I create a dictionary property, values, with the key as String and value as B. Class A then has methods to return or set values in the dictionary such that the values are not constrained to a single type (they maintain their generic SomeType type which is a subclass of NSObject). However, this produces the following two errors noted inline below:
class A: NSObject {
var values = [String : B]()
func get<SomeType: NSObject>(key: String) -> B<SomeType>? {
// #1 Error on line below: cannot convert return expression of type 'B<NSObject>?' to return type 'B<SomeType>?'
return values[key]
}
func set<SomeType: NSObject>(key: String, value: B<SomeType>) {
// #2 Error on line below: cannot assign value of type 'B<SomeType>' to type 'B<NSObject>?'
values[key] = value
}
}
class B<SomeType: NSObject>: NSObject {
}
I've attempted various forms of declaring the values dictionary to tell the compiler that SomeType is a subclass of NSObject and everything is going to be ok, but have been unsuccessful. Similarly to this question, I'm a bit stumped because the methods define SomeType as a subclass of NSObject and therefore things appear to be type safe when setting and getting from values.
I could remove the generic types from the methods and instead force the type to be <NSObject>, but then I'd run into the same problem as noted here.
This may not be doing what you think it's doing:
var values = [String : B]()
This isn't really [String : B], it's [String : B<NSObject>]. (I'm actually kind of surprised that this is legal syntax; I'd be tempted to open a bugreport about that; B isn't a proper type in Swift.) You may realize this already, but it's the first important note.
The second important note is that generic types are not covariant in Swift. A Thing<Cat> is not a subtype of Thing<Animal>. There are some type-theory reasons for this, and there are some technical implementation reasons for this, but the important fact is that it's not possible in Swift.
If you need to hold a variety of B types, then you'll need to build a type eraser. In your case, the type eraser could possibly be B<NSObject> with something like this:
class B<SomeType: NSObject>: NSObject {
let value: SomeType
init(value: SomeType) {
self.value = value
}
func liftGeneric() -> B<NSObject> {
return B<NSObject>(value: value)
}
}
If you need to hold just one kind of B type, then make A generic as well.

Get the class type name of a UIView subclass in Swift [duplicate]

Is there a way to print the runtime type of a variable in swift? For example:
var now = NSDate()
var soon = now.dateByAddingTimeInterval(5.0)
println("\(now.dynamicType)")
// Prints "(Metatype)"
println("\(now.dynamicType.description()")
// Prints "__NSDate" since objective-c Class objects have a "description" selector
println("\(soon.dynamicType.description()")
// Compile-time error since ImplicitlyUnwrappedOptional<NSDate> has no "description" method
In the example above, I'm looking for a way to show that the variable "soon" is of type ImplicitlyUnwrappedOptional<NSDate>, or at least NSDate!.
Update September 2016
Swift 3.0: Use type(of:), e.g. type(of: someThing) (since the dynamicType keyword has been removed)
Update October 2015:
I updated the examples below to the new Swift 2.0 syntax (e.g. println was replaced with print, toString() is now String()).
From the Xcode 6.3 release notes:
#nschum points out in the comments that the Xcode 6.3 release notes show another way:
Type values now print as the full demangled type name when used with
println or string interpolation.
import Foundation
class PureSwiftClass { }
var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"
print( "String(myvar0.dynamicType) -> \(myvar0.dynamicType)")
print( "String(myvar1.dynamicType) -> \(myvar1.dynamicType)")
print( "String(myvar2.dynamicType) -> \(myvar2.dynamicType)")
print( "String(myvar3.dynamicType) -> \(myvar3.dynamicType)")
print( "String(Int.self) -> \(Int.self)")
print( "String((Int?).self -> \((Int?).self)")
print( "String(NSString.self) -> \(NSString.self)")
print( "String(Array<String>.self) -> \(Array<String>.self)")
Which outputs:
String(myvar0.dynamicType) -> __NSCFConstantString
String(myvar1.dynamicType) -> PureSwiftClass
String(myvar2.dynamicType) -> Int
String(myvar3.dynamicType) -> String
String(Int.self) -> Int
String((Int?).self -> Optional<Int>
String(NSString.self) -> NSString
String(Array<String>.self) -> Array<String>
Update for Xcode 6.3:
You can use the _stdlib_getDemangledTypeName():
print( "TypeName0 = \(_stdlib_getDemangledTypeName(myvar0))")
print( "TypeName1 = \(_stdlib_getDemangledTypeName(myvar1))")
print( "TypeName2 = \(_stdlib_getDemangledTypeName(myvar2))")
print( "TypeName3 = \(_stdlib_getDemangledTypeName(myvar3))")
and get this as output:
TypeName0 = NSString
TypeName1 = __lldb_expr_26.PureSwiftClass
TypeName2 = Swift.Int
TypeName3 = Swift.String
Original answer:
Prior to Xcode 6.3 _stdlib_getTypeName got the mangled type name of a variable. Ewan Swick's blog entry helps to decipher these strings:
e.g. _TtSi stands for Swift's internal Int type.
Mike Ash has a great blog entry covering the same topic.
Edit: A new toString function has been introduced in Swift 1.2 (Xcode 6.3).
You can now print the demangled type of any type using .self and any instance using .dynamicType:
struct Box<T> {}
toString("foo".dynamicType) // Swift.String
toString([1, 23, 456].dynamicType) // Swift.Array<Swift.Int>
toString((7 as NSNumber).dynamicType) // __NSCFNumber
toString((Bool?).self) // Swift.Optional<Swift.Bool>
toString(Box<SinkOf<Character>>.self) // __lldb_expr_1.Box<Swift.SinkOf<Swift.Character>>
toString(NSStream.self) // NSStream
Try calling YourClass.self and yourObject.dynamicType.
Reference: https://devforums.apple.com/thread/227425.
Swift 3.0
let string = "Hello"
let stringArray = ["one", "two"]
let dictionary = ["key": 2]
print(type(of: string)) // "String"
// Get type name as a string
String(describing: type(of: string)) // "String"
String(describing: type(of: stringArray)) // "Array<String>"
String(describing: type(of: dictionary)) // "Dictionary<String, Int>"
// Get full type as a string
String(reflecting: type(of: string)) // "Swift.String"
String(reflecting: type(of: stringArray)) // "Swift.Array<Swift.String>"
String(reflecting: type(of: dictionary)) // "Swift.Dictionary<Swift.String, Swift.Int>"
Is this what you're looking for?
println("\(object_getClassName(now))");
It prints "__NSDate"
UPDATE: Please note this no longer seems to work as of Beta05
My current Xcode is Version 6.0 (6A280e).
import Foundation
class Person { var name: String; init(name: String) { self.name = name }}
class Patient: Person {}
class Doctor: Person {}
var variables:[Any] = [
5,
7.5,
true,
"maple",
Person(name:"Sarah"),
Patient(name:"Pat"),
Doctor(name:"Sandy")
]
for variable in variables {
let typeLongName = _stdlib_getDemangledTypeName(variable)
let tokens = split(typeLongName, { $0 == "." })
if let typeName = tokens.last {
println("Variable \(variable) is of Type \(typeName).")
}
}
Output:
Variable 5 is of Type Int.
Variable 7.5 is of Type Double.
Variable true is of Type Bool.
Variable maple is of Type String.
Variable Swift001.Person is of Type Person.
Variable Swift001.Patient is of Type Patient.
Variable Swift001.Doctor is of Type Doctor.
As of Xcode 6.3 with Swift 1.2, you can simply convert type values into the full demangled String.
toString(Int) // "Swift.Int"
toString(Int.Type) // "Swift.Int.Type"
toString((10).dynamicType) // "Swift.Int"
println(Bool.self) // "Swift.Bool"
println([UTF8].self) // "Swift.Array<Swift.UTF8>"
println((Int, String).self) // "(Swift.Int, Swift.String)"
println((String?()).dynamicType)// "Swift.Optional<Swift.String>"
println(NSDate) // "NSDate"
println(NSDate.Type) // "NSDate.Type"
println(WKWebView) // "WKWebView"
toString(MyClass) // "[Module Name].MyClass"
toString(MyClass().dynamicType) // "[Module Name].MyClass"
You can still access the class, through className (which returns a String).
There are actually several ways to get the class, for example classForArchiver, classForCoder, classForKeyedArchiver (all return AnyClass!).
You can't get the type of a primitive (a primitive is not a class).
Example:
var ivar = [:]
ivar.className // __NSDictionaryI
var i = 1
i.className // error: 'Int' does not have a member named 'className'
If you want to get the type of a primitive, you have to use bridgeToObjectiveC(). Example:
var i = 1
i.bridgeToObjectiveC().className // __NSCFNumber
You can use reflect to get information about object.
For example name of object class:
var classname = reflect(now).summary
Xcode 8 Swift 3.0 use type(of:)
let className = "\(type(of: instance))"
I had luck with:
let className = NSStringFromClass(obj.dynamicType)
SWIFT 5
With the latest release of Swift 3 we can get pretty descriptions of type names through the String initializer. Like, for example print(String(describing: type(of: object))). Where object can be an instance variable like array, a dictionary, an Int, a NSDate, an instance of a custom class, etc.
Here is my complete answer: Get class name of object as string in Swift
That question is looking for a way to getting the class name of an object as string but, also i proposed another way to getting the class name of a variable that isn't subclass of NSObject. Here it is:
class Utility{
class func classNameAsString(obj: Any) -> String {
//prints more readable results for dictionaries, arrays, Int, etc
return String(describing: type(of: obj))
}
}
I made a static function which takes as parameter an object of type Any and returns its class name as String :) .
I tested this function with some variables like:
let diccionary: [String: CGFloat] = [:]
let array: [Int] = []
let numInt = 9
let numFloat: CGFloat = 3.0
let numDouble: Double = 1.0
let classOne = ClassOne()
let classTwo: ClassTwo? = ClassTwo()
let now = NSDate()
let lbl = UILabel()
and the output was:
diccionary is of type Dictionary
array is of type Array
numInt is of type Int
numFloat is of type CGFloat
numDouble is of type Double
classOne is of type: ClassOne
classTwo is of type: ClassTwo
now is of type: Date
lbl is of type: UILabel
In Xcode 8, Swift 3.0
Steps:
1. Get the Type:
Option 1:
let type : Type = MyClass.self //Determines Type from Class
Option 2:
let type : Type = type(of:self) //Determines Type from self
2. Convert Type to String:
let string : String = "\(type)" //String
In Swift 3.0, you can use type(of:), as dynamicType keyword has been removed.
To get a type of object or class of object in Swift, you must need to use a type(of: yourObject)
type(of: yourObject)
When using Cocoa (not CocoaTouch), you can use the className property for objects that are subclasses of NSObject.
println(now.className)
This property is not available for normal Swift objects, which aren't subclasses of NSObject (and in fact, there is no root id or object type in Swift).
class Person {
var name: String?
}
var p = Person()
println(person.className) // <- Compiler error
In CocoaTouch, at this time there is not a way to get a string description of the type of a given variable. Similar functionality also does not exist for primitive types in either Cocoa or CocoaTouch.
The Swift REPL is able to print out a summary of values including its type, so it is possible this manner of introspection will be possible via an API in the future.
EDIT: dump(object) seems to do the trick.
The top answer doesn't have a working example of the new way of doing this using type(of:. So to help rookies like me, here is a working example, taken mostly from Apple's docs here - https://developer.apple.com/documentation/swift/2885064-type
doubleNum = 30.1
func printInfo(_ value: Any) {
let varType = type(of: value)
print("'\(value)' of type '\(varType)'")
}
printInfo(doubleNum)
//'30.1' of type 'Double'
I've tried some of the other answers here but milage seems to very on what the underling object is.
However I did found a way you can get the Object-C class name for an object by doing the following:
now?.superclass as AnyObject! //replace now with the object you are trying to get the class name for
Here is and example of how you would use it:
let now = NSDate()
println("what is this = \(now?.superclass as AnyObject!)")
In this case it will print NSDate in the console.
I found this solution which hopefully might work for someone else.
I created a class method to access the value. Please bear in mind this will work for NSObject subclass only. But at least is a clean and tidy solution.
class var className: String!{
let classString : String = NSStringFromClass(self.classForCoder())
return classString.componentsSeparatedByString(".").last;
}
In the latest XCode 6.3 with Swift 1.2, this is the only way I found:
if view.classForCoder.description() == "UISegment" {
...
}
Many of the answers here do not work with the latest Swift (Xcode 7.1.1 at time of writing).
The current way of getting the information is to create a Mirror and interrogate that. For the classname it is as simple as:
let mirror = Mirror(reflecting: instanceToInspect)
let classname:String = mirror.description
Additional information about the object can also be retrieved from the Mirror. See http://swiftdoc.org/v2.1/type/Mirror/ for details.
Swift version 4:
print("\(type(of: self)) ,\(#function)")
// within a function of a class
Thanks #Joshua Dance
In lldb as of beta 5, you can see the class of an object with the command:
fr v -d r shipDate
which outputs something like:
(DBSalesOrderShipDate_DBSalesOrderShipDate_ *) shipDate = 0x7f859940
The command expanded out means something like:
Frame Variable (print a frame variable) -d run_target (expand dynamic types)
Something useful to know is that using "Frame Variable" to output variable values guarantees no code is executed.
I've found a solution for self-developed classes (or such you have access to).
Place the following computed property within your objects class definition:
var className: String? {
return __FILE__.lastPathComponent.stringByDeletingPathExtension
}
Now you can simply call the class name on your object like so:
myObject.className
Please note that this will only work if your class definition is made within a file that is named exactly like the class you want the name of.
As this is commonly the case the above answer should do it for most cases. But in some special cases you might need to figure out a different solution.
If you need the class name within the class (file) itself you can simply use this line:
let className = __FILE__.lastPathComponent.stringByDeletingPathExtension
Maybe this method helps some people out there.
Based on the answers and comments given by Klass and Kevin Ballard above, I would go with:
println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!)
which will print out:
"NSDate"
"ImplicitlyUnwrappedOptional"
"Optional"
"NSDate"
"NSString"
"PureSwiftClass"
"Int"
"Double"
let i: Int = 20
func getTypeName(v: Any) -> String {
let fullName = _stdlib_demangleName(_stdlib_getTypeName(i))
if let range = fullName.rangeOfString(".") {
return fullName.substringFromIndex(range.endIndex)
}
return fullName
}
println("Var type is \(getTypeName(i)) = \(i)")
Swift 4:
// "TypeName"
func stringType(of some: Any) -> String {
let string = (some is Any.Type) ? String(describing: some) : String(describing: type(of: some))
return string
}
// "ModuleName.TypeName"
func fullStringType(of some: Any) -> String {
let string = (some is Any.Type) ? String(reflecting: some) : String(reflecting: type(of: some))
return string
}
Usage:
print(stringType(of: SomeClass())) // "SomeClass"
print(stringType(of: SomeClass.self)) // "SomeClass"
print(stringType(of: String())) // "String"
print(fullStringType(of: String())) // "Swift.String"
There appears to be no generic way to print the type name of an arbitrary value's type. As others have noted, for class instances you can print value.className but for primitive values it appears that at runtime, the type information is gone.
For instance, it looks as if there's not a way to type: 1.something() and get out Int for any value of something. (You can, as another answer suggested, use i.bridgeToObjectiveC().className to give you a hint, but __NSCFNumber is not actually the type of i -- just what it will be converted to when it crosses the boundary of an Objective-C function call.)
I would be happy to be proven wrong, but it looks like the type checking is all done at compile time, and like C++ (with RTTI disabled) much of the type information is gone at runtime.
This is how you get a type string of your object or Type which is consistent and takes into account to which module the object definition belongs to or nested in. Works in Swift 4.x.
#inline(__always) func typeString(for _type: Any.Type) -> String {
return String(reflecting: type(of: _type))
}
#inline(__always) func typeString(for object: Any) -> String {
return String(reflecting: type(of: type(of: object)))
}
struct Lol {
struct Kek {}
}
// if you run this in playground the results will be something like
typeString(for: Lol.self) // __lldb_expr_74.Lol.Type
typeString(for: Lol()) // __lldb_expr_74.Lol.Type
typeString(for: Lol.Kek.self)// __lldb_expr_74.Lol.Kek.Type
typeString(for: Lol.Kek()) // __lldb_expr_74.Lol.Kek.Type
Not exactly what you are after, but you can also check the type of the variable against Swift types like so:
let object: AnyObject = 1
if object is Int {
}
else if object is String {
}
For example.
Xcode 7.3.1, Swift 2.2:
String(instanceToPrint.self).componentsSeparatedByString(".").last

Swift how to "pass by value" of a object

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.

Turn a string into a variable

Hello I have a for in loop where elements is the variable being changed and in this case "elements" is a string but there is a corresponding variable out side of the for in loop that has the same name as the string called elements. So what I mean is out side there is a Var time = [some,text,words] and theres a for in loop that calls a STRING named "time" and I would like to know how to convert the string in the for in loop into the variable by some how taking off the "'s (not that simple I know) without specifically saying "time"(the variable) but instead converting the "elements"(which is the string 'time') string into the variable. I hope I was clear enough if I'm not making sense I'll try again.
You cannot refer to local variables dynamically by their names in Swift. This would break a lot of compiler optimizations as well as type safety if you could.
You can refer to object properties by their names if the class conforms to key-value coding. For example:
class X : NSObject {
let time = ["some", "text", "words"]
func readWordsFromProp(name: String) -> String {
guard let list = self.valueForKey(name) as? [String] else {
return ""
}
var result = ""
for word in list {
result += word
}
return result
}
}
let x = X()
print(x.readWordsFromProp("time"))
In general, there are better ways to do things in Swift using closures that don't rely on fragile name-matching. But KVC can be a very powerful tool

Resources