Done: No
DueDate: March 14, 2022
init은
미리 구현된 타입 메서드일까?→ 함수!
→INITIALIZERS ARE FUNCTIONS
func
이름
(....)
- >
return type
{ }
(....)
: parameter list
return의 역할
argument : 함수의 parameter에 넣는 값
신발상자(변수선언)에 이름 안 붙이고 싶을 때
_
@discardableResult
func signature(data : Int) -> Int {
///
}
//signature함수의 function signature는
// (Int) -> Int
()
혹은 Void
로 표시In Swift, function overloading is legal (and common).”
- 오버로딩이란?
- 이름이 같지만
signature
가 달라서(리턴타입
,parameter type
등으로 구분됨) 구분되는 함수가 되는 것 .- external parameter name(argument label)으로 구분되는 것은 overloading의 경우가 아닌 그저
다른
함수(메서드)가 되는 것이다.- method overloading 예시
```swift
func test(_ forwhat: Int) {
}
func test(_ forwhat: String) {
}
```
오버로딩 메소드들을 쓸 땐 타입추론에 기대지말고 직접 타입을 명시하는게 좋다. 또 그래야만 쓸 수 있는 경우도 있다.
func overloadingTestOne(_ data: String) {
print(data)
}
func overloadingTestOne(_ data: String) -> String {
return data
}
let test = overloadingTestOne(1)
//Constant 'test' inferred to have type '()',
// which may be unexpected
func testOfTest(_ forTest: String) {
}
let testOne = test("1")
let testOfTest = testOfTest(testOne)
assignment
뒤에 타입명시
as
이용해 타입 캐스팅 하여 타입을 명시
let test: String = overloadingTestOne(1)
let test = overloadingTestOne("1") as String
왜 써야하나유?
어떻게 구분되나유?
_
) 한다면 함수 호출 시 이름이 보이지 않는다.=
)이용해 기본값 선언func isMeGenius(answer: Bool = true) -> Bool {
//
}
func addALot(of fruits: Fruit ...) {
//
}
let addingFruit = addALot(Apple, Banana, Grape)
func ignore(_ data: Int) {
//
}
Swift
inout
키워드를 파라미터 타입 앞에 작성 ⇒ 함수 바디 내부로 파라미터 변수를 전달하지 않고 해당 파라미터(인자로 들어온 변수)의 address
를 전달하기 위해 &
키워드를 함수 호출 시 인자 앞에 추가함b. reference Type(Class) - 클래스는 그 자체로 mutable
하다
c. 구조체의 경우 인자로 들어가는 값을 변경해주싶다면 변수여야하며, 클래스는 let 이어도 상관없다.
Calling Objective-C with Modifiable Parameters
UnsafeMutablePointer
사용UIColor 의 호출 과정
func getRed(_ red: UnsafeMutablePointer<CGFloat>,
green: UnsafeMutablePointer<CGFloat>,
blue: UnsafeMutablePointer<CGFloat>,
alpha: UnsafeMutablePointer<CGFloat>) -> Bool {
// 빨간색으로 바꾸는 로직 구현
}
let c = UIColor.purple
var r : CGFloat = 0
var g : CGFloat = 0
var b : CGFloat = 0
var a : CGFloat = 0
c.getRed(&r, green: &g, blue: &b, alpha: &a)”
// now r, g, b, a are 0.5, 0.0, 0.5, 1.0
Calling Objective-C with Modifiable Parameters
이해안됨
func countDownFrom(_ ix:Int) {
print(ix)
if ix > 0 { // stopper
countDownFrom(ix - 1) // recurse!
}
}
countDownFrom(5) // 5, 4, 3, 2, 1, 0
“ In Swift, a function is a first-class citizen”
= 즉 함수를 Value로서 사용할 수 있다.
= paramter Value
(argument) 로서도 사용 가능한 이유
매게변수로 받으면 해당 함수가 뭔지 몰라도 호출할 수 있다.
typealias VoidVoidFunction = () -> ()
func dothis(_ f:VoidVoidFunction) {
f()
}
// f()가 뭔지 모르지만 dothis함수를 이용해 호출 가능
The Cocoa API is full of situations where you’ll pass a function to be called by the runtime in some special way or at some later time.
- ex : selector
//출처 : iOS14 Programming Fundamentals with Swift Chapter2
let para = NSMutableParagraphStyle()
para.headIndent = 10
para.firstLineHeadIndent = 10
// ... more configuration of para ...
content.addAttribute( // content is an NSMutableAttributedString”
.paragraphStyle, value:para, range:NSRange(location:0, length:1))
// refactoring
content.addAttribute(
.paragraphStyle,
**value: {
let para = NSMutableParagraphStyle()
para.headIndent = 10
para.firstLineHeadIndent = 10
// ... more configuration of para ...
return para
}()**,“range:NSRange(location:0, length:1))”
Closure
클로저 = 바디에서 사용하는 변수 등의 reference를 캡쳐한다.
= "see” variables and functions declared in a surrounding scope
= a function is a closure and that it captures external variables referred to in its body
//출처 : iOS14 Programming Fundamentals with Swift Chapter2
func imageOfSize(_ size: CGSize, _ whatToDraw: () -> ()) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false, 0)
whatToDraw()
let result = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return result
}
let image = imageOfSize(CGSize(width: 45, height: 20)) {
let p = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 45, height: 20), cornerRadius: 8)
p.stroke()
}
//MARK:- firstRefactor
let sz = CGSize(width: 45, height: 20)
let firstRefactoredImage = imageOfSize(sz) {
let p = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: sz), cornerRadius: 8)
p.stroke()
}
//MARK:- SecondRefactor
func makeRoundedRectangle(_ sz: CGSize) -> UIImage {
let image = imageOfSize(sz) {
let p = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: sz), cornerRadius: 8)
p.stroke()
}
return image
}
//MARK:- Usage
UIImageView(image: UIImage(named: "cat")).image
= makeRoundedRectangle(CGSize(width: 45, height: 45))
//출처 : iOS14 Programming Fundamentals with Swift Chapter2
//MARK:- Functions returing funtion
func makeRoudnedRectangleMaker(_ sz: CGSize) -> () -> UIImage {
func maker() -> UIImage {
let image = imageOfSize(sz) {
let path = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: sz), cornerRadius: 8)
path.stroke()
}
return image
}
return maker
}
let maker = makeRoudnedRectangleMaker(CGSize(width:45, height: 20))
UIImageView(image: UIImage(named: "cat")).image = maker()
//“makeRoundedRectangleMaker is a factory for creating a whole family of functions similar to maker, each of which produces an image of one particular size. That’s a dramatic illustration of the power of closures.”
//MARK: 클로저 캡쳐 이용해 리팩토링
func “makeRoundedRectangleMakerTwo(_ sz: CGSize) -> () -> UIImage {
func any() -> UIImage {
return imageOfSize(sz) {
let p = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: sz), cornerRadius: 8)
p.stroke()
}
}
return any
}
func “makeRoundedRectangleMakerThree(_ sz: CGSize) -> () -> UIImage {
func any() -> UIImage {
return {
return imageOfSize(sz) {
let p = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: sz), cornerRadius: 8)
p.stroke()
}
}
}
}
클로저는 주변 환경을 캡쳐
할 수 있다.
//출처 : iOS14 Programming Fundamentals with Swift Chapter2
func countAdder(_ f: @escaping () -> ()) -> () -> () {
var ct = 0
return {
ct = ct + 1
print("count is \(ct)")
f()
}
}
func greet() {
print("하이")
}
let countedGreet = countAdder(greet)
countedGreet()
countedGreet()
Secondary feature of escaping closures is that, when you refer to a property or method of self within the function body, the compiler may insist that you say self explicitly. That’s because such a reference captures self, and the compiler wants you to acknowledge this fact by saying self:
//출처 : iOS14 Programming Fundamentals with Swift Chapter2
func makeRoundedRectangleMakerThree(_ sz: CGSize) -> ((CGFloat) -> UIImage) {
return { r in
imageOfSize(sz) {
let p = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: sz), cornerRadius: r)
p.stroke()
}
}
}
//일반적으로 쓸 때
let maker2 = makeRoundedRectangleMakerThree(CGSize(width:45, height:20))
maker2(8)
//curreid Function
makeRoundedRectangleMakerThree(CGSize(width:45, height:20))(8)
함수를 호출하지 않고 reference만 가지고 오는게 가능하다
func test() {
print("test")
}
let a = test // () -> () 타입의 객체가 됨
method overloaded일 땐 signature
를 명시해라
//출처 : iOS14 Programming Fundamentals with Swift Chapter2
class Dog {
func bark() { }
func bark(_ loudly: Bool) { }
func bark(_ times: Int) { }
func test() {
let barkFunction = bark(_:) **as (Int) -> ()**
}
}
함수의 Reference만 가지고 오고 싶을 땐 인스턴스로 안가져와도 됨.
//출처 : iOS14 Programming Fundamentals with Swift Chapter2
class Dog {
func bark() { }
}
class Cat {
func purr() {}
func test() {
let c = Dog.bark
}
}
Curried function
curried static/class version
를 명확히 해야한다. “If you use the type with dot-notation and you need to disambiguate the function reference by giving its signature, the signature must describe the curried static/class version of the instance method (see “The Secret Life of Instance Methods”):”//2.
class Cat {
func purr() {
}
func purr(_ loudly:Bool) {
}
}
class Dog {
func test() {
let purrFunction = Cat.purr as (Cat) -> () -> Void
}
}
selector
가 메소드의 reference
처럼 사용됨selector
추가하는게 있는 걸 볼 수 있음unrecognized crash
" 발생 위험 높음⇒ 그래서 제공하는게 #selector
키워드
//출처 : iOS14 Programming Fundamentals with Swift Chapter2
class ViewController : UIViewController {
@IBOutlet var button : UIButton!
func viewDidLoad() {
super.viewDidLoad()
self.button.addTarget(
// #selector 문법 사용
self, action: #selector(buttonPressed), for: .touchUpInside)
// #selector 문법 사용하지 않는 경우
self.button.addTarget(self, action: buttonPressed:, for: .touchUpInside)
}
@objc func buttonPressed(_ sender: Any) {
// ...
}
}
♦️addTarget( 해당객체가선언된객체
, action: 무엇을실행할것인가
, for: 어떤이벤트가발생했을때인가
)
함수를 매게변수로 받을 수 있다. 더 나아가 함수를 만드는 함수
를 만들 수 있다. 클로저 잘 이용해 보자
//출처 : iOS14 Programming Fundamentals with Swift Chapter2
//MARK:- Functions returing funtion
func makeRoudnedRectangleMaker(_ sz: CGSize) -> () -> UIImage {
func maker() -> UIImage {
let image = imageOfSize(sz) {
let path = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: sz), cornerRadius: 8)
path.stroke()
}
return image
}
return maker
}
let maker = makeRoudnedRectangleMaker(CGSize(width:45, height: 20))
UIImageView(image: UIImage(named: "cat")).image = maker()
//“makeRoundedRectangleMaker is a factory for creating a whole family of functions similar to maker, each of which produces an image of one particular size. That’s a dramatic illustration of the power of closures.”
//MARK: 클로저 캡쳐 이용해 리팩토링
func “makeRoundedRectangleMakerTwo(_ sz: CGSize) -> () -> UIImage {
func any() -> UIImage {
return imageOfSize(sz) {
let p = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: sz), cornerRadius: 8)
p.stroke()
}
}
return any
}
func “makeRoundedRectangleMakerThree(_ sz: CGSize) -> () -> UIImage {
func any() -> UIImage {
return {
return imageOfSize(sz) {
let p = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: sz), cornerRadius: 8)
p.stroke()
}
}
}
}