138
초급 개발자 IOS 입문기 장공의 @gonini Swift3 & IOS10

초급 개발자 Ios 입문기

  • Upload
    -

  • View
    1.294

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 초급 개발자 Ios 입문기

초급�개발자�IOS�입문기�

장공의 @gonini

Swift3�&�IOS10

Page 2: 초급 개발자 Ios 입문기

내용

‣ ���IOS�&�Swift�학습

‣ ���개발�시작

‣ ���도움이�되었던�것들

Page 3: 초급 개발자 Ios 입문기

IOS�&�Swift�학습

Page 4: 초급 개발자 Ios 입문기

저는...

‣ ���앞으로�Mac�App�개발하고�싶음

‣ ���함수형�프로그래밍�경험�有

‣ ���Android�개발�경험�有(그렇지만�안한지�1년�이상�경과�😖 )�

‣ ���장공의

‣ ���21살�젊은이

Page 5: 초급 개발자 Ios 입문기

저는...

‣ ���함수형�프로그래밍�경험�有

‣ ���Android�개발�경험�有(그렇지만�안한지�1년�이상�경과�😖 )�

‣ ���장공의

⭐ (도움)

‣ ���앞으로�Mac�App�개발하고�싶음

‣ ���21살�젊은이

⭐ (도움)

Page 6: 초급 개발자 Ios 입문기

학습�기간

‣ ���Swift3�공부�1�week

‣ ���IOS�공부�4�days

‣ ���카메라�앱�개발�2�month�+�ɑ

‣ ���개발�도중�필요한�부분�추가�학습

Page 7: 초급 개발자 Ios 입문기

학습�기간

‣ ���Swift3�공부�1�week

‣ ���IOS�공부�4�days

‣ ���카메라�앱�개발�2�month�+�ɑ

‣ ���개발�도중�필요한�부분�추가�학습

Page 8: 초급 개발자 Ios 입문기

개발�일정�때문에�학습에�많은�시간을�투자�할�수�없음

Page 9: 초급 개발자 Ios 입문기

안드로이드�개발�경험을�살려�기본부터�빠르게�접근

Page 10: 초급 개발자 Ios 입문기

And

Page 11: 초급 개발자 Ios 입문기

Android�&�IOS

‣ ���Single�Thread�Model

‣ ���Lifecycle,�Data�유보�등

