+ (void)mySimpleMethod { // "" // // } - (NSString *)myMethodNameWithParameter1:(NSString *)param1 parameter2:(NSNumber *)param2 { // "" // - NSString , // - NSNumber // NSString return @"hello, world!"; }
Methods are functions that are associated with a particular “type”. Classes, structures, and enumerations can define “instance” methods that encapsulate specific works and functionality for working with an “instance” of a given “type”. Classes, structures, and enumerations can also define methods for “type” that are associated with “type” as such. “Type” methods are similar to “class” methods in Objective-C.
class, struct
or enum
. func mySimpleFunction() { println("hello, world!") }
func
keyword is a function.mySimpleFunction
. func myFunctionName(param1: String, param2: Int) -> String { return "hello, world!" }
param1
type String
and another parameter named param2
type Int
and returns a value of type String
. func hello(name: String) { println("hello \(name)") } hello("Mr. Roboto")
func hello(name: String, age: Int, location: String) { println("Hello \(name). I live in \(location) too. When is your \(age + 1)th birthday?") } hello("Mr. Roboto", 5, "San Francisco")
hello("Mr. Roboto", 5, "San Francisco")
, you will need to know what the parameter means. func hello(name name: String) { println("hello \(name)") } hello(name: "Robot")
func hello(#name: String) { println("hello \(name)") } hello(name: "Robot")
class
(or struct
, or enum
), the name of the first parameter of the method is not included as external , while all subsequent parameter names are included as external when the method is called: class MyFunClass { func hello(name: String, age: Int, location: String) { println("Hello \(name). I live in \(location) too. When is your \(age + 1)th birthday?") } } let myFunClass = MyFunClass() myFunClass.hello("Mr. Roboto", age: 5, location: "San Francisco")
class MyFunClass { func helloWithName(name: String, age: Int, location: String) { println("Hello \(name). I live in \(location) too. When is your \(age + 1)th birthday?") } } let myFunClass = MyFunClass() myFunClass.helloWithName("Mr. Roboto", age: 5, location: "San Francisco")
“hello”
function, I renamed it helloWithName
to make the name of the first parameter of the method more understandable. class MyFunClass { func helloWithName(name: String, _ age: Int, _ location: String) { println("Hello \(name). I live in \(location) too. When is your \(age + 1)th birthday?") } } let myFunClass = MyFunClass() myFunClass.helloWithName("Mr. Roboto", 5, "San Francisco")
The basic idea of currying is that the function can be partially applied, which means that some of the parameter values can be defined before the function is called. Partial function application produces a new function.
class MyHelloWorldClass { func helloWithName(name: String) -> String { return "hello, \(name)" } }
helloWithName
class: let helloWithNameFunc = MyHelloWorldClass.helloWithName // MyHelloWorldClass -> (String) -> String
helloWithNameFunc
function is a function of type MyHelloWorldClass -> (String) -> Sting
, which takes an “instance” of my class and returns another function, which in turn takes a string value and returns a string value. let myHelloWorldClassInstance = MyHelloWorldClass() helloWithNameFunc(myHelloWorldClassInstance)("Mr. Roboto") // hello, Mr. Roboto
Init
: Special Notesinit
method is called when the class, struct
, or enum
is initialized. In Swift , you can define initialization parameters, like any other method: class Person { init(name: String) { // init } } Person(name: "Mr. Roboto")
init
method always requires an external name when obtaining an instance of a class.fromName
— to make getting an instance of the class more readable: class Person { init(fromName name: String) { // your init implementation } } Person(fromName: "Mr. Roboto")
init
method to skip the external name of the parameter. I like the readability and power of the following initialization example from the book Swift Programming Language : struct Celsius { var temperatureInCelsius: Double init(fromFahrenheit fahrenheit: Double) { temperatureInCelsius = (fahrenheit - 32.0) / 1.8 } init(fromKelvin kelvin: Double) { temperatureInCelsius = kelvin - 273.15 } init(_ celsius: Double) { temperatureInCelsius = celsius } } let boilingPointOfWater = Celsius(fromFahrenheit: 212.0) // boilingPointOfWater.temperatureInCelsius is 100.0 let freezingPointOfWater = Celsius(fromKelvin: 273.15) // freezingPointOfWater.temperatureInCelsius is 0.0 let bodyTemperature = Celsius(37.0) // bodyTemperature.temperatureInCelsius is 37.0
class / enum / struct
initialized. I really like using David Owen’s json-swift library: public struct JSValue : Equatable { // ... /// `JSValue` `JSArrayType` . public init(_ value: JSArrayType) { self.value = JSBackingValue.JSArray(value) } /// `JSValue` `JSObjectType` . public init(_ value: JSObjectType) { self.value = JSBackingValue.JSObject(value) } /// `JSValue` `JSStringType` . public init(_ value: JSStringType) { self.value = JSBackingValue.JSString(value) } /// `JSValue` `JSNumberType` . public init(_ value: JSNumberType) { self.value = JSBackingValue.JSNumber(value) } /// `JSValue` `JSBoolType` . public init(_ value: JSBoolType) { self.value = JSBackingValue.JSBool(value) } /// `JSValue` `Error` . init(_ error: Error) { self.value = JSBackingValue.Invalid(error) } /// `JSValue` `JSBackingValue` . init(_ value: JSBackingValue) { self.value = value } }
Optional
:Optionals say that either “this value and it is equal to x”, or “there is no value at all.” Optionals are similar to using nil with pointers in Objective-C, but they work for any type, not just for classes. Optionals are safer and more expressive than nil pointers in Objective-C, and they are the center of many powerful features of Swift.
Optional
(i.e., maybe nil
), just add a question mark? Following type specification: func myFuncWithOptionalType(parameter: String?) { // function execution } myFuncWithOptionalType("someString") myFuncWithOptionalType(nil)
Optionals
, do not forget to "deploy" it! func myFuncWithOptionalType(optionalParameter: String?) { if let unwrappedOptional = optionalParameter { println("The optional has a value! It's \(unwrappedOptional)") } else { println("The optional is nil!") } } myFuncWithOptionalType("someString") // The optional has a value! It's someString myFuncWithOptionalType(nil) // The optional is nil
Optionals
!Default
Values func hello(name: String = "you") { println("hello, \(name)") } hello(name: "Mr. Roboto") // hello, Mr. Roboto hello() // hello, you
default
value can be skipped when calling a function, it is good practice to place all parameters with default
values at the end of the parameter list. Here is a quote from the book "Swift Programming Language" on this topic:Place the parameters with default values at the end of the function parameter list. This ensures that all function calls use the same order of parameters for their non default arguments. Therefore, in all cases the same function is called.
default
parameters, mainly because it makes it easy to change code and provide backward compatibility. You can, for example, start with two parameters that you need at the moment, for example, to configure a custom “table cell” UITableViewCell
, and if you need additional configuration when another parameter is needed (for example, a different color for your text label cells), then you simply add a new parameter with a default value - and all other places where this function has already been called can be left unchanged, and you can send a pair to a new part of your code that requires a new parameter. empl with a value other than the default values!Variadic
parameters are simply a more readable version of the transmission of an array of elements. In fact, if you look at the type of the internal parameter name
in the example below, you will see that it is of the type [String]: func helloWithNames(names: String...) { for name in names { println("Hello, \(name)") } } // 2 names helloWithNames("Mr. Robot", "Mr. Potato") // Hello, Mr. Robot // Hello, Mr. Potato // 4 names helloWithNames("Batman", "Superman", "Wonder Woman", "Catwoman") // Hello, Batman // Hello, Superman // Hello, Wonder Woman // Hello, Catwoman
func helloWithNames(names: String...) { if names.count > 0 { for name in names { println("Hello, \(name)") } } else { println("Nobody here!") } } helloWithNames() // Nobody here!
variadic
parameters: the variadic
parameter should be the last parameter in your parameter list!inout
parameters we get the ability to manipulate external variables passed by reference: var name1 = "Mr. Potato" var name2 = "Mr. Roboto" func nameSwap(inout name1: String, inout name2: String) { let oldName1 = name1 name1 = name2 name2 = oldName1 } nameSwap(&name1, &name2) name1 // Mr. Roboto name2 // Mr. Potato
NSJSONSerialization
is one such example: - (void)parseJSONData:(NSData *)jsonData { NSError *error = nil; id jsonResult = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error]; if (!jsonResult) { NSLog(@"ERROR: %@", error.description); } }
inout
parameters! Take a look at Swift's David Owen recent blog post about error handling . A lot of material on this topic in the book "Functional Programming in Swift" . func valueSwap<T>(inout value1: T, inout value2: T) { let oldValue1 = value1 value1 = value2 value2 = oldValue1 } var name1 = "Mr. Potato" var name2 = "Mr. Roboto" valueSwap(&name1, &name2) name1 // Mr. Roboto name2 // Mr. Potato var number1 = 2 var number2 = 5 valueSwap(&number1, &number2) number1 // 5 number2 // 2
generics
, I recommend taking a look at the “Generics” section in the Apple book, Swift Programming Language. var name = "Mr. Roboto" func appendNumbersToName(var name: String, #maxNumber: Int) -> String { for i in 0..<maxNumber { name += String(i + 1) } return name } appendNumbersToName(name, maxNumber:5) // Mr. Robot12345 name // Mr. Roboto
inout
parameter — the variable parameters do not change the externally passed variable! func luckyNumberForName(name: String, #lotteryHandler: (String, Int) -> String) -> String { let luckyNumber = Int(arc4random() % 100) return lotteryHandler(name, luckyNumber) } func defaultLotteryHandler(name: String, luckyNumber: Int) -> String { return "\(name), your lucky number is \(luckyNumber)" } luckyNumberForName("Mr. Roboto", lotteryHandler: defaultLotteryHandler) // Mr. Roboto, your lucky number is 38
defaultLotteryHandler
function. The function is executed later when the function that the parameter is passed to decides. func luckyNumberForName(name: String, #lotteryHandler: (String, Int) -> String) -> String { let luckyNumber = Int(arc4random() % 100) return lotteryHandler(name, luckyNumber) } class FunLottery { func defaultLotteryHandler(name: String, luckyNumber: Int) -> String { return "\(name), your lucky number is \(luckyNumber)" } } let funLottery = FunLottery() luckyNumberForName("Mr. Roboto", lotteryHandler: funLottery.defaultLotteryHandler) // Mr. Roboto, your lucky number is 38
typedef
in Objective-C ): typealias lotteryOutputHandler = (String, Int) -> String func luckyNumberForName(name: String, #lotteryHandler: lotteryOutputHandler) -> String { let luckyNumber = Int(arc4random() % 100) return lotteryHandler(name, luckyNumber) }
func luckyNumberForName(name: String, #lotteryHandler: (String, Int) -> String) -> String { let luckyNumber = Int(arc4random() % 100) return lotteryHandler(name, luckyNumber) } luckyNumberForName("Mr. Roboto", lotteryHandler: {name, number in return "\(name)'s' lucky number is \(number)" }) // Mr. Roboto's lucky number is 74
completion handler
management and error handler
in methods with asynchronous operations. It will also be popular in Swift . public func myPublicFunc() { } func myInternalFunc() { } private func myPrivateFunc() { } private func myOtherPrivateFunc() { }
class MyFunClass { func myInternalFunc() { } // MARK: Private Helper Methods private func myPrivateFunc() { } private func myOtherPrivateFunc() { } }
Optionals
and multiple return types.nil
, you need to define the return type as Optional
: func myFuncWithOptonalReturnType() -> String? { let someNumber = arc4random() % 100 if someNumber > 50 { return "someString" } else { return nil } } myFuncWithOptonalReturnType()
Optional
return value, then do not forget to "expand" it: let optionalString = myFuncWithOptonalReturnType() if let someString = optionalString { println("The function returned a value: \(someString)") } else { println("The function returned nil") }
I finally got the @SwiftLang optionals that resemble Schrödinger 's cat ! You should see if the cat is alive before you use it.
func findRangeFromNumbers(numbers: Int...) -> (min: Int, max: Int) { var min = numbers[0] var max = numbers[0] for number in numbers { if number > max { max = number } if number < min { min = number } } return (min, max) } findRangeFromNumbers(1, 234, 555, 345, 423) // (1, 555)
let range = findRangeFromNumbers(1, 234, 555, 345, 423) println("From numbers: 1, 234, 555, 345, 423. The min is \(range.min). The max is \(range.max).") // From numbers: 1, 234, 555, 345, 423. The min is 1. The max is 555. let (min, max) = findRangeFromNumbers(236, 8, 38, 937, 328) println("From numbers: 236, 8, 38, 937, 328. The min is \(min). The max is \(max)") // From numbers: 236, 8, 38, 937, 328. The min is 8. The max is 937
Optional
, but there are two ways to control this situation. func findRangeFromNumbers(numbers: Int...) -> (min: Int, max: Int)? { if numbers.count > 0 { var min = numbers[0] var max = numbers[0] for number in numbers { if number > max { max = number } if number < min { min = number } } return (min, max) } else { return nil } } if let range = findRangeFromNumbers() { println("Max: \(range.max). Min: \(range.min)") } else { println("No numbers!") } // No numbers!
Optional
, , Optional
: func componentsFromUrlString(urlString: String) -> (host: String?, path: String?) { let url = NSURL(string: urlString) return (url.host, url.path) }
Optional
, «», Optional
: let urlComponents = componentsFromUrlString("http://name.com/12345;param?foo=1&baa=2#fragment") switch (urlComponents.host, urlComponents.path) { case let (.Some(host), .Some(path)): println("This url consists of host \(host) and path \(path)") case let (.Some(host), .None): println("This url only has a host \(host)") case let (.None, .Some(path)): println("This url only has path \(path). Make sure to add a host!") case let (.None, .None): println("This is not a url!") } // This url consists of host name.com and path /12345
func myFuncThatReturnsAFunc() -> (Int) -> String { return { number in return "The lucky number is \(number)" } } let returnedFunction = myFuncThatReturnsAFunc() returnedFunction(5) // The lucky number is 5
typealias returnedFunctionType = (Int) -> String func myFuncThatReturnsAFunc() -> returnedFunctionType { return { number in return "The lucky number is \(number)" } } let returnedFunction = myFuncThatReturnsAFunc() returnedFunction(5) // The lucky number is 5
func myFunctionWithNumber(someNumber: Int) { func increment(var someNumber: Int) -> Int { return someNumber + 10 } let incrementedNumber = increment(someNumber) println("The incremented number is \(incrementedNumber)") } myFunctionWithNumber(5) // The incremented number is 15
Source: https://habr.com/ru/post/244487/
All Articles