목록iOS (53)
develop
KVC는 Key-Value Coding의 약자이다. Swift3에서는 #keyPath()로 키패스를 가져왔지만 Swift4에서는 \만 적어주면 키패스를 가져올수 있게 되었다. class Example: NSObject { var value: String = "" } print(\Example.value) Swift.ReferenceWritableKeyPath 수정도 간단하다. class Example: NSObject { var value: String = "HI" } let example = Example() print(example[keyPath: \Example.value]) example[keyPath: \Example.value] = "HELLO" print(example[keyPath: \Ex..
== 는 비교 연산자로 많이 사용이 되고 인스턴스의 값이 같은지 비교를 한다. 비교 연산자에서 =을 하나 더 붙인 === 연산자가 있는데 이 연산자는 인스턴스의 참조가 같은지 즉, 주소값이 같은지 비교를 한다. class Example { var value: Int? } let example1 = Example() let example2 = Example() let example3 = example1 print("example1 === example2: \(example1 === example2)") print("example1 === example3: \(example1 === example3)") example1 === example2: false example1 === example3: true e..
struct나 protocol 확장 에서 self 변수를 참조해 수정하려면 mutating을 써야 한다. protocol ExampleProtocol { var value: Int? { set get } } extension ExampleProtocol { mutating func exampleFunc() { self.value = 5 } } struct Example1 { var value: Int? mutating func exampleFunc() { self.value = 5 } } struct에서 변수의 값이 변경되면 struct 전체가 복사되고 주소값이 변경이 된다. 값이 변경될 때 struct가 복사되는 이유는 swift가 함수형 언어이고 불변성이 중요한 요소라서 전체가 복사가 되고 주소값이 ..
class Example1 { var value: Int? required init(value: Int?) { self.value = value } } Required를 init앞에 붙이면 필수로 init을 상속받은 곳에서 구현해야 한다. 그리고 반드시 override되어 야 하므로 override를 붙이지 않고 required를 붙여준다. class Example2: Example1 { required init(value: Int?) { super.init(value: value) } } protocol에서 init를 사용하면 자동으로 required가 된다. protocol ExampleProtocol { init() } class Example: ExampleProtocol { required in..
convenience init은 편의 생성자라고 하는데 convenience init을 사용하면 같은 클래스에 있는 다른 init를 호출해야 한다는 규칙이 있다. class Example1 { var value1: Int? var value2: Int? init(value1: Int?, value2: Int?) { self.value1 = value1 self.value2 = value2 } convenience init(value1: Int?) { self.init(value1: value1, value2: 5) } } let example = Example1(value1: 3) 나는 convenience init을 확장에서 자주 사용한다. extension UITextField { convenienc..
class나 struct에서 비교연산자를 사용하면 struct Example1 { var value: Int? } let structExample1 = Example1() let structExample2 = Example1() if structExample1 == structExample2 { } class Example2 { var value: Int? } let classExample1 = Example2() let classExample2 = Example2() if classExample1 == classExample2 { } error: binary operator '==' cannot be applied to two 'Example1' operands 라는 에러가 난다. 하지만 struct나..

struct Example1 { var value: Int? } let example1 = Example1(value: 10) 따로 init를 만들지 않았는데 자동으로 이니셜라이즈가 생긴다. 하지만 클래스에서는 init이 자동으로 생기지 않고 직접 만들어 줘야 한다. class Example2 { var value: Int? } let example2 = Example2()

반복적으로 메모리를 많이 차지하는 로직을 사용할때 메모리가 해제되지 않고 앱이 죽어버리는 경우가 있다. 메모리를 해제할 시간을 주지않고 계속 메모리를 사용을 해서 생기는 문제이다. 메모리가 한계까지 올라가면서 앱이 죽는다. 이런 경우에 autoreleasepool을 사용하게 되면 특정 로직을 실행하기 전에 임시오토릴리즈풀이 만들어지고 블럭을 빠져나간 뒤에 임시오토릴리즈풀은 비워지게 되면서 메모리 사용량이 다시 줄어들게 된다. 오토릴리즈풀 함수 안에서 만약 i가 10보다 클 때 for문을 나가려면 어떻게 해야할까? 오토릴리즈풀 블럭 안에서는 return이 되지 않는다. break 는 컴파일에러가 난다. autoreleasepool 함수 안에서 리턴값으로 Result를 받는다. autoreleasepool ..
iOS 앱에서 App LifeCycle이 applicationDidEnterBackground가 되면 로직이 실행이 되지 않는다. 대용량 파일을 다운로드, 업로드할때 앱화면에서 배경화면으로 들어갔을떄 다운로드, 업로드가 중단되어진다. 사용자들은 다운로드, 업로드할때 계속 앱을 열어야 하지만 BackgroundFetch기능으로 applicationDidEnterBackground가 되어도 로직이 계속 실행되게 할 수 있다. BackgroundTask 상태를 알려준다. var backgroundTaskIdentifier = UIBackgroundTaskIdentifier.invalid UIBackgroundTaskIdentifier는 이렇게 구현되어 있다. public struct UIBackgroundTa..
MemoryCache 메모리 캐시는 NSCache를 사용하여 캐시를 관리한다. 메모리를 사용하기 때문에 앱의 메모리가 커지면 캐시가 삭제될 수 있다. Swift에서는 NSCache라는 클래스가 있다. https://developer.apple.com/documentation/foundation/nscache Apple Developer Documentation developer.apple.com class NSCache : NSObject where KeyType : AnyObject, ObjectType : AnyObject Key와 Value를 Generic으로 구현되어 있다. 사용 방법은 let cache = NSCache() SET cache.setObject(UIImage(), forKey: "..
유연하게 작성할 수 있고 추상적으로 코드를 작성할 수 있다. 하나의 타입만 생각하고 코드를 만드는 것이 아니라 타입에 관계 없이 코드를 만들어서 사용한다. 1. Functions func swapValues(_ lhs: inout T, _ rhs: inout T) { let temp = lhs lhs = rhs rhs = temp } var intA = 10 var intB = 20 swapValues(&intA, &intB) print(intA) print(intB) var str1 = "str1" var str2 = "str2" swapValues(&str1, &str2) print(str1) print(str2) 20 10 str2 str1 2. Struct, Class struct Example ..

함수를 일정 시간 이후에 실행할 수 있게 해준다. 예를 들어 UITextField에서 텍스트를 입력할 때마다 입력된 텍스트를 받게 되면 큰 비용이 일어나게 된다. 이 문제를 해결하려면 텍스트를 입력한 다음 일정 시간 동안 다음 텍스트를 입력 받지 못하면 이벤트가 일어나고 일정 시간 안에 텍스트를 입력 받으면 다시 다음 일정 시간을 기다리게 한다. 이 방법으로 큰 비용이 발생되지 않는다. Debounce 입력이 될 때마다 일정 시간을 다시 기다린다. 위의 라인이 이벤트 발생이고 아래 라인이 이벤트가 호출되는 시점이다. 위의 1번 이벤트를 발생시키고 일정 시간 동안 이벤트 발생이 없어서 1번이 호출되었다. 위의 2번 이벤트를 발생시키고 일정 시간이 지나기 전에 3번, 4, 5, 6, 7번 이벤트를 발생 시켰..
@objc Swift에서 objc 라는 키워드는 심볼을 Objective-C 네임스페이스에 알려주는 역활이다. Objective-C에서 Swift를 찾을수 없게 되어 있는데 찾을수 있게 해주는 것이 objc 키워드 이다. Selector self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(self.doneTap(_:))) private func doneTap(_ sender: UIBarButtonItem) { } 이렇게 적으면 Argument of '#selector' refers to instance method 'doneTap' that is n..
어떤 작업의 동기화를 그룹으로 묶을수 있다. 여러 작업들이 각각의 큐에서 동작하고 모든 작업이 완료 되었을 때를 알수 있다. let workGroup = DispatchGroup() workGroup.enter() print("work1 start") DispatchQueue.global().asyncAfter(deadline: .now() + 0.5) { print("work1 end") workGroup.leave() } workGroup.enter() print("work2 start") DispatchQueue.global().asyncAfter(deadline: .now() + 1) { print("work2 end") workGroup.leave() } workGroup.notify(queue..