Skip to main content

· One min read

Date

  1. Locale 이란?
  • 사용자의 언어, 국가뿐 아니라 사용자 인터페이스에서 사용자가 선호하는 사항을 지정한 매개 변수의 모임

· 2 min read

RealmSWIFT 정리

  1. RealmSWIFT 란 ?
  • 오픈소스로 제공되는 모바일 데이터베이스 관리 라이브러리
  • 클래스 단위로 Table이 생성되고, 객체 단위로 row가 구성된다.
  1. Install
  • using cocoapod
  • pop 'RealmSwift'
  1. 모델 생성
 import RealmSwift
class DictionaryRealm: Object {
@objc dynamic var date = ""
var todoList = List<Todo>() // Realm 은 배열 선언을 할때 List로 해야한다, NSArray is not supported as an RLMObject property
}
 class Todo: Object {
@objc dynamic var title = ""
@objc dynamic var contents = ""
}
  1. 저장
let dataToSave = DictionaryRealm() // 저장 할 모델 선언
dataToSave.date = "today" // 데이터 set
let todo = Todo() // 추가할 todo set
todo.title = "title"
todo.contents = "contens"
dataToSave.todoList.append(todo)
try! realm.write { // realm.write로 저장
realm.add(dataToSave) // realm.add()로 데이터 추가
}
  • 불러온 Realm 데이터를 write외부 에서 수정할 시 에러 발생
  1. 로드
let realm = try! Realm() // realm 객체 선언
let savedData = realm.objects(DictionaryRealm.self).filter("date='today'") // realm 오브젝트 형태로 filter에 맞게 불러옴
saveData.isEmpty // 데이터 비어있는지 확인
saveData.first.todoList // todoList 확인
  1. 삭제
 try! realm.write {
realm.delete(item)
}
  1. 업데이트
 try! realm.write {
updateItem.titlt = "newTitle"
}

· 2 min read

ImageView ContentMode

  1. ContentMode
  • ContentMode는 enum이다.

    • case scaleToFill // 이미지의 높이와 너비는 UIImageView의 크기와 일치하도록 늘어납니다.
    • case scaleAspectFit // 이미지의 비율을 유지하면서 뷰의 사이즈에 맞게 이미지를 늘리는 옵션
    • case scaleAspectFill // 이미지의 비율을 유지하면서 뷰에 사이즈에 맞게 이미지를 꽉 채우는 옵션(특정 부분이 잘려 보일 수 있음)
    • case redraw
    • case center
    • case top
    • case bottom
    • case left
    • case right
    • case topLeft
    • case topRight
    • case bottomLeft
    • case bottomRight
  • 정리

    • scaleToFill: 비율 유지 X, 화면 꽉 채움 O, 이미지 잘림 X
    • scaleAspectFit: 비율 유지 O, 화면 꽉 채움 X, 이미지 잘림 X
    • sacleAspectFill: 비율 유지 O, 화면 꽉 채움 O, 이미지 잘림 O

· 3 min read