‣ ���SurfaceView�(==�CALayer

‣ ���Thread,�Handler,�Executors…�(==�GCD

‣ ���메모리�관리

‣ ���Optimizing,�Performance

Page 12: 초급 개발자 Ios 입문기

Android�&�IOS

‣ ���Single�Thread�Model

‣ ���Lifecycle,�Data�유보�등

‣ ���SurfaceView�(==�CALayer

‣ ���Thread,�Handler,�Executors…�(==�GCD

‣ ���메모리�관리

‣ ���Optimizing,�Performance

Page 13: 초급 개발자 Ios 입문기

LifecycleViewController의�생명주기

Page 14: 초급 개발자 Ios 입문기

어디서�많이�본�것�같은�생명주기

Page 15: 초급 개발자 Ios 입문기

LifecycleViewController의�생명주기

Page 16: 초급 개발자 Ios 입문기

LifecycleViewController의�생명주기

onCreate()

Page 17: 초급 개발자 Ios 입문기

LifecycleViewController의�생명주기

onResume()

onStart()

Page 18: 초급 개발자 Ios 입문기

LifecycleViewController의�생명주기

onLowMemory()

Page 19: 초급 개발자 Ios 입문기

LifecycleViewController의�생명주기

onStop()

onPause()

Page 20: 초급 개발자 Ios 입문기

LifecycleViewController의�생명주기

onDestory()

Page 21: 초급 개발자 Ios 입문기

LifecycleViewController의�생명주기

Page 22: 초급 개발자 Ios 입문기

정확히�일치하는�것은�아니나�맥락은�비슷하다

Page 23: 초급 개발자 Ios 입문기

GCD

Grand�Central�DispatchGCD�provides�and�manages�FIFO�queues�to�which�your�application�can�submit�tasks�in�the�form�of�block�objects.�Work�submitted�to�dispatch�queues�are�executed�on�a�pool�of�threads�fully�managed�by�the�system.�No�guarantee�is�made�as�to�the�thread�on�which�a�task�executes.�

Synchronous�and�Asynchronous�Execution�Each�work�item�can�be�executed�either�synchronously�or�asynchronously.�When�a�work�item�is�executed�synchronously�with�the�sync�method,�the�program�waits�until�execution�finishes�before�the�method�call�returns.�When�a�work�item�is�executed�asynchronously�with�the�async�method,�the�method�call�returns�immediately.�

Serial�and�Concurrent�Queues�A�dispatch�queue�can�be�either�serial,�so�that�work�items�are�executed�one�at�a�time,�or�it�can�be�concurrent,�so�that�work�items�are�dequeued�in�order,�but�run�all�at�once�and�can�finish�in�any�order.�Both�serial�and�concurrent�queues�process�work�items�in�first�in,�first-out�(FIFO)�order.�

System-Provided�Queues�When�an�app�launches,�the�system�automatically�creates�a�special�queue�called�the�main�queue.�Work�items�enqueued�to�the�main�queue�execute�serially�on�your�app’s�main�thread.�You�can�access�the�main�queue�using�the�main�type�property.

Page 24: 초급 개발자 Ios 입문기

GCD

Grand�Central�DispatchGCD�provides�and�manages�FIFO�queues�to�which�your�application�can�submit�tasks�in�the�form�of�block�objects.�Work�submitted�to�dispatch�queues�are�executed�on�a�pool�of�threads�fully�managed�by�the�system.�No�guarantee�is�made�as�to�the�thread�on�which�a�task�executes.�

Synchronous�and�Asynchronous�Execution�Each�work�item�can�be�executed�either�synchronously�or�asynchronously.�When�a�work�item�is�executed�synchronously�with�the�sync�method,�the�program�waits�until�execution�finishes�before�the�method�call�returns.�When�a�work�item�is�executed�asynchronously�with�the�async�method,�the�method�call�returns�immediately.�

Serial�and�Concurrent�Queues�A�dispatch�queue�can�be�either�serial,�so�that�work�items�are�executed�one�at�a�time,�or�it�can�be�concurrent,�so�that�work�items�are�dequeued�in�order,�but�run�all�at�once�and�can�finish�in�any�order.�Both�serial�and�concurrent�queues�process�work�items�in�first�in,�first-out�(FIFO)�order.�

System-Provided�Queues�When�an�app�launches,�the�system�automatically�creates�a�special�queue�called�the�main�queue.�Work�items�enqueued�to�the�main�queue�execute�serially�on�your�app’s�main�thread.�You�can�access�the�main�queue�using�the�main�type�property.

그렇답니다.

Page 25: 초급 개발자 Ios 입문기

‣ ���어셈블리�최적화를�통해�빠른�성능�제공

‣ ���스레드�생성과�관리를�안정적으로�처리

GCDGCD는�스레드를�직접�다루지�않고�동시성�문제를�처리하는�기술

‣ ���스레드�풀을�통해�스레드를�재사용�

‣ ���동기화�문제를�유연하게�처리

‣ ���메모리를�효율적으로�사용

‣ ���직관적이고�단순한�API

Page 26: 초급 개발자 Ios 입문기

GCDGCD는�스레드를�직접�다루지�않고�동시성�문제를�처리하는�기술

‣ ���어셈블리�최적화를�통해�빠른�성능�제공

‣ ���스레드�생성과�관리를�안정적으로�처리

‣ ���스레드�풀을�통해�스레드를�재사용�

‣ ���동기화�문제를�유연하게�처리

‣ ���메모리를�효율적으로�사용

‣ ���직관적이고�단순한�API

Page 27: 초급 개발자 Ios 입문기

GCD

func�removeVideoWithPaths(videoPathArray:�[String])�{���������DispatchQueue.global().async�{��[unowned�self]�in�������������for�path�in�videoPathArray�{�����������������self.dataManager.removeVideoWithPath(atPath:�path)�������������}���������}�����}

특정�Task를�백그라운드�스레드에서�실행하는�패턴

Page 28: 초급 개발자 Ios 입문기

GCD특정�Task를�백그라운드�스레드에서�실행하는�패턴

func�removeVideoWithPaths(videoPathArray:�[String])�{���������DispatchQueue.global().async�{��[unowned�self]�in�������������for�path�in�videoPathArray�{�����������������self.dataManager.removeVideoWithPath(atPath:�path)�������������}���������}�����}

유연!�직관!�단순!

Page 29: 초급 개발자 Ios 입문기

GCD백그라운드에서�작업을�실행한�후�UI를�업데이트하는�패턴

DispatchQueue.global().async�{��������//�Background�Task���������DispatchQueue.main.async�{���

//�UI�Update�Task�}�

}

Page 30: 초급 개발자 Ios 입문기

GCD백그라운드에서�작업을�완료하고�Callback을�받는�패턴

func�backgroundTask(completeHandler:�@escaping�()�->�Void)�{�����DispatchQueue.global().async�{���������completeHandler()�����}�}

Page 31: 초급 개발자 Ios 입문기

GCD백그라운드에서�작업을�완료하고�Callback을�받는�패턴

func�backgroundTask(completeHandler:�@escaping�()�->�Void)�{�����DispatchQueue.global().async�{���������completeHandler()�����}�}

closure를�인자로�받는�함수가�반환된�이후�해당�closure가�호출�되는�경우

closure가�함수에서�벗어나는�것을�허용한다는�것을�나타냄

Page 32: 초급 개발자 Ios 입문기

GCD백그라운드에서�작업을�완료하고�Callback을�받는�패턴

func�backgroundTask(completeHandler:�@escaping�()�->�Void)�{�����DispatchQueue.global().async�{���������completeHandler()�����}�}

closure를�인자로�받는�함수가�반환된�이후�해당�closure가�호출�되는�경우

closure가�함수에서�벗어나는�것을�허용한다는�것을�나타냄

xcode�8�beta�6부터�@noescape가�기본값

이전에는�@escaping이�기본값

Page 33: 초급 개발자 Ios 입문기

GCD백그라운드에서�작업을�완료하고�Callback을�받는�패턴

func�backgroundTask(completeHandler:�@escaping�()�->�Void)�{�����DispatchQueue.global().async�{���������completeHandler()�����}�}

closure를�인자로�받는�함수가�반환된�이후�해당�closure가�호출�되는�경우

closure가�함수에서�벗어나는�것을�허용한다는�것을�나타냄

xcode�8�beta�6부터�@noescape가�기본값

이전에는�@escaping이�기본값

@noescape�클로저는�변수�안에�저장할�수�없으며�당연히�함수에서�벗어날�수�없다.

Page 34: 초급 개발자 Ios 입문기

GCD

var�receivedChickenList�=�[String]()�let��receivedChickenListSemaphore�=�DispatchSemaphore(value:�1)

for�_�in�1...10�{�������������DispatchQueue.global().async�{�����������������self.sendChicken(chickenName:�"SpicyFriedChicken")�������������}�������������DispatchQueue.global().async�{�����������������self.sendChicken(chickenName:�"SoyChicken")�������������}�}

func�sendChicken(chickenName:�String)�{���������receivedChickenListSemaphore.wait()���������receivedChickenList.append(chickenName)���������receivedChickenListSemaphore.signal()�}

세마포어�or�뮤텍스를�사용하는�패턴

Page 35: 초급 개발자 Ios 입문기

GCD

var�receivedChickenList�=�[String]()�let��receivedChickenListSemaphore�=�DispatchSemaphore(value:�1)

for�_�in�1...10�{�������������DispatchQueue.global().async�{�����������������self.sendChicken(chickenName:�"SpicyFriedChicken")�������������}�������������DispatchQueue.global().async�{�����������������self.sendChicken(chickenName:�"SoyChicken")�������������}�}

func�sendChicken(chickenName:�String)�{���������receivedChickenListSemaphore.wait()���������receivedChickenList.append(chickenName)���������receivedChickenListSemaphore.signal()�}

세마포어�or�뮤텍스를�사용하는�패턴

Page 36: 초급 개발자 Ios 입문기

GCD

var�receivedChickenList�=�[String]()�let��receivedChickenListSemaphore�=�DispatchSemaphore(value:�1)

for�_�in�1...10�{�������������DispatchQueue.global().async�{�����������������self.sendChicken(chickenName:�"SpicyFriedChicken")�������������}�������������DispatchQueue.global().async�{�����������������self.sendChicken(chickenName:�"SoyChicken")�������������}�}

func�sendChicken(chickenName:�String)�{���������receivedChickenListSemaphore.wait()���������receivedChickenList.append(chickenName)���������receivedChickenListSemaphore.signal()�}

Critical�Section

세마포어�or�뮤텍스를�사용하는�패턴

Page 37: 초급 개발자 Ios 입문기

GCD

var�receivedChickenList�=�[String]()�let��receivedChickenListSemaphore�=�DispatchSemaphore(value:�1)

for�_�in�1...10�{�������������DispatchQueue.global().async�{�����������������self.sendChicken(chickenName:�"SpicyFriedChicken")�������������}�������������DispatchQueue.global().async�{�����������������self.sendChicken(chickenName:�"SoyChicken")�������������}�}

func�sendChicken(chickenName:�String)�{���������receivedChickenListSemaphore.wait()���������receivedChickenList.append(chickenName)���������receivedChickenListSemaphore.signal()�}

성능저하요소�조심해서�사용

세마포어�or�뮤텍스를�사용하는�패턴

Page 38: 초급 개발자 Ios 입문기

GCD지정�시간만큼�지연시킨�후�실행하는�패턴

let��delay�=�DispatchTime.now()�+�3

DispatchQueue.global().asyncAfter(deadline:�delay)�{�����print("goni")�}

let��repeat�=�5

DispatchQueue.concurrentPerform(iterations:�repeat)�{�i�in�����print(“goni�\(i)”)�}

지정�횟수만큼�Dispatch�Queue에�추가하는�패턴

Page 39: 초급 개발자 Ios 입문기

GCD지정�시간만큼�지연시킨�후�실행하는�패턴

let��repeat�=�5

DispatchQueue.concurrentPerform(iterations:�repeat)�{�i�in�����print(“goni�\(i)”)�}

5을�전달하면�0,�1,�2,�3,�4�가�반복상수로�전달

지정�횟수만큼�Dispatch�Queue에�추가하는�패턴

let��delay�=�DispatchTime.now()�+�3

DispatchQueue.global().asyncAfter(deadline:�delay)�{�����print("goni")�}

Page 40: 초급 개발자 Ios 입문기

GCD지정�시간만큼�지연시킨�후�실행하는�패턴

let��repeat�=�5

DispatchQueue.concurrentPerform(iterations:�repeat)�{�i�in�����print(“goni�\(i)”)�}

실행�순서는�보장되지�않음

5을�전달하면�0,�1,�2,�3,�4�가�반복상수로�전달

지정�횟수만큼�Dispatch�Queue에�추가하는�패턴

let��delay�=�DispatchTime.now()�+�3

DispatchQueue.global().asyncAfter(deadline:�delay)�{�����print("goni")�}

Page 41: 초급 개발자 Ios 입문기

GCDDispatch�Queue에�추가된�작업을�그룹으로�관리하는�패턴

let��goniGroup�=�DispatchGroup()

DispatchQueue.global().asyncAfter(group:�goniGroup)�{�����self.additionalTask()�}

Page 42: 초급 개발자 Ios 입문기

GCDDispatch�Queue에�추가된�작업을�그룹으로�관리하는�패턴

let��goniGroup�=�DispatchGroup()

DispatchQueue.global().asyncAfter(group:�goniGroup)�{�����self.additionalTask()�}

그룹�생성

Page 43: 초급 개발자 Ios 입문기

GCDDispatch�Queue에�추가된�작업을�그룹으로�관리하는�패턴

let��goniGroup�=�DispatchGroup()

DispatchQueue.global().asyncAfter(group:�goniGroup)�{�����self.additionalTask()�}

그룹에�포함된�작업

Page 44: 초급 개발자 Ios 입문기

GCDDispatch�Queue에�추가된�작업을�그룹으로�관리하는�패턴

let��goniGroup�=�DispatchGroup()

DispatchQueue.global().asyncAfter(group:�goniGroup)�{�����self.additionalTask()�}

그룹에�포함된�모든�작업의�실행이�완료되는�시점이�그룹의�실행이�완료된�시점

Page 45: 초급 개발자 Ios 입문기

GCDDispatch�Queue에�추가된�작업을�그룹으로�관리하는�패턴

let��goniGroup�=�DispatchGroup()

DispatchQueue.global().asyncAfter(group:�goniGroup)�{�����self.additionalTask()�}

goniGroup.wait()

Page 46: 초급 개발자 Ios 입문기

GCDDispatch�Queue에�추가된�작업을�그룹으로�관리하는�패턴

let��goniGroup�=�DispatchGroup()

DispatchQueue.global().asyncAfter(group:�goniGroup)�{�����self.additionalTask()�}

goniGroup.wait() 그룹에�포함된�모든�작업이�완료될�때까지�기다림

Page 47: 초급 개발자 Ios 입문기

GCDDispatch�Queue에�추가된�작업을�그룹으로�관리하는�패턴

let��goniGroup�=�DispatchGroup()

DispatchQueue.global().asyncAfter(group:�goniGroup)�{�����self.additionalTask()�}

goniGroup.wait()

let��latency�=�10

let��result�=�goniGroup.wait(timeout:�DispatchTime(uptimeNanoseconds:�latency))

switch�result�{�case�.success:�����print("success")�case�.timedOut:�����print("timeOut")�}

Page 48: 초급 개발자 Ios 입문기

GCDDispatch�Queue에�추가된�작업을�그룹으로�관리하는�패턴

let��goniGroup�=�DispatchGroup()

goniGroup.wait()

let��latency�=�10

let��result�=�goniGroup.wait(timeout:�DispatchTime(uptimeNanoseconds:�latency))

switch�result�{�case�.success:�����print("success")�case�.timedOut:�����print("timeOut")�}

만료�시간을�직접�지정

DispatchQueue.global().asyncAfter(group:�goniGroup)�{�����self.additionalTask()�}

Page 49: 초급 개발자 Ios 입문기

GCDDispatch�Queue에�추가된�작업을�그룹으로�관리하는�패턴

let��goniGroup�=�DispatchGroup()

DispatchQueue.global().asyncAfter(group:�goniGroup)�{�����self.additionalTask()�}

goniGroup.wait()

let��latency�=�10

let��result�=�goniGroup.wait(timeout:�DispatchTime(uptimeNanoseconds:�latency))

switch�result�{�case�.success:�����print("success")�case�.timedOut:�����print("timeOut")�}

그룹�작업�완료�여부

Page 50: 초급 개발자 Ios 입문기

Reference

Automatic�Reference�CountingSwift�uses�Automatic�Reference�Counting�(ARC)�to�track�and�manage�your�app’s�memory�usage.�In�most�cases,�this�means�that�memory�management�“just�works”�in�Swift,�and�you�do�not�need�to�think�about�memory�management�yourself.�ARC�automatically�frees�up�the�memory�used�by�class�instances�when�those�instances�are�no�longer�needed.�However,�in�a�few�cases�ARC�requires�more�information�about�the�relationships�between�parts�of�your�code�in�order�to�manage�memory�for�you.This�chapter�describes�those�situations�and�shows�how�you�enable�ARC�to�manage�all�of�your�app’s�memory.�Using�ARC�in�Swift�is�very�similar�to�the�approach�described�in�Transitioning�to�ARC�Release�Notes�for�using�ARC�with�Objective-C.�

Page 51: 초급 개발자 Ios 입문기

Reference

Automatic�Reference�CountingSwift�uses�Automatic�Reference�Counting�(ARC)�to�track�and�manage�your�app’s�memory�usage.�In�most�cases,�this�means�that�memory�management�“just�works”�in�Swift,�and�you�do�not�need�to�think�about�memory�management�yourself.�ARC�automatically�frees�up�the�memory�used�by�class�instances�when�those�instances�are�no�longer�needed.�However,�in�a�few�cases�ARC�requires�more�information�about�the�relationships�between�parts�of�your�code�in�order�to�manage�memory�for�you.This�chapter�describes�those�situations�and�shows�how�you�enable�ARC�to�manage�all�of�your�app’s�memory.�Using�ARC�in�Swift�is�very�similar�to�the�approach�described�in�Transitioning�to�ARC�Release�Notes�for�using�ARC�with�Objective-C.�

가끔씩�장문이�튀어나오는�이유

Page 52: 초급 개발자 Ios 입문기

Reference

Automatic�Reference�CountingSwift�uses�Automatic�Reference�Counting�(ARC)�to�track�and�manage�your�app’s�memory�usage.�In�most�cases,�this�means�that�memory�management�“just�works”�in�Swift,�and�you�do�not�need�to�think�about�memory�management�yourself.�ARC�automatically�frees�up�the�memory�used�by�class�instances�when�those�instances�are�no�longer�needed.�However,�in�a�few�cases�ARC�requires�more�information�about�the�relationships�between�parts�of�your�code�in�order�to�manage�memory�for�you.This�chapter�describes�those�situations�and�shows�how�you�enable�ARC�to�manage�all�of�your�app’s�memory.�Using�ARC�in�Swift�is�very�similar�to�the�approach�described�in�Transitioning�to�ARC�Release�Notes�for�using�ARC�with�Objective-C.�

가끔씩�장문이�튀어나오는�이유

Page 53: 초급 개발자 Ios 입문기

사용법은�java.lang.ref�패키지와�비슷하다

Page 54: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

class�Person�{�����let�name:�String�����init(name:�String)�{�self.name�=�name�}�����var�apartment:�Apartment?�����deinit�{�println(“\(name)�is�being�deinitialized")�}�}���class�Apartment�{�����let�number:�Int�����init(number:�Int)�{�self.number�=�number�}�����var�tenant:�Person?�����deinit�{�println("Apartment�#(number)�is�being�deinitialized")�}�}

Page 55: 초급 개발자 Ios 입문기

class�Person�{�����let�name:�String�����init(name:�String)�{�self.name�=�name�}�����var�apartment:�Apartment?�����deinit�{�println(“\(name)�is�being�deinitialized")�}�}���class�Apartment�{�����let�number:�Int�����init(number:�Int)�{�self.number�=�number�}�����var�tenant:�Person?�����deinit�{�println("Apartment�#(number)�is�being�deinitialized")�}�}

ReferenceStrong�Reference�Cycles�Between�Class�Instances

Page 56: 초급 개발자 Ios 입문기

class�Person�{�����let�name:�String�����init(name:�String)�{�self.name�=�name�}�����var�apartment:�Apartment?�����deinit�{�println(“\(name)�is�being�deinitialized")�}�}���class�Apartment�{�����let�number:�Int�����init(number:�Int)�{�self.number�=�number�}�����var�tenant:�Person?�����deinit�{�println("Apartment�#(number)�is�being�deinitialized")�}�}

ReferenceStrong�Reference�Cycles�Between�Class�Instances

Person�인스턴스는�nil로�초기화되는�옵셔널�apartment�속성을�가짐

Page 57: 초급 개발자 Ios 입문기

class�Person�{�����let�name:�String�����init(name:�String)�{�self.name�=�name�}�����var�apartment:�Apartment?�����deinit�{�println(“\(name)�is�being�deinitialized")�}�}���class�Apartment�{�����let�number:�Int�����init(number:�Int)�{�self.number�=�number�}�����var�tenant:�Person?�����deinit�{�println("Apartment�#(number)�is�being�deinitialized")�}�}

ReferenceStrong�Reference�Cycles�Between�Class�Instances

Page 58: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

class�Person�{�����let�name:�String�����init(name:�String)�{�self.name�=�name�}�����var�apartment:�Apartment?�����deinit�{�println(“\(name)�is�being�deinitialized")�}�}���class�Apartment�{�����let�number:�Int�����init(number:�Int)�{�self.number�=�number�}�����var�tenant:�Person?�����deinit�{�println("Apartment�#(number)�is�being�deinitialized")�}�}

Apartment�인스턴스는�nil로�초기화되는�옵셔널�tenant�속성을�가짐

Page 59: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

var�john:�Person?�var�number73:�Apartment?

Page 60: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

var�john:�Person?�var�number73:�Apartment?

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

Page 61: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

각각의�인스턴스를�만들고�변수에�할당

var�john:�Person?�var�number73:�Apartment?

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

Page 62: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

var�john:�Person?�var�number73:�Apartment?

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

두�인스턴스가�만들어지고�할당�된�후�강한�참조�발생

Page 63: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

var�john:�Person?�var�number73:�Apartment?

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

john�변수는�새로운�Person�인스턴스에�강한�참조�

number73�변수는�새로운�Apartment�인스턴스에�강한�참조

Page 64: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

Page 65: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

john!.apartment�=�number73�number73.tenant�=�john

Page 66: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

john!.apartment�=�number73�number73.tenant�=�john

두�인스턴스를�연결하도록�Person는�apartment를�가지고

apartment는�tenant를�가지도록�한다

Page 67: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

john!.apartment�=�number73�number73.tenant�=�john

두�인스턴스를�서로�연결한�후�강한�참조의�모습

Page 68: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

john!.apartment�=�number73�number73.tenant�=�john

즉�두�인스턴스�사이에�강한�참조�순환이�일어난다

Person�인스턴스는�Apartment�인스턴스를�강한�참조

Apartment�인스턴스는�Person�인스턴스를�강한�참조

Page 69: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

john!.apartment�=�number73�number73.tenant�=�john

john�=�nil�number73�=�nil

Page 70: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

john!.apartment�=�number73�number73.tenant�=�john

john�=�nil�number73�=�nil

john과�number73�변수의�강한�참조를�끊을�때

ARC는�인스턴스의�할당을�해체하지�않는다.

Page 71: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

john!.apartment�=�number73�number73.tenant�=�john

john�=�nil�number73�=�nil

강한�참조�순환�때문에�Person와�Apartment�인스턴스의�참조�계수가�0이�아니기�때문

Page 72: 초급 개발자 Ios 입문기

ReferenceStrong�Reference�Cycles�Between�Class�Instances

john�=�Person(name:�"John�Appleseed")�number73�=�Apartment(number:�73)

john!.apartment�=�number73�number73.tenant�=�john

john�=�nil�number73�=�nil

강한�참조�순환�때문에�Person와�Apartment�인스턴스의�참조�계수가�0이�아니기�때문

메모리�누수�현장

Page 73: 초급 개발자 Ios 입문기

안드로이드에서도�이런�일이�빈번한�거�같은데..

Page 74: 초급 개발자 Ios 입문기

ReferenceWeak�References

public�class�WeakHandler�extends�Handler�{����private�final�WeakReference<HandlerMessage>�mActivity;����public�WeakHandler(HandlerMessage�activity)�{��������mActivity�=�new�WeakReference<HandlerMessage>(activity); ����}�����@Override����public�void�handleMessage(Message�msg)�{��������super.handleMessage(msg);��������HandlerMessage�activity�=�(HandlerMessage)�mActivity.get(); ��������if�(�activity�==�null�)�{�return;�} ��������activity.handleMessage(msg);����}}

Page 75: 초급 개발자 Ios 입문기

ReferenceWeak�References

public�class�WeakHandler�extends�Handler�{����private�final�WeakReference<HandlerMessage>�mActivity;����public�WeakHandler(HandlerMessage�activity)�{��������mActivity�=�new�WeakReference<HandlerMessage>(activity); ����}�����@Override����public�void�handleMessage(Message�msg)�{��������super.handleMessage(msg);��������HandlerMessage�activity�=�(HandlerMessage)�mActivity.get(); ��������if�(�activity�==�null�)�{�return;�} ��������activity.handleMessage(msg);����}}

안드로이드에서�Weak�References를�사용한�사례

Page 76: 초급 개발자 Ios 입문기

ReferenceWeak�References

‣ ���MessageQueue�에�있는�Message

Page 77: 초급 개발자 Ios 입문기

ReferenceWeak�References

‣ ���MessageQueue�에�있는�Message

‣ ���Message는�Target�Handler를�강한�참조

Page 78: 초급 개발자 Ios 입문기

ReferenceWeak�References

‣ ���MessageQueue�에�있는�Message

‣ ���Message는�Target�Handler를�강한�참조

‣ ���Activity가�종료되어도�MessageQueue에�Message가�있다면

Page 79: 초급 개발자 Ios 입문기

ReferenceWeak�References

‣ ���MessageQueue�에�있는�Message

‣ ���Message는�Target�Handler를�강한�참조

‣ ���Handler�는�GC�되지�않음

‣ ���Activity가�종료되어도�MessageQueue에�Message가�있다면

Page 80: 초급 개발자 Ios 입문기

ReferenceWeak�References

‣ ���MessageQueue�에�있는�Message

‣ ���Message는�Target�Handler를�강한�참조

‣ ���Handler�는�GC�되지�않음

‣ ���자연스레�Handler�가�참조하는�Activity�도�GC�가�되지�않음

‣ ���Activity가�종료되어도�MessageQueue에�Message가�있다면

Page 81: 초급 개발자 Ios 입문기

ReferenceWeak�References

‣ ���MessageQueue�에�있는�Message

‣ ���Message는�Target�Handler를�강한�참조

‣ ���Handler�는�GC�되지�않음

‣ ���Handler�관련��Message가�모두�소비가�되고�나서야�GC

‣ ���자연스레�Handler�가�참조하는�Activity�도�GC�가�되지�않음

‣ ���Activity가�종료되어도�MessageQueue에�Message가�있다면

Page 82: 초급 개발자 Ios 입문기

ReferenceWeak�References

public�class�WeakHandler�extends�Handler�{����private�final�WeakReference<HandlerMessage>�mActivity;����public�WeakHandler(HandlerMessage�activity)�{��������mActivity�=�new�WeakReference<HandlerMessage>(activity); ����}�����@Override����public�void�handleMessage(Message�msg)�{��������super.handleMessage(msg);��������HandlerMessage�activity�=�(HandlerMessage)�mActivity.get(); ��������if�(�activity�==�null�)�{�return;�} ��������activity.handleMessage(msg);����}}

Page 83: 초급 개발자 Ios 입문기

ReferenceWeak�References

public�class�WeakHandler�extends�Handler�{����private�final�WeakReference<HandlerMessage>�mActivity;����public�WeakHandler(HandlerMessage�activity)�{��������mActivity�=�new�WeakReference<HandlerMessage>(activity); ����}�����@Override����public�void�handleMessage(Message�msg)�{��������super.handleMessage(msg);��������HandlerMessage�activity�=�(HandlerMessage)�mActivity.get(); ��������if�(�activity�==�null�)�{�return;�} ��������activity.handleMessage(msg);����}}

Activity에�대해�강한�참조가�아니라�약한�참조를�한다

Page 84: 초급 개발자 Ios 입문기

ReferenceWeak�References

public�class�WeakHandler�extends�Handler�{����private�final�WeakReference<HandlerMessage>�mActivity;����public�WeakHandler(HandlerMessage�activity)�{��������mActivity�=�new�WeakReference<HandlerMessage>(activity); ����}�����@Override����public�void�handleMessage(Message�msg)�{��������super.handleMessage(msg);��������HandlerMessage�activity�=�(HandlerMessage)�mActivity.get(); ��������if�(�activity�==�null�)�{�return;�} ��������activity.handleMessage(msg);����}}

Activity에�대해�강한�참조가�아니라�약한�참조를�한다

Message�Queue에�해당�handler�관련된�message�가�있어도,�Activity�는�GC

Page 85: 초급 개발자 Ios 입문기

ReferenceWeak�References

public�class�WeakHandler�extends�Handler�{����private�final�WeakReference<HandlerMessage>�mActivity;����public�WeakHandler(HandlerMessage�activity)�{��������mActivity�=�new�WeakReference<HandlerMessage>(activity); ����}�����@Override����public�void�handleMessage(Message�msg)�{��������super.handleMessage(msg);��������HandlerMessage�activity�=�(HandlerMessage)�mActivity.get(); ��������if�(�activity�==�null�)�{�return;�} ��������activity.handleMessage(msg);����}}

Activity에�대해�강한�참조가�아니라�약한�참조를�한다

Message�Queue에�해당�handler�관련된�message�가�있어도,�Activity�는�GC

약한�참조로�메모리�누수�문제�해결

Page 86: 초급 개발자 Ios 입문기

ReferenceWeak�References

관련�지식을�더�알고�싶다면...

&

D2�Java�Reference와�GC

객체�사용후�null�할당!

Java:�difference�between�strong/soft/weak/phantom�reference

Page 87: 초급 개발자 Ios 입문기

다시�스위프트로�돌아갑시다

Page 88: 초급 개발자 Ios 입문기

ReferenceWeak�References

class�Person�{�����let�name:�String�����init(name:�String)�{�self.name�=�name�}�����var�apartment:�Apartment?�����deinit�{�println(“\(name)�is�being�deinitialized")�}�}���class�Apartment�{�����let�number:�Int�����init(number:�Int)�{�self.number�=�number�}�����weak�tenant:�Person?�����deinit�{�println("Apartment�#(number)�is�being�deinitialized")�}�}

Page 89: 초급 개발자 Ios 입문기

class�Person�{�����let�name:�String�����init(name:�String)�{�self.name�=�name�}�����var�apartment:�Apartment?�����deinit�{�println(“\(name)�is�being�deinitialized")�}�}���class�Apartment�{�����let�number:�Int�����init(number:�Int)�{�self.number�=�number�}�����weak�tenant:�Person?�����deinit�{�println("Apartment�#(number)�is�being�deinitialized")�}�}

ReferenceWeak�References

약한�참조는�참조한�다른�인스턴스는�참조�계수가�증가하지�않는다

Page 90: 초급 개발자 Ios 입문기

class�Person�{�����let�name:�String�����init(name:�String)�{�self.name�=�name�}�����var�apartment:�Apartment?�����deinit�{�println(“\(name)�is�being�deinitialized")�}�}���class�Apartment�{�����let�number:�Int�����init(number:�Int)�{�self.number�=�number�}�����weak�tenant:�Person?�����deinit�{�println("Apartment�#(number)�is�being�deinitialized")�}�}

ReferenceWeak�References

약한�참조는�참조한�다른�인스턴스는�참조�계수가�증가하지�않는다

약한�참조하는�인스턴스는�옵셔널�타입

Page 91: 초급 개발자 Ios 입문기

ReferenceWeak�References

class�Person�{�����let�name:�String�����init(name:�String)�{�self.name�=�name�}�����var�apartment:�Apartment?�����deinit�{�println(“\(name)�is�being�deinitialized")�}�}���class�Apartment�{�����let�number:�Int�����init(number:�Int)�{�self.number�=�number�}�����weak�tenant:�Person?�����deinit�{�println("Apartment�#(number)�is�being�deinitialized")�}�}

약한�참조는�참조한�다른�인스턴스는�참조�계수가�증가하지�않는다

약한�참조하는�인스턴스는�옵셔널�타입

ARC는�인스턴스�참조가�할당�해제될�때,�자동적으로�약한�참조는�nil로�설정

Page 92: 초급 개발자 Ios 입문기

ReferenceWeak�References

class�Apartment�{�����let�number:�Int�����init(number:�Int)�{�self.number�=�number�}�����weak�tenant:�Person?�����deinit�{�println("Apartment�#(number)�is�being�deinitialized")�}�}

Person�인스턴스는�강한�참조하는�Apartment�인스턴스를�가지지만

Apartment�인스턴스는�약한�참조하는�Person�인스턴스�가짐

Page 93: 초급 개발자 Ios 입문기

ReferenceWeak�References

john�=�nil

Page 94: 초급 개발자 Ios 입문기

ReferenceWeak�References

john�=�nil

Person�인스턴스에�대한�강한�참조가�더이상�없기에�인스턴스는�할당�해제

Page 95: 초급 개발자 Ios 입문기

ReferenceWeak�References

john�=�nil

Person�인스턴스에�대한�강한�참조가�더이상�없기에�인스턴스는�할당�해제

약한�참조로�강한�참조�순환�해결

Page 96: 초급 개발자 Ios 입문기

Reference

ARC�and�Memory�Management�in�Swift

Automatic�Reference�Counting

관련�지식을�더�알고�싶다면...

Page 97: 초급 개발자 Ios 입문기

개발�시작

Page 98: 초급 개발자 Ios 입문기

Architecture�Pattern

‣ ���MVC

‣ ���MVP

‣ ���MVVM

‣ ���VIPER

Page 99: 초급 개발자 Ios 입문기

Architecture�Pattern

‣ ���MVC

‣ ���MVP

‣ ���MVVM

‣ ���VIPER

‣ ���시간은�없는데�너무�많다.

Page 100: 초급 개발자 Ios 입문기

Architecture�Pattern

‣ ���MVC

‣ ���MVP

‣ ���MVVM

‣ ���VIPER

안드로이드에서�해본�거

‣ ���시간은�없는데�너무�많다.

Page 101: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP

Android�MVP�=�RxJava�&�RxAndroid�+�Dagger�2�+�Retrofit�2�+�Butterknife...�

IOS�MVP�=�RxSwift�&�RxCocoa�+�Swinject�&��SwinjectStoryboard�+�Alamofire...�

대략�이렇게�구성

Page 102: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP

Android�MVP�=�RxJava�&�RxAndroid�+�Dagger�2�+�Retrofit�2�+�Butterknife...�

IOS�MVP�=�RxSwift�&�RxCocoa�+�Swinject�&��SwinjectStoryboard�+�Alamofire...�

대략�이렇게�구성

네트워크는�사용하지�않았음

Page 103: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP

Page 104: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP

View:�일반적으로�ViewController�Presenter에서�받은�데이터를�사용자에게�표시하는�역할�사용자와�상호�작용이나�입력을�처리하고,�필요에�따라�Presenter에�위임

Page 105: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP

View:�일반적으로�ViewController�Presenter에서�받은�데이터를�사용자에게�표시하는�역할�사용자와�상호�작용이나�입력을�처리하고,�필요에�따라�Presenter에�위임

Presenter:�DataManager에서�제공하는�Observable을�구독���DataManager에서�반환한�데이터를�적절하게�처리하고�이를�표시하기�위해���View에서�필요한�함수�호출

Page 106: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP

View:�일반적으로�ViewController�Presenter에서�받은�데이터를�사용자에게�표시하는�역할�사용자와�상호�작용이나�입력을�처리하고,�필요에�따라�Presenter에�위임

Presenter:�DataManager에서�제공하는�Observable을�구독���DataManager에서�반환한�데이터를�적절하게�처리하고�이를�표시하기�위해���View에서�필요한�함수�호출

DataManager:�아키텍처의�핵심부분,�모든�서비스�or�헬퍼에�대한�참조를�가지고�있으며�

서비스�or�헬퍼의�데이터를�결합,�변환,�필터링하여�Presenter에서�원하는�출력을�생성

이를�사용하여�Presenter의�요청에�대응

Page 107: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP

View:�일반적으로�ViewController�Presenter에서�받은�데이터를�사용자에게�표시하는�역할�사용자와�상호�작용이나�입력을�처리하고,�필요에�따라�Presenter에�위임

Presenter:�DataManager에서�제공하는�Observable을�구독���DataManager에서�반환한�데이터를�적절하게�처리하고�이를�표시하기�위해���View에서�필요한�함수�호출

DataManager:�아키텍처의�핵심부분,�모든�서비스�or�헬퍼에�대한�참조를�가지고�있으며�

서비스�or�헬퍼의�데이터를�결합,�변환,�필터링하여�Presenter에서�원하는�출력을�생성

이를�사용하여�Presenter의�요청에�대응

Model:�API,�DB�접근,�특정�비지니스�로직�등�다양하며�DataManager에�의해�사용

Page 108: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP�-�View

protocol�ShareMvpView:�Mvpview�{����������func�playVideo(mergedVideofileUrl:�URL?)����������func�createActivityIndicatory(uiView:�UIView)�->�(UIActivityIndicatorView,�UIView)����������func�dimissShareViewController()����������func�showCompleteDialog()����������func�showShareSheet(videoUrl:�URL)����������func�enabledSaveButton(isEnabled:�Bool)�}

ViewController에�구현될�프로토콜

Presenter에서�View�갱신을�위해�작성된�함수

Page 109: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP�-�View

ViewController에�ShareMvpView�프로토콜�구현

extension�ShareViewController:�ShareMvpView�{

//......��

func�dimissShareViewController()�{���������self.dismiss(animated:�true,�completion:�nil);�}�

func�showCompleteDialog()�{���������self.present(PopupDialog(title:�"Save�is�complete.",�message:�nil),��animated:�true,�completion:�nil)�}�����}

Page 110: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP�-�View

ViewController에�ShareMvpView�프로토콜�구현

extension�ShareViewController:�ShareMvpView�{

//......��

func�dimissShareViewController()�{���������self.dismiss(animated:�true,�completion:�nil);�}�

func�showCompleteDialog()�{���������self.present(PopupDialog(title:�"Save�is�complete.",�message:�nil),��animated:�true,�completion:�nil)�}�����}

구현된�함수는��View갱신을�위해�Presenter에서�호출�된다.

Page 111: 초급 개발자 Ios 입문기

Architecture�Pattern

let�saveButtonEvent�=�saveButton.rx.controlEvent(UIControlEvents.touchUpInside)�presenter.saveButtonClickEvent(event:�saveButtonEvent)����������let�homeButtonEvent�=�homeButton.rx.controlEvent(UIControlEvents.touchUpInside)�presenter.homeButtonClickEvent(event:�homeButtonEvent)����������let�shareButtonEvent�=�shareButton.rx.controlEvent(UIControlEvents.touchUpInside)�presenter.shareButtonClickEvent(event:�shareButtonEvent)

무작정�MVP�-�View

View에서�발생하는�유저액션을�Presenter에�위임합니다.

Page 112: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP�-�Presenter

func�homeButtonClickEvent(event:�ControlEvent<Void>)�{���������event.debounce(0.2,�scheduler:�MainScheduler.instance)�������������.bindNext�{�����������������self.view?.dimissShareViewController()���������}.addDisposableTo(bag)�}

func�saveButtonClickEvent(event:�ControlEvent<Void>)�{���������event.debounce(0.2,�scheduler:�MainScheduler.instance)�������������.bindNext�{�����������������self.saveVideoWithURL()�{�

�����self.view?.showCompleteDialog()�����������������}���������}.addDisposableTo(bag)�}

유저액션을�위임�받은�Presenter

Page 113: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP�-�Presenter

func�homeButtonClickEvent(event:�ControlEvent<Void>)�{���������event.debounce(0.2,�scheduler:�MainScheduler.instance)�������������.bindNext�{�����������������self.view?.dimissShareViewController()���������}.addDisposableTo(bag)�}

func�saveButtonClickEvent(event:�ControlEvent<Void>)�{���������event.debounce(0.2,�scheduler:�MainScheduler.instance)�������������.bindNext�{�����������������self.saveVideoWithURL()�{�

�����self.view?.showCompleteDialog()�����������������}���������}.addDisposableTo(bag)�}

유저액션을�위임�받은�Presenter

필요한�로직을�수행하고�View�update를�위해�ShareMvpView�의�함수�호출

Page 114: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP�-�DataManager

class�DataMenager�{�����//.....�����private�let�musicService:�MusicService�����private�let�videoService:�VideoService������//�@inject�����init(musicService:�MusicService,�videoService:�VideoService)�{�

�self.musicService�=��musicService��self.videoService�=��videoService�

}�

����public�func�getMusics()�->�Observable<MPMediaItem>�{�������return�musicService.getMusics()�

����}�����//.....��}

Page 115: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP�-�DataManager

class�DataMenager�{�����//.....�����private�let�musicService:�MusicService�����private�let�videoService:�VideoService������//�@inject�����init(musicService:�MusicService,�videoService:�VideoService)�{�

�self.musicService�=��musicService��self.videoService�=��videoService�

}�

����public�func�getMusics()�->�Observable<MPMediaItem>�{�������return�musicService.getMusics()�

����}�����//.....��}

모든�서비스에�대한�참조를�가짐

Page 116: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP�-�DataManager

class�DataMenager�{�����//.....�����private�let�musicService:�MusicService�����private�let�videoService:�VideoService������//�@inject�����init(musicService:�MusicService,�videoService:�VideoService)�{�

�self.musicService�=��musicService��self.videoService�=��videoService�

}�

����public�func�getMusics()�->�Observable<MPMediaItem>�{�������return�musicService.getMusics()�

����}�����//.....��}

모든�서비스에�대한�참조를�가짐

Presenter에서�원하는�출력(데이터)을�서비스에�요청하여�반환

Page 117: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP�-�Model

class�VideoService�{�����//.....�����public�func�getLastVideoThumbnail()�->�Observable<UIImage>�{���������return�Observable<UIImage>.create{�observableOfUIImage�in�������������if�let�lastVideoPHAsset�=�self.getLastPhAsset()�{�����������������PHImageManager..�{�image,�_�in���������������������if�let�image�=�image�{�������������������������observableOfUIImage.on(Event.next(image))�������������������������observableOfUIImage.on(Event.completed)���������������������}�else�{�������������������������observableOfUIImage.on(Event.error(NSError(domain:�“video..”���������������������������������������������}�����������������}�������������}�������������return�Disposables.create()���������}�����}�}

Page 118: 초급 개발자 Ios 입문기

Architecture�Pattern무작정�MVP�-�Model

class�VideoService�{�����//.....�����public�func�getLastVideoThumbnail()�->�Observable<UIImage>�{���������return�Observable<UIImage>.create{�observableOfUIImage�in�������������if�let�lastVideoPHAsset�=�self.getLastPhAsset()�{�����������������PHImageManager..�{�image,�_�in���������������������if�let�image�=�image�{�������������������������observableOfUIImage.on(Event.next(image))�������������������������observableOfUIImage.on(Event.completed)���������������������}�else�{�������������������������observableOfUIImage.on(Event.error(NSError(domain:�“video..”���������������������������������������������}�����������������}�������������}�������������return�Disposables.create()���������}�����}�}

DataManager에서�요청하는�데이터에�대한�Observable을�반환

Page 119: 초급 개발자 Ios 입문기

Permission권한�처리

func�showAlert(_�permission:�Permission,�_�title:�String)�{�������������let�alert�=�permission.prePermissionAlert�������������alert.title�=�"Please�allow�access�to�your�\(title)"�������������alert.message�=�nil�������������alert.cancel�=�"Cancel"�������������alert.settings�=�"Settings"���������}����

Page 120: 초급 개발자 Ios 입문기

Permission권한�처리

func�showAlert(_�permission:�Permission,�_�title:�String)�{�������������let�alert�=�permission.prePermissionAlert�������������alert.title�=�"Please�allow�access�to�your�\(title)"�������������alert.message�=�nil�������������alert.cancel�=�"Cancel"�������������alert.settings�=�"Settings"���������}����

권한을�요청하고�설정화면으로�이동시키는�Alert�코드

Page 121: 초급 개발자 Ios 입문기

Permission권한�처리

권한을�요청하고�거부하면�재요청�반복,�허가하면�다음�권한을�요청

이후�모든�권한이�허가되면�인트로�화면에서�이동하는�재귀호출�코드

func�requestAccess(_�permission:�Permission,�title:�String,�_�complete:�@escaping�()�->�Void)�{�����������������showAlert(permission,�title)�����������������permission.request{�status�in���������������������switch�status�{���������������������case�.authorized:�������������������������complete()�������������������������break���������������������default:�������������������������requestAccess(permission,�title:�title,�complete)���������������������}�����������������}�������������}

Page 122: 초급 개발자 Ios 입문기

Permission권한�처리

권한을�요청하고�거부하면�재요청�반복,�허가하면�다음�권한을�요청

이후�모든�권한이�허가되면�인트로�화면에서�이동하는�재귀호출�코드

func�requestAccess(_�permission:�Permission,�title:�String,�_�complete:�@escaping�()�->�Void)�{�����������������showAlert(permission,�title)�����������������permission.request{�status�in���������������������switch�status�{���������������������case�.authorized:�������������������������complete()�������������������������break���������������������default:�������������������������requestAccess(permission,�title:�title,�complete)���������������������}�����������������}�������������}

요청�거부시�재요청

Page 123: 초급 개발자 Ios 입문기

Permission권한�처리

권한을�요청하고�거부하면�재요청�반복,�허가하면�다음�권한을�요청

이후�모든�권한이�허가되면�인트로�화면에서�이동하는�재귀호출�코드

func�requestAccess(_�permission:�Permission,�title:�String,�_�complete:�@escaping�()�->�Void)�{�����������������showAlert(permission,�title)�����������������permission.request{�status�in���������������������switch�status�{���������������������case�.authorized:�������������������������complete()�������������������������break���������������������default:�������������������������requestAccess(permission,�title:�title,�complete)���������������������}�����������������}�������������}

함수는�레퍼런스

기저사례�

허가해주면�완료�함수�호출

Page 124: 초급 개발자 Ios 입문기

Permission권한�처리

권한을�요청하고�거부하면�재요청�반복,�허가하면�다음�권한을�요청

이후�모든�권한이�허가되면�인트로�화면에서�이동하는�재귀호출�코드

requestAccess(.camera,�title:�"camera")�{�������������requestAccess(.mediaLibrary,�title:�"mediaLibrary")�{�����������������requestAccess(.microphone,�title:�"microphone")�{���������������������requestAccess(.photos,�title:�"photos")�{�������������������������DispatchQueue.main.async�{����������������������������self.present(self.mainViewController,�animated:�true,�completion:�nil)�������������������������}���������������������}�����������������}�������������}���������}

Page 125: 초급 개발자 Ios 입문기

Permission권한�처리

권한을�요청하고�거부하면�재요청�반복,�허가하면�다음�권한을�요청

이후�모든�권한이�허가되면�인트로�화면에서�이동하는�재귀호출�코드

requestAccess(.camera,�title:�"camera")�{�������������requestAccess(.mediaLibrary,�title:�"mediaLibrary")�{�����������������requestAccess(.microphone,�title:�"microphone")�{���������������������requestAccess(.photos,�title:�"photos")�{�������������������������DispatchQueue.main.async�{����������������������������self.present(self.mainViewController,�animated:�true,�completion:�nil)�������������������������}���������������������}�����������������}�������������}���������}

해괴하게�작성해서�죄송합니다

Page 126: 초급 개발자 Ios 입문기

‣ ��SwinjectStoryboard�등�IOS�확장�가능

SwInjectDependency�Injection�library

‣ ��Dagger2�보다�직관적

‣ ��그래프를�통해�의존성�주입

https://github.com/Swinject/Swinject

Page 127: 초급 개발자 Ios 입문기

RxSwiftReactive�Programming�library

‣ ��기존�Rx유저라면�빠르게�적응

‣ ��손쉬운�동시성과�비동기�실행

‣ ��콜백�지옥에서�벗어나기�위한�방법

https://github.com/ReactiveX/RxSwift

Page 128: 초급 개발자 Ios 입문기

‣ ��Swift�커뮤니티나�Apple�규칙�반영

‣ ��선호하는�규칙을�세밀하게�반영�가능

‣ ��코딩�스타일에�대한�일관성�유지

Swift�Lintlinter�library

https://github.com/realm/SwiftLint

Page 129: 초급 개발자 Ios 입문기

앞으로�공부할�것들

Page 130: 초급 개발자 Ios 입문기

VIPERClean�Architecture

‣ ���View:�displays�what�it�is�told�to�by�the�Presenter�and�relays�user�input�back�to�the�Presenter.

‣ ���Interactor:�contains�the�business�logic�as�specified�by�a�use�case.

‣ ���Presenter:�contains�view�logic�for�preparing�content�for�display�(as�received�from�the�Interactor)�and�for�reacting�to�user�inputs�(by�requesting�new�data�from�the�Interactor).

‣ ���Entity:�contains�basic�model�objects�used�by�the�Interactor.

‣ ���Routing:�contains�navigation�logic�for�describing�which�screens�are�shown�in�which�order.

https://www.objc.io/issues/13-architecture/viper/

Page 131: 초급 개발자 Ios 입문기

POPProtocol�oriented�programming

�•�범용적인�사용�� ◦�클래스,�구조체,�열거형�등등�모든�타입에�적용�가능�� ◦�제네릭과�결합하면�더욱�파급적인�효과�

�•�상속의�한계�극복�� ◦�특정�상속�체계에�종속되지�않음�� ◦�프레임워크에�종속적이지�않게�재활용�가능�

�•�적은�시스템�비용�� ◦�Reference�type�cost�>�Value�type�cost�

�•�용이한�테스트�� ◦�GUI�코드�없이도�수월한�테스트�

https://realm.io/kr/news/protocol-oriented-programming-in-swift/

Page 132: 초급 개발자 Ios 입문기

Swift�CompilerLLVM�&�Swiftc

�•�LLVM�� ◦�LLVM이란�Low-Level�Virtual�Machine�� ◦�Chris�Arthur�Lattner의�2002년�석사�논문에서�시작�� ◦�오픈�소스로�컴파일러를�제작�� ◦�Apple에서�후원한�컴파일러�� ◦�2007년도에�Apple에�팀�합병

�•�Swiftc�� ◦�LLVM과�거의�유사하나�최적화를�하는�2단계�더�있음�� ◦�프론트엔드는�swift�파일을�읽에서�토큰�처리와�의미분석�

중간언어�생성�및�타입�검사를�함�� ◦�중간�언어�최적화는�SIL�수준에서�분석과�변환,�ARC�처리�

와�Generic�코드�타입�지정�� ◦이후�LLVM�IR�수준을�최적화하고�타깃�기계에�맞는�binary�������생성

https://realm.io/kr/news/swift-internals-llvm-type-system-swift-foundation/

Page 133: 초급 개발자 Ios 입문기

마지막으로IOS는�문서화가�정말�잘�되어있습니다.

커버해야하는�기기�수�또한�많지�않기에�IOS로�앱�개발을�시작하는�건�나쁘지�않은�선택�같습니다.

Page 134: 초급 개발자 Ios 입문기

마지막으로

이번�개발은�안드로이드에서의�경험에�의존하여�비전문적(야매)으로�진행되었습니다.

경험이�큰�도움이�되긴�했지만,�진행속도에�맞추기�위해�얕게�공부한�부분을�다시�공부해야�합니다.

IOS는�문서화가�정말�잘�되어있습니다.

커버해야하는�기기�수�또한�많지�않기에�IOS로�앱�개발을�시작하는�건�나쁘지�않은�선택�같습니다.

Page 135: 초급 개발자 Ios 입문기

마지막으로

이번�개발은�안드로이드에서의�경험에�의존하여�비전문적(야매)으로�진행되었습니다.

1년간�안드로이드와�마음이�많이�멀어져�있었는데�이번�계기로�더욱�멀어졌습니다.

Swift�&�IOS�정말�좋음!��

경험이�큰�도움이�되긴�했지만,�진행속도에�맞추기�위해�얕게�공부한�부분을�다시�공부해야�합니다.

IOS는�문서화가�정말�잘�되어있습니다.

커버해야하는�기기�수�또한�많지�않기에�IOS로�앱�개발을�시작하는�건�나쁘지�않은�선택�같습니다.

Page 136: 초급 개발자 Ios 입문기

마지막으로

개인적으로�Realm의�Let�Swift!�세션에서�많은�도움을�받았습니다.

이번�개발은�안드로이드에서의�경험에�의존하여�비전문적(야매)으로�진행되었습니다.

1년간�안드로이드와�마음이�많이�멀어져�있었는데�이번�계기로�더욱�멀어졌습니다.

경험이�큰�도움이�되긴�했지만,�진행속도에�맞추기�위해�얕게�공부한�부분을�다시�공부해야�합니다.

IOS는�문서화가�정말�잘�되어있습니다.

커버해야하는�기기�수�또한�많지�않기에�IOS로�앱�개발을�시작하는�건�나쁘지�않은�선택�같습니다.

Swift�&�IOS�정말�좋음!��

특히�������������������������������������는�스위프트를�사용한다면�한�번쯤�읽어보시면�좋을�것�같습니다.스위프트�성능�이해하기

Page 137: 초급 개발자 Ios 입문기

마지막으로

빨리�제가�Swift로�mac�용�앱을�개발하는�날이�오면�좋겠습니다.�(모바일개발을�벗어나고�싶음)

개인적으로�Realm의�Let�Swift!�세션에서�많은�도움을�받았습니다.

이번�개발은�안드로이드에서의�경험에�의존하여�비전문적(야매)으로�진행되었습니다.

1년간�안드로이드와�마음이�많이�멀어져�있었는데�이번�계기로�더욱�멀어졌습니다.

경험이�큰�도움이�되긴�했지만,�진행속도에�맞추기�위해�얕게�공부한�부분을�다시�공부해야�합니다.

IOS는�문서화가�정말�잘�되어있습니다.

커버해야하는�기기�수�또한�많지�않기에�IOS로�앱�개발을�시작하는�건�나쁘지�않은�선택�같습니다.

Swift�&�IOS�정말�좋음!��

특히�������������������������������������는�스위프트를�사용한다면�한�번쯤�읽어보시면�좋을�것�같습니다.스위프트�성능�이해하기

Page 138: 초급 개발자 Ios 입문기

마지막으로

아직�제가�무엇을�모르는지도�모르는�상태입니다.�

하지만�빠른�시일�내에�무엇을�모르는지는�아는�단계까지�나아갈�수�있을�것�같습니다.

개인적으로�Realm의�Let�Swift!�세션에서�많은�도움을�받았습니다.

이번�개발은�안드로이드에서의�경험에�의존하여�비전문적(야매)으로�진행되었습니다.

1년간�안드로이드와�마음이�많이�멀어져�있었는데�이번�계기로�더욱�멀어졌습니다.

경험이�큰�도움이�되긴�했지만,�진행속도에�맞추기�위해�얕게�공부한�부분을�다시�공부해야�합니다.

IOS는�문서화가�정말�잘�되어있습니다.

커버해야하는�기기�수�또한�많지�않기에�IOS로�앱�개발을�시작하는�건�나쁘지�않은�선택�같습니다.

빨리�제가�Swift로�mac�용�앱을�개발하는�날이�오면�좋겠습니다.�(모바일개발을�벗어나고�싶음)

Swift�&�IOS�정말�좋음!��

특히�������������������������������������는�스위프트를�사용한다면�한�번쯤�읽어보시면�좋을�것�같습니다.스위프트�성능�이해하기