목록iOS (53)
develop
반복적으로 메모리를 많이 차지하는 로직을 사용할때 메모리가 해제되지 않고 앱이 죽어버리는 경우가 있다. 메모리를 해제할 시간을 주지않고 계속 메모리를 사용을 해서 생기는 문제이다. 이런 경우에 autoreleasepool을 사용하게 되면 특정 로직을 실행하기 전에 임시오토릴리즈풀이 만들어지고 블럭을 빠져나간 뒤에 임시오토릴리즈풀은 비워지게 되면서 메모리 사용량이 다시 줄어들게 된다. 오토릴리즈풀 블럭 안에서는 return이 되지 않는다. break 는 컴파일에러가 난다. autoreleasepool 함수 안에서 리턴값으로 Result를 받는다. autoreleasepool 함수는 Result를 리턴해준다.
ARC 프로퍼티, 상수, 변수등을 참조하면 레퍼런스가 카운트가 올라가고 참조가 끝나면 레퍼런스 카운터가 내려가고 레퍼런스 카운터가 0이되면 메모리에서 해제한다. 자동 레퍼런트 카운터는 더 이상 사용되지 않는 시점을 결정하여 메모리를 해제한다. 그리고 ARC는 compile time에 코드 분석을 통해 적절한 위치에 retain, release 등의 코드를 삽입해 주고 삽입된 코드는 run time에 실행이 된다 옛날 MRC는 개발자가 직접 리테인과 릴리즈를 해줘야 했고 retain, release를 통해 referenceCount를 증감시키다가 count 가 0이 되면 deinit 을 통해 해제를 하였다. 이러한 작업을 ARC는 자동으로 해준다. 순환참조 메모리가 제대로 해지되지 않는 경우가 있고 순환참..
뷰에 label이 가로로 2개 있다고 가정하고 label의 텍스트가 고정되지 않고 leftLabel은 좌측, 상단에 오토레이아웃이 잡혀있고 rightLabel은 우측, 상단에 오토레이아웃이 잡혀있고 leftLabel의 좌측과 rightLabel의 우측에 오토레이아웃이 연결되어 있다고 가정했을때 let leftLabel = UILabel() leftLabel.translatesAutoresizingMaskIntoConstraints = false view.addSubview(leftLabel) leftLabel.text = "left label" let rightLabel = UILabel() rightLabel.translatesAutoresizingMaskIntoConstraints = false vi..
frame과 bounds의 차이는 1. frame은 x, y가 super 뷰 기준의 좌표계로 설정되고 bounds는 x, y좌표가 자기 자신 기준의 좌표계로 설정된다. let testView = UIView(frame: CGRect(x: 0, y: 100, width: 80, height: 80)) testView.backgroundColor = .blue view.addSubview(testView) print("frame: \(testView.frame)") print("bounds: \(testView.bounds)") frame: (0.0, 100.0, 80.0, 80.0) bounds: (0.0, 0.0, 80.0, 80.0) 2. frame을 변경하게 되면 자기 자신의 좌표가 이동된다. bou..
https://developer.apple.com/documentation/swift/hashable Apple Developer Documentation developer.apple.com 정수 해시 값을 생성하기 위해 Hasher로 해시 할 수있는 유형 Hashable과 Hasher는 아래와 같이 생겼다. Hash를 어떻게 사용하냐면 Dictionary나 Set의 Key값을 사용할때 Hashble을 준수하는 타입만 사용할 수 있다. 기본타입인 String, Int, enum(associated value 없는 enum은 Hashable 을 자동으로 준수) 등은 해시가 가능한 타입이라 Dictionary나 Set의 Key값에 사용할수 있다. 예를 들어 Dictionary의 Key값으로 class를 넣는..
==(Equivalence Operators 같음 비교 연산자) 는 일반적으로 값을 비교한다. https://developer.apple.com/documentation/swift/equatable/1539854 Apple Developer Documentation developer.apple.com let first: Int = 1 let second: Int = 2 print(first == second) class에서 ==을 하려면 Equatable을 채택하여야 한다. class에서 기본적으로 NSObject를 자주 상속받는데 NSObject는 Equatable을 채택하고 있다. ===(Identity Operators 식별연산자) 는 값을 비교하는게 아니라 참조값을 비교를 한다. https://d..
srt파일이나 smi파일안에 한글이 있다면 아래와 같이 한글이 깨져서 나오게 된다. let urlPath = "https://pikachu987.github.io/ProjectData/Playground/exampleSrt1.srt" guard let url = URL(string: urlPath) else { return } guard let data = try? Data(contentsOf: url) else { return } guard let attributed = try? NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil) else {..
Reorder기능은 셀을 터치한 다음 드래그로 셀의 위치를 바꾸는 기능이다. UITableView Reorder let tableView: UITableView = { let tableView = UITableView() return tableView }() var array: [UIColor] = [.blue, .red, .brown, .black, .green, .gray, .cyan, .orange, .darkGray, .lightGray, .link, .magenta, .purple, .yellow] override func viewDidLoad() { super.viewDidLoad() self.view.addSubview(self.tableView) self.tableView.frame = s..
GCD(GrandCentralDispatch) 구현이 아주 간단하고 대부분 GCD 방식으로 사용하고 있다. 2021/01/18 - [iOS] - DispatchGroup 으로 GCD로 만든 것들을 그룹화 할 수도 있다. GCD는 Main큐와 Global큐가 시스템으로 만들어져 있다. 그리고 Queue를 직접 만들수 있다. DispatchQueue.main.async { print("main Queue isMainThread: \(Thread.isMainThread)") } DispatchQueue.global().async { print("global Queue isMainThread: \(Thread.isMainThread)") } let queue = DispatchQueue(label: "Custo..
작업 큐라는 방식이고 병렬프로그래밍을 하기위한 개념이다. 큐에 작업들을 넣으면 알아서 별도의 Thread에서 실행시켜 준다. let queue = OperationQueue() queue.addOperation { (0...3).forEach({ print("queue1: \($0)") }) } let operation = Operation() operation.completionBlock = { () in (0...3).forEach({ print("queue2: \($0)") }) } queue.addOperation(operation) queue1: 0 queue2: 0 queue2: 1 queue1: 1 queue2: 2 queue1: 2 queue2: 3 queue1: 3 간단하게는 Operat..
모든 언어에서 일반적으로 사용되는 병렬프로그래밍 기술인 멀티스레드 하지만 아래의 다른 병렬프로그래밍 기술보다 사용하기가 까다롭고 비효율적이다. Thread에는 Selector을 사용할수 있는 생성자와 block구문을 이용한 생성자가 있다. @available(iOS 2.0, *) public convenience init(target: Any, selector: Selector, object argument: Any?) @available(iOS 10.0, *) public convenience init(block: @escaping () -> Void) Selector을 사용하는 방법이다. override func viewDidLoad() { let thread1 = Thread(target: self..
let workItem = DispatchWorkItem { print("work Item") } workItem.perform() work Item 생성자에 block을 넣는다. perform 메서드로 block를 실행한다. let workItem = DispatchWorkItem { print("work Item") } workItem.notify(queue: DispatchQueue.main) { print("notify") } workItem.perform() work Item notify workItem이 끝나면 notify로 알림을 받을수 있다. let workItem = DispatchWorkItem { print("work Item") } let completeWorkItem = Dispa..
let example = [1,2,3,4,5,6].filter { (value) -> Bool in print("filter: \(value)") return value % 2 == 0 } let example1 = [1,2,3,4,5,6].lazy.filter { (value) -> Bool in print("lazy filter: \(value)") return value % 2 == 0 } filter: 1 filter: 2 filter: 3 filter: 4 filter: 5 filter: 6 lazy를 사용하지 않은 example은 filter가 동작이 된다. lazy를 사용한 example1는 lazy의 뜻에 알맞게 동작이 되지 않는다. let example = [1,2,3,4,5,6].fil..
저장 프로퍼티(Stored Property) struct Example { var value: String } 지연 프로퍼티(Lazy Property) struct Example { lazy var value: String = "" } let example = Example() value에 접근하기 전까지 value는 메모리에 올라가지 않는다. lazy는 let이 될수 없다. let으로 선언된 변수는 초기에 값이 있어야 하는데 lazy는 초기에 값이 존재하지 않고 접근시 값이 생기는 것이라 let을 사용할 수 없다. 만약 변수가 클로저로 되어서 스스로를 참조하면 캡쳐리스트로 메모리 누수를 방지 해야 한다. class Example { var value = "" lazy var closure: () -> ..