Lottie Animation

  1. What is the Lottie Animation
  • JSON 기반의 이미지 파일
  1. Lottie 라이브러리 설치
  • pod init
  • podfile에 추가 pod 'lottie-ios'
  • pod install
  • open ProjectName.xcworkspace
  1. Lottie 사용법
  • Animation 띄우기

    • private var animationView: AnimationView? // 애니메이션뷰 변수 선언
    • animationView = .init(name: "coffee") // 애니메이션 뷰에 다운받은 coffee.json(로티이미지) 설정
    • animationView!.frame = view.bounds // 애니메이션뷰 프레임 설정
    • animationView!.contentMode = .scaleAscpectFill // 비율 유지하면서 화면 가득 채우기 옵션
    • animationView!.loopMode = .loop // 애니메이션 반복 설정
    • animationView!.animationSpeed = 0.5 // 애니메이션 재생 속도
    • view.addSubView(animationView!) // 베이스 뷰에 애니메이션 뷰 추가
    • animationView!.play() // 애니메이션 재생
  • Progress Image

    • private var progressView: AnimationView? // 변수 선언
    • progressView = .init(name: "download") // download.json 설정
    • progressView.frame = view.bounds
    • progressView.contentMode = .scaleAspectFill
    • view.addSubview(progressView!)
  • url 다운로드 세팅

    • let url = URL(string: "https://archive.org/download/SampleVideo1280x7205mb/SampleVideo_1280x720_5mb.mp4")! // URL 설정
    • let configuration = URLSessionConfiguration.default // url Configuration 설정
    • let operationQueue = OperationQueue() // 비동기 처리를 위한 큐 설정
    • let session = URLSession(configuration: configuration, delegate: self, delegateQueue: operationQueue) // URLSession 생성
    • let downloadTask = session.downloadTask(with: url) // downloadTask 실행
    • downloadTask.resume()
  • 시작, 끝, 완료를 구분하기 위한 enum 설정

    • enum ProgressKeyFrames: CGFloat { case start = 140 case end = 187 case complete = 240 }
  • ProgressView Play

    • progressView?.play(fromFrame: 0, // set start frame toFrame: ProgressKeyFrames.start.rawValue, // set end point loopMode: .none, // 반복 설정 completion: { [self weak] (_) in
      self?.startDownload() // 다운로드 함수 호출 } )
  • startDownLoad()

    • progressView?.play(fromFrame: ProgressKeyFrames.start.rawValue, // set start frame toFrame: ProgressKeyFrames.end.rawValue, // set end frame loopMode: .none, // 반복 설정 completion: { [weak self] (_) in self?.endDownload() // 다운로드 끝 함수 호출 } )
  • endDownload()

    • progressView?.play(fromFrame: ProgressKeyFrames.end.rawValue, toFrame: ProgresssKeyFrames.complete.rawValue, loopMode: .none) )
  • URLSessionDownloadDelegate

    • private func progress(to progress: CGFloat) { let progressRange = ProgressKeyFrames.end.rawValue - ProgressKeyFrames.start.rawValue // set range let progressFrame = progressRange * progress // set frame with progress let currentFrame = progressFrame + ProgressKeyFrames.start.rawValue // set currentFrame

      progressView?.currentFrame = currentFrame // updateFrame

      }

    • func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { let percentDownloaded:CGFloat = CGFloat(totalBytesWritten) / CGFloat(totalBytesExpectedToWrite) // 현재 다운로드 퍼센트 계산 DispatchQueue.main.async { self.progress(to: percentDownloaded) // 메인큐로 progress 함수로 넘겨줌 } }

    • func urlSession(_ session: URLSession, downloadTask: URLSessionDownLoadTask, didFinishDownloadingTo location: URL) { DispatchQueue.main.async { self.endDownload() // 다운로드 완료 } }

· One min read

아파치 취약점

  1. TRACE and TRACE HTTP 메소드 사용
  • HTTP 규약에 따라 웹서버들은 GET, PORT, HEAD, PUT, OPTIONS, DELETE, TRACE 7개의 메소드를 제공한다
  • 최근 웹 트렌드에는 GET, POST를 제외한 나머지 메소드들을 비활성화 한다.
  • web.xml에 security-constraint 추가
    * <security-constraint>
<web-resource-collection>
<web-resource-name>Restricted methods</web-resource-name>
<url-pattern>/*</url-parrern>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
  • httpd.conf에 추가
    • TraceEnable Off
  1. Apache 헤드에 불필요한 정보 숨김 처리
  • 테스트 방법
    • curl --head 서버주소
  • 처리 방법
    • httpd.conf에 아래 내용 추가
    • ServerTokens Prod
    • ServerSignature off

· 4 min read

IOS 개념 정리

  1. lazy var 란
  • 변수이지만 이 변수가 사용되거나, 호출되기전까지 초기화되지 않고 메모리 할당을 받지 않는 변수
  • 즉, 이 lazy 변수는 view controller가 초기화 되었을때 초기화되지 않는다.
  • 자신이 사용될떄가지 대기하다가 자신이 사용될 때 초기화 된다.
  • UI 구성요성을 초기화 할 때 유용하다.
  1. UITextField 수직 정렬
  • textField.centerVerticalAlignment = .top
  1. clipToBounds
  • textField.clipToBounds = true -> "true일때 내용들과 서브뷰들은 뷰의 테두리를 기준으로 잘리게 된다.
  1. masksToBounds
  • layer 속성 이며, clipToBounds 와 똑같은 역할 내용들 테두리에 맞추어 자를지 말지 true false로 결정
  • textFeild.layer.masksToBounds = true -> "true일때 내용물과 서브뷰들은 testField의 테두리를 기준으로 잘리게 된다.
  1. UI 세팅
  • ViewController에서 뷰를 그리지 말고 UIView로 View를 만들어서 ViewController에서 사용
  • updateConstrains() 함수 사용하여 UIView 레이아웃 설정
  • ViewCOntroller에서 세팅
    • lazy var mainView: MainView = { return MainView(tableView: self.tableView) }()
    • view.addSubview(mainView)
    • 레이아웃 설정
  1. TableView 유동적인 행 높이 지정
  • 같은 Cell - 다른 높이 -> 같은 형태의 Cell을 사용하더라도 들어가는 컨텐츠의 내용이 다를 경우 높이가 다르게 될 수 있음
  • 이러한 형태를 고려하여 Cell 안에 요소들의 Constrains를 잘 지정해주어야 함
  • 스토리보드에서 테이블 Cell 높이를 지정할 떄 주의할 점은 Dynamic Prototype Cell을 만드는 경우에 TableView의 Row Height는 Cell의 Custom Row Height를 Override 한다
    • 즉, cell 높이를 500으로 지정해도, TableView에서 Row Height 값이 50이면 50으로 적용된다는 뜻
    • static cell인 경우는 Cell의 높이가 row height보다 우선시 된다.
  • AutomaticDimension
    • 가각 다른 cell마다 높이를 적용하는 것이라면 tableView 메소드 중 HeightForRowAtIndexPath를 사용하여 임의로 해당 Cell 높이 지정 가능
    • 하지만 같은 cell의 높이를 각각 지정하려면 AutomationDimension을 통해 테이블 Row의 높이가 유동적이라고 선언해야 한다.
    • 이 선언을 통해 위에서 지정한 row height는 무시되고 row안의 내용에 따라 row의 높이가 유동적으로 결정된다
    • tableView.rowHeight = UITableView.automaticDimension (최신 버전에서 변경됨)
  • estimatedRowHeight
    • 개발자가 예상되는 RowHeight 값
    • 테이블 뷰의 데이터가 Reload 될때 각 Row마다 대략적인 높이를 계산하는데 도움을 주는 역할
    • 직접대입, 메소드 사용 둘다 가능
  1. 여러 뷰에서 데이터 공유
  • delegate 패턴 사용
    • A class에서 사용되는 데이터를 B class에서 가공하여 다시 A에서 사용하고 싶을때
    • protocol 정의
      • protocol TodoProtocol { func addTodoList(todoViewModel: TodoViewModel) }
    • A class에서 prococol implement
      • class A: TodoProtocol { func addTodoList(todoViewModel: TodoViewModel) { self.todoVM = TodoViewModel } }
    • A class init에서 B class delegate 변수 self 선언
      • init() { b.delegate = self }
    • B class에서 delegate 변수 선언
      • var delegate: TodoProtocol?
    • B class에서 delegate?.addTodoList(todoViewModel: self.TodoViewModel)

· 8 min read

Objective C

  1. 변수
  • int, long, float, double, char
  • formatter
    • int -> %d
    • long -> %ld
    • float -> %f
    • double -> %f
    • *char -> %s
  • NSInteger: 현재 사용하고 있는 아키텍처에 맞게 사이즈가 자동으로 설정되는 애플의 Foundation 프레임워크에 있는 특별한 primitive data type
    • primitive type이며 32bit에서 NSInteger, NSUInteger는 int, unsigned int에 mapping된다.
    • 64bit에서는 NSInteger, NSUInteger는 long, unsigned long에 mapping 된다.
    • NSInteger nsInt = 100;
    • 출력: NSlog(@"result : %i", nsInt); long일 경우 %li
  • CGFloat: Foundation 프레임워크에 있는 primitive data type float, double에 자동 맵핑
    • CoreGraphics
    • CGFloat cgFloat = 10.3;
    • 출력: NSLog(@"result : %f", cgFloat);
  • BOOL: boolean type
    • BOOL isTrue = YES; -> YES 는 1
    • BOOL isFalse = NO; -> NO 는 0
  1. 조건문
  • if (// condition) { // statement }else if (// condition) { // statement }else
  1. 함수
  • 함수 선언
    • (returnType)functionName:(parameterType) parameterName withAnotherValue:(secondParamterType) secondParameterName { // statement
      }
    • (void)addIntegers:(NSInteger) firstValue withAnotherValue: (NSInteger) secondValue { NSLog(@"result: %i", firstValue + secondValue); }
  • 함수호출
    • [self addIntegers:5 withAnotherValue: 10]; -> 15 출력
  1. NSString
  • NSString 은 스트링형태를 다루는 ObjectiveC 객체
  • 객체 생성
    • NSString *myName = [[NSString alloc] initWithFormat:@"David Yoon"];
    • 출력: NSLog(@"result: %@", myName); -> 객체 포멧은 %@
    • NSString *otherName = [NSString stringWithFormat:@"your name"];
  • 문자열 출력
    • NSLog(@"%i", [myName length]);
  • 문자열 복사
    • NSStirng *tmp = [NSString stringWithString:myName];
  • 문자열 합치기
    • NSString *tmp = [str1 stringByAppendingString:str2];
  • 문자열 합치기 2
    • NSMutableString *str1 = @"This is"
    • NSString *str2 = @"Love"
    • [str1 appendString:str2];
  • 문자열 비교
    • NSString *tmp = str1;
    • if ([str1 isEqualToString:tmp] == YES)
  1. NSNumber
  • Foundation 프레임워크의 NSNumber 클래스 인스턴스를 생성하는 것 -> 자바의 wrapper 클래스 개념
  • 객체를 만드는 데 다른 객체를 사용하는 몇몇의 Cocoa 클래스들이 있기 때문(primitive type 사용 불가)
  • 생성
    • NSNumber *appleNumber = [[NSNumber alloc] initWithInt:5];
    • NSNumber *carNumber = [NSNumber numberWithInt: 3295];
  • NSNumber to CGFloat
    • CGFloat cgFloat = [carNumber floatValue];
  • NSInteger to NSNumber
    • NSInteger originInteger = 50;
    • NSNumber *numberForOrigin = [NSNumber numberWithInteger: originInteger];
  1. LifeCycle
  • 주기

    • 앱실행 -> main() -> AppDelegate -> ViewController
  • 앱 구성요소 보기

    • UIKit: UI를 그리는 다양한 컴포넌트를 가지고 있는 라이브러리
  • 앱 생명주기

    • 앱실행 -> 인액티브 -> 액티브 -> 백그라운드 -> 서스팬드 -> 스톱
  1. UIView
  • UIViewController
    • 큰 장면 덩어리를 관리
    • UIViewController를 만들면 자동적으로 하나의 UIView가 따라온다.
  • 화면에 보이는 것들의 기본속성
    • 사각형이 기본
    • 사각형을 그리기 위한 위치, 크기 필요
    • (x,y), width, height -> frame
    • 색깔(Color)
  • IOS 좌표계
    • 왼쪽 위에서 부터 (0,0) 시작 -> 처음 constrains 없이 뷰 넣으면 왼쪽 상단에 몰려있음
  • UIView 생성
    • CGRect testRect = CGRectMake(0,0,30,30);
    • UIView *testView = [[UIView alloc] initWithFrame: testRect];
  • 화면에 뷰 추가
    • addSubView
    • [부모뷰 addSubView: 자식뷰]
    • [self.view addSubView: testView];
  • 색추가
    • self.view.backgroundcolor = UIColor.redColor;
    • testView.backgroundcolor = [UIColor blueColor];
  1. UIView_2
  • [parent addSubView child];
  • 화면에서 삭제하기
    • [child removeFromSuperview];
  • 부모뷰 뿐만 아니라 다른뷰에도 addSubView 가능
    • [secondView addSubView:thirdView];
    • 좌표가 0,0이면 secondView 왼쪽위에서 부터 그려짐 기준이 부모 왼쪽 위에 점으로 시작
  • 이동시키기
    • frame 에 들어가는 CGRect 좌표로 view 이동 가능
    • secondView.frame = CGRectMake(200,200,70,70); 으로 이동 가능
  • 화면 숨기기
    • hidden
    • thirdView.hidden = true;
  • 투명도
    • alpha
    • min: 0, max: 1.0
    • 투명도가 줄어드는 것이라 0이어도 메모리는 잡아먹음
    • 페이드효과 만들 때 사용
    • [UIView animationWithDuration:0.4 delay: 1.0f options:UIViewAnimationOptionCurveEaseIn animations:^{ thirdView.alpha = 0.0f; } completion:^(BOOL finished) { }]
  1. Self, Super
  • Self

    • 나 자신, 현재 메소드가 변수가 소속되어 있는 Class
    • ViewController.m 에서 self는 ViewController
    • Appdelegate.m 에서는 self = appDelegate
    • .h 파일에서 self사용할 일 없음
    • 다른언어에서는 this라고 불림
  • Super

    • 내 위에 무언가를 지칭한다
  • 상속

    • 그대로 물려받다. [inherit]
    • UIView 상속 받아 새로운 뷰 생성 가능
  • superclass

    • 내가 상속받은 class
    • NSObject(최상의 클래스) -> UIResponder -> UIViewController
    • NSObject -> UIResponder -> Appdelegate
  • superview

    • self.view.superview 는 null 자동 생성 뷰이기 떄문에 슈퍼뷰 없음
    • testView.superview 는 UIView(self.view)
    • 뷰에 태그 붙이기
      • self.view.tag = 20 (기본값은 0)
  1. UILabel
  • text
    • 사용자에게 단순히 보여지는 text
      • 메뉴 가격 (static form)
    • 사용자가 입력할 수 있는 text
      • 글쓰기 form (input form)
    • 사용자의 행위에 따라 변하는 text
      • 장바구니 가격 form (dynamic form)
  • UILabel 은 static, dynamic에 적합
  • UILable 속성
    • 사격형
    • 텍스트
    • 배경색
    • font
      • testLabel.font = [UIFont systemFontOfSize:30];
    • textAlignment
      • testLabel.textAlignment = NSTextAlignmentCenter;
  1. UIImageView
  • UIImage

    • 이미지 파일 데이터를 화면에 쉽게 출력할 수 있게 도와주는 도구
    • file -> data -> UIImage -> UIImageView -> 사용자
  • UIImageView 생성

    • UIImage *testImage = [UIImage imageNamed: @"imageName.png"];
    • UIImageView *testImageView = [[UIImageView alloc] initWithFrame: CGRectMake(0,0, 200,200);
    • testImageView.image = testImage;
    • testImageView.contentMode = UIViewContentModeScaleAspectFill -> 원본 비율에 맞게 크기 채워서 이미지 출려 옵션
    • testImageView.contentMode = UIViewContentModeScaleAspectFit -> 원본 비율에 맞게 프레임 사이즈에 맞게 이미지 출력 옵션
    • [self.view addSubView:testImageView];
  • 프레임 사이즈 출력

    • NSLog(@"%@", NSStringFromCGRect(testImageView));
  • 파일 경로 가져오기

    • NSString *path = [[UIBundle mainBundle] pathForResource:@"fileName", ofType:@"fileType"];
    • NSData *data = [NSData dataWithContentOfFile:path];
    • UIImage *imageWithData = [UIImage imageWithData: data];
  1. UIButton
  • UIButton 생성

    • UIButton *testButton = [UIButton buttonWithType: UIButtonTypeCustom];
    • testButton.frame = CGRectMake(50,50,50,50);
  • UIButtonTypeRoundedRect

    • setTitle 가능
    • UIButton *testButton = [UIButton buttonWithType: UIButtonTypeRoundedRect]
    • [testButton setTitle:@"Test" forState:UIControlStateNormal];
  • UIButtonTypeCustom

    • image 삽입 가능
    • UIButton *userButton = [UIButton buttonWithType: UIButtonTypeCustom];
    • UIImage *image = [UIImage imageNamed:@"imageName.jpg"];
    • [userButton setBackgroundImage:image forState:UIControlStateNormal];
  • Event

    • [testButton addTarget:self action:@selector(touchedEvent:) forControlEvents: UIControlEventTouchUpInside];
    • sender 이벤트 처리
      • (void) touchedEvent: (UIButton) sender { NSLog(@"Button Clicked! %@", sender.tag); }
    • button.tag = 10 -> 넣어서 sender 구분
      • if (sender.tag == 10)
  1. 지역변수 전역변수
  • 지역변수
    • 함수 내에서 선언되는 변수
    • 함수내에서만 사용 가능한 변수
  • 전역변수
    • .h 파일 인터페이스 아래에 선언
    • 변수 타입과 변수명만 선언(초기화 x)
    • UIView *testView;
    • ctrl+command+화살표 위아래 하면 .m .h파일 전환 가능
  1. UITextField
  • UITextField 생성
    • UITextField *testField = [[UITextField alloc]initWithFrame: CGRectMake(50,50,200,50)];
    • textField.borderStyle = UITextBorderStyleLine;
  • Placeholder
    • textField.placeholder = @"test placeholder";
  • secureTextEntry
    • textField.secureTextEntry = true;
  1. UIView 제어
  • UIView 생성
    • UIView *sampleView = [[UIView alloc] initWithFrame:CGRectMake(50,50,100,100)];
    • sampleView.backgroundColor = UIColor.redColor;
    • [self.view addSubview: sampleView];
  • frame 좌표 변경
    • CGRect sampleFrame = sampleView.frame
    • sampleFrame.origin.x += 10;
    • sampleView.frame = sampleFrame

· 13 min read

Memory

  1. Automatic Reference Counting
  • Reference 타입(class)은 heap 메모리에 저장된다
  • 메모리는 자동으로 관리된다
  • 가르키는 포인터의 카운터를 세다가 0이되면 놓아버리는 형식의 메모리 관리
  1. ARC에 영향을 주는 세가지
  • strong
    • 디폴트
    • 레퍼런스 카운트 증가(선언된 변수가 힙에 머물도록 하는 타입)
  • weak
    • 메모리에 참조되어 있는 값이 없다면 nil로 만드는 타입
    • 힙에 있는 무엇가를 가르키고 있지만 관심이 없어서 사라져버리면 nil로 설정
    • nil로 설정 가능하다는 것은 optional 포인터여야만 한다는 의미
    • 대표적인 예로 UILabel을 보여주기 위한 Outlet등이 있다.
  • unowned
    • 참조 횟수를 세지마라는 의미
    • 가르키는 값이 사라지면 크래쉬 발생

Closures

  1. Capturing
  • 클로저는 Heap 메모리에서 사용 되고, 레퍼런스 타입이다.
  • 클로저는 클로저를 둘러쌓고 있는 변수들을 사용할 수 있고 이 captured 변수들은 클로저가 heap에 머무는 동안 함께 머물게 된다.
  • 이것은 메모리 사이클을 만들 수 있음
  • 메모리 사이클이란
    • 클로저가 어떤 객체를 가르키고, 객체도 클로저를 가르키게 된다면 서로 가르키게 되고 순환 참조가 발생하게 된다
addUnaryOperation("루트") { [self weakSelf = self] in
weakSelf?.display.textColor = UIColor.redColor()
return sqrt($0)
}

Extensions

  1. Extensions
  • 메소드나 프로퍼티를 다른 클래스에게 추가하게 해줌
  • class, struct, enum 모두 사용 가능
  • 이제 존재하는 메소드를 다시 구현할 수는 없다
  • 추가된 요소들은 계산된 요소여야만 한다

Protocol

  1. protocols
  • API를 더욱 간결하게 표현하는 방법
  • 선언된 메소드와 프로퍼티들로 된 집합체
  • 프로토콜은 타입이다
  • 프로토콜을 실행하는 class, struct, enum에서 사용 가능
  • protocol 과 extension은 저장 공간이 없다.
  • extension을 사용할 수 있음
  1. four aspects
  • protocol declaration
    • 프로토콜에 들어갈 메소드와 프로퍼티를 선언하는 작업
  • class, struct, enum이 자기가 이 프로토콜을 실행하겠다고 선언
  • 프로토콜에 있는 값들을 구현하고 실행
  • 프로토콜을 실행한다면, 프로토콜에 있는 모든 것들을 실행해야함
    • ObjectiveC에서는 optional을 통해 필요한 것만 구현 가능
    • @objc protocol로 objectiveC버전으로 프로토콜 실행가능
    • optional 키워드로 func 나 var 앞에 붙일 수 있음
    • optional 프로토콜을 실행하는 클래스는 NSObject를 상속 받아야만 한다.
  • 프로토콜은 다중 상속 받을 수 있음
    • 상속 받은 프로토콜의 모든 것들을 실행해야한다.
  • var 에 get 이나 get and set 설정 해주어야 함
  • 변경될 예정인 함수들은 mutating 키워드 붙어야함 (struct(값 타입)에 변경이 발생하는 경우)
  • protocol Somprotocol: class 하면 class만 해당 프로토콜 상속 가능
  • 프로토콜 안에 initializer 사용 가능
  • 프로토콜 안에 init이 있고 클래스가 그것을 실행한다면 그 init을 required로 만들어야 한다.
  • extension에 추가 가능

Delegation

  • 프로토콜을 사용하는 대표적인 예
  • 델리게이션은 눈에 보이지 않는 소통을 하는 방식(blind communication between a View and Controller)
  • 프로토콜을 이용하여 델리게이션 하는 방법
    • 뷰에서 델리게이션 프로토콜을 선언한다.
      • MainTableViewController: ToDoProtocol
    • 뷰의 API는 weak delegate를 가지고 있을 것이고 이것은 델이게이션 프로토콜 타입이다.
      • AddTodoViewController { weak var delegate: TodoProtocol? }
      • weak or unowned인 이유: 컨트롤러가 뷰를 메모리에 저장할 수 있지만, 뷰가 컨트롤러를 메모리에 저장하게 하고 싶진 않을테니까
      • 사용하지 않으면 nil로 초기화
    • 뷰가 delegate 사용: 뷰가 메시지를 보내길 원할 때
      • should, will, did, count, data ... etc
    • 컨트롤러는 이 프로토콜을 실행한다고 선언한다
    • 컨트롤러는 자기자신(self)을 delegate라고 지정한다
      • addViewController.delegate = self
    • 컨트롤러는 프로토콜을 실행
  • 모든 델리게이트 들은 오프젝티브C로 구성되어 있어서 IOS의 대부분의 델리게이트(ScrollVeiwDelegate, TableViewDelegate)의 거의 모든 메소드들은 옵셔널이다.
  • 위에 과정을 걸치면 뷰는 컨트롤러에 연결된 상태지만 뷰는 어떤 오프젝트가 will, should, did를 실행하고 있는지 모른다.
  • closure방식으로 델리게이트 처리할 수 있음
    • 프로토콜이 처리하게 하느냐고 많은 비용이 들 수 있는데 클로져가 있으면, 클로져의 인자가 무엇인지 알고 있고 무엇을 반환할지 알고 있기 때문에 사실상 프로토콜을 정하는것과 동일하다
    • ScrollView를 예를 들면 스크롤이 끝나면 이 클로져를 실행해라 라는 의미 -> 클로저에게 처리를 맡기는 것
  • 클로져와 프로토콜 둘다 사용가능하지만 서로 완전히 대체가능하지는 않다.
  • 프로토콜은 이 오브젝트가 무엇을 위임할 수 있는지를 매우 분명히 할때 좋다.
  • 클로져는 에러 콜백(Error Callback), Multi-Thread 환경 어떤 처리가 오래 걸리다가 나중에 완료되면 끝났다고 알려줄때 좋다
  • Example
    • UIScrollView
    • weak var delegate: UIScrollViewDelegate?
    • @objc protocol UIScrollViewDelegate{ optional func ~~ optional func ~~ }

ImageView

  • URL에서 이미지 가져오는 방법
    • let url = imageURL
    • let imageData = NSData(contentOf: url as URL)
    • UIImage image = UIImage(data: imageData as Data)
  • UIImageView set
    • image { set { imageView.image = newValue imageView.sizeToFit() scrollView?.contentSize = imageView.frame } }

Mulithreading

  • 멀티 쓰레딩이란, 일을 처리하는 별도의 쓰레드를 갖추는 것이다.

  • 싱글코어프로세서에서도 시분할 방식으로 문맥교환을 통해 여러 쓰레드를 작동시킨다

  • IOS에서 멀티 쓰레딩은 queue와 같다

  • 이 큐는 IOS 함수들을 포함하고 있다 (대부분 여기에 들어간 함수는 클로져로 되어 있다)

  • 큐는 여러개가 존재할 수 있고 스시템은 각각의 큐에서 꺼내서 각각의 쓰레드에서 동작시킨다

  • 시리얼큐(serial)는 큐에 있는 첫 번째 테스크가 끝나면 그 다음 테스크는 꺼내는 방식의 큐이다.

  • 병렬큐(concurrent)는 큐에서 테크를 꺼내 처리하는 동안 놀고있는 다른 쓰레드에서 다음 것들을 바로 처리하는 방식

  • Main Queue

    • 가장 중요한 큐 (very special serial queue)
    • 메인 큐는 모든 UI가 작동해야 할 곳에서 사용된다.
    • 이와 반대로 시간이나 리소스를 잡아먹는 UI외의 모든 처리는 메인큐 밖에서 처리해야만 한다.
    • 메인 큐에서 동작하는 것들은 직렬로 처리된다.
    • UI가 순서대로 예상가능하게 표현되어야 하기 떄문인다.
    • 메인 큐가 클로져나 함수를 꺼내 작업을 처리하는 유일한 떄는 메인큐가 한가할 때이다.
  • Other Queue

    • UI가 아닌 것들을 처리하는데 사용하는 큐
  • 큐에 뭔가를 집어넣는 방법

    • dispatchasync(queue) { / do what you want to do here _/ <- 클로저임 }
    • 2개의 arguments를 받음
      • queue
      • func(closure)
  • The Main Queue

    • main queue call
      • dispatch_get_main_queue() 함수 사용 -> swift 3.0 미만
      • DispatchQueue.main.async
  • The Other Queue

    • 다른 큐를 사용하는 방법은 시스템이 제공하는 병렬 큐들을 사용
    • 시스템이 제공하는 4가지 큐
    • 4개의 큐는 각자 맡고 있는 서비스(Quality Of Service)가 있다.
    • QOS는 시스템이 얼마나 특정 서비스에 중점을 두느냐를 말한다 -> 우선순위로 이해해도 된다.
    • 4가지 QOS
      • USER_INTERACTIVE: 가장 우선순위가 높은 큐 메인큐는 아니지만 즉각 처리가 필요한 부분
      • USER_INITIATED: 유저가 처리를 요청했지만 상호작용이 필요한 처리는 아님 시간은 조금 걸리지만 바로 처리해야함
      • UTILITY: 뒤에서 오랫동안 작동하는 작업 데이터를 가져오거나 데이터 베이스를 비운다던지 하는 경우
      • BACKGROUND: 오늘 해도 되고 내일 해도 되는 작업
    • other queue call
      dispatch_get_global_queue(<one of the QOS>, 0) // 0 is a "reserved for future" 언젠가를 위해 남겨둔다는 의미로 항상 0으로 세팅
    • DispatchQueue.global.async
  • User Create Queue

    • custome queue call
      • dispatch_queue_create("name", DISPATCH_QUEUE_SERIAL)
      • DispatchQueue(label:"queuename")
    • 메인 큐 까지는 아니지만 높은 우선순위의 직렬큐로 생성된다.
  • GCD(Grand Central Dispatch)

    • 따로 공부해라
  • 추상적인 API

    • NSOpertaionQueue and NSOperation
    • 서로 다른 쓰레드에서 동작하는 2개의 객체가 서로 의존성이 있을때 사용
  • IOS API관점에서 멀티 쓰레딩

    • IOS 전반에는 쓰레드를 사용해서 비동기적으로 처리하는 수많은 메소드가 있다
    • 메소들의 인자중 하나인 클로저를 살펴보면 된다.
    • 클로저는 비동기으로 메인 큐 바깥에서 처리될 것
    • 대표적인 예 URLSession

UITextField

  • UITextField는 UILabel과 같지만 텍스트를 편집할 수 있다.
  • UITextField가 "first responder"가 되면 키보드가 나타난다.
  • 키보드를 숨기고 싶으면 resignFirstResponder를 사용하면 된다.
  • Delegate 주로 return키와 함께 사용된다.
  • 키보드를 설정하려면 UITextField를 통하면 된다.
  • 키보드위에 커스텀 뷰 올릴때 inputAccessoryView

· 3 min read

View Controller Lifecycle

  • 뷰 컨트롤러는 라이프 라이클을 가지고 있음

  • 인스턴스 생성과 준비 그리고 Outlet 설정이 끝나면 viewDidLoad 가 불린다.

  • viewDidLoad

    • 초기화 코드를 넣기에 좋은 장소
    • Update UI 하기 좋은 장소
    • Geometry 는 아직 세팅되어 있지 않다(its bounds)
    • 무엇가 확실히 나타나지 않는 것들은 viewDidLoad에 설정하지 않는다(복잡한 로직이나 네트워크 등)
    • 한 번만 호출 된다(중요)
  • viewWillAppear

    • 화면을 올리기 직전에 호출됨
    • 복잡한 로직을 실행하기 좋은 곳이다.
  • viewDidAppear

    • 화면이 나타는 직후에 호출되는 메소드
    • animation을 시작하기 좋은 곳
  • viewWillDisappear

    • viewDidAppear()에서 했던 것들은 undo(되돌리기)하게 될 곳
    • stop animation
  • viewDidDisappear

    • 네트워크에서 가져온 데이터를 풀어줄 수 있음
  • Geometry changed

    • viewWillLayoutSubviews()
    • viewDidLayoutSubviews()
    • View에 상태에 따라 Bounds가 변함 -> navigationBar는 뷰 위에 있어서 변하지 않지만, TabBar는 뷰와 겹쳐서 Bound가 변한다.
  • viewWillTrasitionToSize

    • 유저가 디바이스를 가로.세로로 전환할때 자동으로 bound를 바꾸어 줌
    • 개발자가 viewWillTrasitionToSize() 함수를 사용하여 수동으로 조작할 수도 있음
  • didReceiveMemoryWarning

    • 메모리 부족 상황에서는 didReceiveMemoryWarning 메소드가 호출된다.
  • awakeFromNib

    • 스토리보드로 부터 나오는 모든 오브젝트를 이 메소드로 보냄
    • 아웃렛이 세팅되기 전에 발생
  • 결론
  1. Instantiated(from storyboard usually)
  2. awakeFromNib
  3. segue preparation happens
  4. outlets get set
  5. viewDidLoad
  6. These pairs will be called eath time your Controller's view goes on/off screen ...
    • viewWillAppear and viewDidAppear
    • viewWillDisapper and viewDisDisappear
  7. These "geometry changed" methods might be called at any time after viewDidLoad
    • viewWillLayoutSubviews
    • viewDidLayoutSubviews
  8. If memory gets low, you might get ...
    • didReceiveMemoryWarning

· 2 min read
  1. 안드로이드 Handler 란
  • 안드로이드에서 UI 작업은 메인 스레드에서 처리
  • 로직상 워커 스레드 내에서 UI처리를 해야 한다면, 해당 워커 스레드와 메인 스레드를 연결해주는 핸들러를 이용
  • 워커 스레드에서 핸들러는 메인 스레드로 메시지를 전달하고, 메시지를 수신한 메인스레드에서 적절한 처리
  • UI 반응성을 위해 메인 스레드에서는 무거운 작업을 해서는 안된다. 결국 성능 문제로 워커 스레드에서 처리
  1. MessageQueue, Looper
  • 메세지 큐는 핸들러가 전달하는 메세지를 보관하는 FIFO방식의 큐
  • 메세지 또는 Runnable이 저장되며, 메세지 큐에 저장된 것들을 Looper가 차례로 꺼내서 핸들러로 전달