116 ios 9 핵심노트야곰 지음
116 ios 9 핵심노트야곰 지음
표지사진변진남이책의표지는변진남님이보내주신풍경사진을담았습니다. 리얼타임은독자의시선을담은풍경사진을책표지로보여주고자합니다. 사진보내기 ebookwriter@hanbit.co.kr ios 9 핵심노트 초판발행 2015 년 11 월 16 일 지은이야곰 / 펴낸이김태헌펴낸곳한빛미디어 ( 주 ) / 주소서울시마포구양화로 7길 83 한빛미디어 ( 주 ) IT출판부전화 02-325-5544 / 팩스 02-336-7124 등록 1999년 6월 24일제10-1779호 ISBN 978-89-6848-754-5 15000 / 정가 12,000원 총괄배용석 / 책임편집김창수 / 기획 편집정지연 / 교정이미연디자인표지 / 내지여동일마케팅송경석 / 영업김형진, 김진불, 조유미 이책에대한의견이나오탈자및잘못된내용에대한수정정보는한빛미디어 ( 주 ) 의홈페이지나아래이메일로알려주십시오. 한빛미디어홈페이지 www.hanbit.co.kr / 이메일 ask@hanbit.co.kr Published by HANBIT Media, Inc. Printed in Korea Copyright c 2015 야곰 & HANBIT Media, Inc. 이책의저작권은야곰과한빛미디어 ( 주 ) 에있습니다. 저작권법에의해보호를받는저작물이므로무단복제및무단전재를금합니다. 지금하지않으면할수없는일이있습니다. 책으로펴내고싶은아이디어나원고를메일 (ebookwriter@hanbit.co.kr) 로보내주세요. 한빛미디어 ( 주 ) 는여러분의소중한경험과지식을기다리고있습니다.
저자소개 지은이 _ 야곰 yagom s blog(http://blog.yagom.net/) 를운영하는 ios 개발블로거이자 ios 프로그래머로, 아이폰개발자커뮤니티인맥부기 (http://cafe.naver.com/mcbugi) 에서강좌를연재중이다. 컴퓨터교육을전공했으며비전공자와학생들에게컴퓨터지식을더쉽고재미있게알리는데관심이많다. 2010년부터 ios 개발을시작해현재까지도계속 ios 관련개발에열정을쏟고있다. 내일걱정은모레하는것이좋다고생각하며스스로긍정적인마음가짐을빼면시체라고말한다. 스스로개발자라고생각하지않는것을보면괴짜임이틀림없다. 무엇보다여행과요리를좋아한다.
저자서문 스마트폰의수요가늘어남에따라사용자가필요한기능도많아졌습니다. 그에발맞추어모바일운영체제도제각기발전을거듭하고있고 ios도사용자의편의를위해점점더빠르게 OS를진화해가고있습니다. 이책에 ios 9에서추가된모든기능을담지는못했지만, 공통으로사용할수있는굵직굵직한신규기능위주로정리해보았습니다. 01 재빠르게변하는 OS에발맞추어나가는데작지만도움이되면좋겠습니다. 책을읽다가부족한부분은언제든지블로그 (http://blog.yagom.net) 또는이메일 (yagomsoft@me.com) 로연락해주세요. 항상믿고응원해주시며사랑을아끼지않는가족과동료, 이책의편집을멋지게해주신한빛미디어정지연님, 함께응원해주신조희진님, 이중민님께무한한감사의말씀을전합니다. 사랑합니다. 01 ios 9 에관한더많은정보를얻으려면 https://developer.apple.com/ios/ 를방문해보세요.
대상독자및참고사항 초급초중급중급중고급고급 이책은이미 ios 개발경험이있는개발자중에서빠르게 ios 9의기능과예제를훑어보고자하는독자를대상으로합니다. Xcode 사용법과 Cocoa Touch 프레임워크를이해하고있으며관련키워드들을이해할수있어야합니다. 또한, Swift 기본문법을알고있어야합니다. ios를처음접하거나 Cocoa Touch 프레임워크에관한전반적인이해가없는독자는소화하기어려울수있습니다. 장마다해당기능을간단히설명하고예제를함께수록하였습니다. 이책의예제는 Xcode 7.0, ios SDK 9.0, Swift 2.0 버전기준으로작성되었으며, 언어와 ios SDK, Xcode 버전에따라코드가동작하지않을수도있습니다. 예제는다음주소에서다운로드하세요. 예제에사용한이미지파일은다음주소의 images 폴더에있습니다. https://bitbucket.org/yagom/ios9_yagom
한빛리얼타임 한빛리얼타임은 IT 개발자를위한전자책입니다. 요즘 IT 업계에는하루가멀다하고수많은기술이나타나고사라져갑니다. 인 터넷을아무리뒤져도조금이나마정리된정보를찾기도쉽지않습니다. 또한, 잘정리되어책으로나오기까지는오랜시간이걸립니다. 어떻게하면조금이라 도더유용한정보를빠르게얻을수있을까요? 어떻게하면남보다조금더빨 리경험하고습득한지식을공유하고발전시켜나갈수있을까요? 세상에는수 많은종이책이있습니다. 그리고그종이책을그대로옮긴전자책도많습니다. 전자책에는전자책에적합한콘텐츠와전자책의특성을살린형식이있다고생 각합니다. 한빛이지금생각하고추구하는, 개발자를위한리얼타임전자책은이렇습니다. 1 2 ebook First - 빠르게변화하는 IT 기술에대해핵심적인정보를신속하게제공합니다 500페이지가까운분량의잘정리된도서 ( 종이책 ) 가아니라, 핵심적인내용을빠르게전달하기위해조금은거칠지만 100페이지내외의전자책전용으로개발한서비스입니다. 독자에게는새로운정보를빨리얻을기회가되고, 자신이먼저경험한지식과정보를책으로펴내고싶지만너무바빠서엄두를못내는선배, 전문가, 고수분에게는좀더쉽게집필할수있는기회가될수있으리라생각합니다. 또한, 새로운정보와지식을빠르게전달하기위해 O'Reilly의전자책번역서비스도하고있습니다. 무료로업데이트되는전자책전용서비스입니다 종이책으로는기술의변화속도를따라잡기가쉽지않습니다. 책이일정분량이상으로집필되고정리되어나오는동안기술은이미변해있습니다. 전자책으로출간된이후에도버전업을통해중요한기술적변화가있거나저자 ( 역자 ) 와독자가소통하면서보완하여발전된노하우가정리되면구매하신분께무료로업데이트해드립니다.
3 4 독자의편의를위해 DRM-Free 로제공합니다 구매한전자책을다양한 IT 기기에서자유롭게활용할수있도록 DRM-Free PDF 포맷으로제공합니다. 이는독자여러분과한빛이생각하고추구하는전자책을만들어나가기위해독자여러분이언제어디서어떤기기를사용하더라도편리하게전자책을볼수있도록하기위함입니다. 전자책환경을고려한최적의형태와디자인에담고자노력했습니다종이책을그대로옮겨놓아가독성이떨어지고읽기어려운전자책이아니라, 전자책의환경에가능한한최적화하여쾌적한경험을드리고자합니다. 링크등의기능을적극적으로이용할수있음은물론이고글자크기나행간, 여백등을전자책에가장최적화된형태로새롭게디자인하였습니다. 앞으로도독자여러분의충고에귀기울이며지속해서발전시켜나가겠습니다. 지금보시는전자책에소유권한을표시한문구가없거나타인의소유권한을표시한문구가있다면위법하게사용하고있을가능성이큽니다. 이경우저작권법에따라불이익을받으실수있습니다. 다양한기기에사용할수있습니다. 또한, 한빛미디어사이트에서구매하신후에는횟수와관계없이내려받으실수있습니다. 한빛미디어전자책은인쇄, 검색, 복사하여붙이기가가능합니다. 전자책은오탈자교정이나내용의수정 보완이이뤄지면업데이트관련공지를이메일로알려드리며, 구매하신전자책의수정본은무료로내려받으실수있습니다. 이런특별한권한은한빛미디어사이트에서구매하신독자에게만제공되며, 다른사람에게양도나이전은허락되지않습니다.
차례 chapter 1 새로운연락처프레임워크 011 1.1 Contacts 와 ContactsUI 011 1.2 돌아보기 021 chapter 2 SafariServices 프레임워크 023 2.1 SFSafariViewController 023 2.2 돌아보기 026 chapter 3 UIKit 프레임워크 027 3.1 스택뷰 027 3.2 더욱쉬워진오토레이아웃제약수정 036 3.3 노티피케이션액션 043 3.4 3D Touch 050 3.5 돌아보기 071 chapter 4 ipad 멀티태스킹 073 4.1 ipad 멀티태스킹지원 073 4.2 참고사항 084 4.3 돌아보기 086 chapter 5 스포트라이트지원 087 5.1 스포트라이트지원 087 5.2 돌아보기 104
chapter 6 Watch 107 6.1 ios의 WatchKit과 watchos의 WatchKit 107 6.2 ios의 WatchKit 애플리케이션 110 6.3 watchos의 WatchKit 애플리케이션 137 6.4 돌아보기 167 chapter 7 앱씨닝 169 7.1 앱씨닝이란 169 7.2 슬라이싱 169 7.3 비트코드 171 7.4 온디맨드리소스 172 chapter 8 Photos 와 PhotosUI 프레임워크 175 8.1 Live Photos 175 8.2 돌아보기 189 부록 191 A.1 Xcode 프로젝트에번들리소스추가하기 191 A.2 App Transport Security 191 A.3 watchos 2 에서 ios 애플리케이션과통신하기 194
chapter 1 새로운연락처프레임워크 1.1 Contacts 와 ContactsUI 애플은 ios 9 발표와함께새로운연락처프레임워크를선보였는데, Contacts 와 ContactsUI 프레임워크가그주인공입니다. Contacts 프레임워크는모든애플플랫폼에서사용할수있으며 ios 9에서사라진기존의 Address Book 프레임워크를대체하게됩니다. 따라서 Contacts 프레임워크로 ios 또는매킨토시기기에저장된사용자의연락처정보에접근할수있습니다. 애플리케이션대부분은연락처를수정하기보다는읽기만하므로이프레임워크는스레드에서사용해도안전하며읽기전용으로최적화되어있습니다 ( 물론수정과추가기능도있습니다 ). Contacts 프레임워크는연락처를관리하기위해기본으로 CNContact 라는클래스를이용합니다. CNContact 클래스의객체는변경할수없는객체로, 모양새와쓰임이 NSDictionary와유사합니다. 물론 CNMutableContact 클래스의객체를이용하면연락처의속성을변경할수있습니다. 연락처속성중에전화번호, 이메일과같이여러항목이있으면 CNLabeledValue 객체의배열이그값을나타내게됩니다. CNLabeledValue 객체또한스레드에서사용할수있으며, 변경할수없는레이블과값의튜플 Tuple 로이루어져있습니다. 레이블은집전화, 직장전화같은설명 1 새로운연락처프레임워크 - 011
값을표현합니다. Contacts 프레임워크는미리지정된레이블도제공하지만, 직 접사용자정의레이블도생성할수있습니다. 그림 1-1 CNContact 객체와주변객체의상관도 01 CNContact CNLabeledValue CNMutableContact ContactsUI 프레임워크는기기연락처정보의열람, 수정, 선택, 생성등을편리하게도와주는컨트롤러를제공하는데, CNContactPickerViewController 와 CNContactViewController 등을포함합니다. 그럼새로운연락처프레임워크를사용하여새로운연락처를생성하고, 수정해보는예제를진행하겠습니다. 우선 Xcode를실행하여새로운 [Single View Application] 프로젝트를생성합니다. 그림 1-2 Single View Application 프로젝트생성 프로젝트이름은 BasicContacts 라고짓습니다 ( 절대 Contacts 라고이름짓지마 01 참고 : https://goo.gl/0hzfzb 012 -
세요. 프레임워크와동일한이름을사용하는프로젝트는모듈명이기본으로프로젝트명과같아 지기때문에프레임워크를 import 하기골치아파집니다 ). 그림 1-3 프로젝트이름지정 프로젝트생성이완료되면 ViewController.swift 파일로이동하여다음코드를작성합니다. 소스코드중 clickshowcontactspickercontroller 메서드는주소록선택화면을보여주며, clickshowcontactscontroller 메서드는선택된연락처를보여줍니다. 그리고 clickeditcontacts 메서드는선택된연락처정보를코드로수정하여업데이트하는메서드입니다. 그외내용은코드에주석을달아설명하였으니코드를참고하시기바랍니다. [ 코드 1-1] BasicContacts 프로젝트의 ViewController.swift 파일전체코드 import UIKit // Contacts 프레임워크와 ContactsUI 프레임워크를 import합니다. import Contacts import ContactsUI // CNContactPickerDelegate 역할을수행할것을명시합니다. class ViewController: UIViewController, CNContactPickerDelegate { // MARK: - Properties // 선택된연락처정보를가질객체입니다. var selectedcontact: CNContact? // MARK: - Methods 1 새로운연락처프레임워크 - 013
func dismissmodalviewcontroller() { self.dismissviewcontrolleranimated(true, completion: nil) // MARK: - IBActions @IBAction func clickshowcontactspickercontroller() { // 연락처선택뷰컨트롤러를생성하여화면에보여줍니다. let contactspicker: CNContactPickerViewController = CNContactPicker ViewController() contactspicker.delegate = self self.presentviewcontroller(contactspicker, animated: true, completion: nil) @IBAction func clickshowcontactscontroller() { // 선택하여가져온연락처정보가있다면연락처정보를보여줍니다. if let contact = self.selectedcontact { let contactviewcontroller: CNContactViewController = CNContactView Controller(forContact: contact) let navigation = UINavigationController(rootViewController: contactviewcontroller) let closebutton = UIBarButtonItem(title: Close, style: UIBarButtonItemStyle.Done, target: self, action: dismissmodalviewcontroller ) contactviewcontroller.navigationitem.rightbarbuttonitem = closebutton self.presentviewcontroller(navigation, animated: true, completion: nil) @IBAction func clickeditcontacts() { // 선택된연락처정보를수정하는한 Mutable 객체로복사해옵니다. if let mutablecontact = self.selectedcontact?.mutablecopy() as? CNMutableContact { // 이름을변경할수있습니다. mutablecontact.givenname = yagom mutablecontact.familyname = Jo // 이메일정보를수정할수있습니다. let email = CNLabeledValue(label:CNLabelWork, value: yagomsoft@ gmail.com ) let icloudmail = CNLabeledValue(label:CNLabelEmailiCloud, value: yagomsoft@me.com ) 014 -
mutablecontact.emailaddresses = [email, icloudmail] mutablecontact.phonenumbers = [CNLabeledValue( label:cnlabelphonenumberiphone, value:cnphonenumber(stringvalue: 010-0000-0000 ))] // 홈페이지나블로그등 URL 정보를변경할수있습니다. let blogurlstring: String = http://blog.yagom.net mutablecontact.urladdresses = [CNLabeledValue(label: CNLabelURLAddressHomePage, value: blogurlstring)] // 주소를변경할수있습니다. let homeaddress = CNMutablePostalAddress() homeaddress.street = Sang-su homeaddress.city = Mapo homeaddress.state = Seoul homeaddress.postalcode = 00000 mutablecontact.postaladdresses = [CNLabeledValue(label:CNLabelHom e, value:homeaddress)] // 생일을변경할수있습니다. let birthday = NSDateComponents() birthday.day = 11 birthday.month = 7 // 년도는비밀이니까넣지않겠습니다 // birthday.year =??? mutablecontact.birthday = birthday // 연락처정보를저장하거나가져올수있는 CNContactStore 객체입니다. let store = CNContactStore() // 저장또는변경을위한요청객체입니다. let updaterequest = CNSaveRequest() updaterequest.updatecontact(mutablecontact) // 저장 ( 기존정보업데이트 ) 을시도해보고실패하면로그를남깁니다. do { try store.executesaverequest(updaterequest) self.selectedcontact = mutablecontact catch let error { print(error) return 1 새로운연락처프레임워크 - 015
// MARK: - ContactsPickerViewController Delegate // 주소록에서한개의연락처정보를선택했을때연락처객체가넘어옵니다. // contactpicker:didselectcontacts 메서드와동시에구현할경우 didselectcontacts 메서드가우선됩니다. func contactpicker(picker: CNContactPickerViewController, didselectcontact contact: CNContact) { self.selectedcontact = contact /* // 예제에서다루는것외에다양한델리게이트메서드를소개하기위해주석처리합니다. // 주소록에서여러개의연락처정보를선택했을때연락처객체의배열이넘어옵니다. func contactpicker(picker: CNContactPickerViewController, didselectcontacts contacts: [CNContact]) { // 주소록의연락처에서하나의속성을선택했을때속성객체가넘어옵니다. // contactpicker:didselectcontactproperties 메서드와동시에구현할경우 didselectcontactproperties 메서드가우선됩니다. func contactpicker(picker: CNContactPickerViewController, didselectcontactproperty contactproperty: CNContactProperty) { // 주소록의연락처에서여러개의속성을선택했을때속성객체의배열이넘어옵니다. func contactpicker(picker: CNContactPickerViewController, didselectcontactproperties contactproperties: [CNContactProperty]) { */ 코드작성을마치면 Main.storyboard 파일로이동하여버튼세개를올려주고 타이틀을 [ 그림 1-4] 처럼변경한후액션을알맞게연결합니다. 016 -
그림 1-4 버튼의액션연결상태 그리고단축키 [command + R] 또는 Xcode 상단의 [ 실행 ] 버튼을눌러애플 리케이션을실행한후, 화면가장위의버튼인 [Show Contacts Picker View Controller] 를선택합니다. 그림 1-5 Show Contacts Picker View Controller 버튼선택 그러면다음과같이기기에저장된연락처의주소록이화면에표시되는데이중주 소록에서가져오려는연락처를선택합니다. 여기서는 Anna Haro 라는이름으 로저장된연락처를선택했습니다. 1 새로운연락처프레임워크 - 017
그림 1-6 저장된연락처선택 연락처를선택하면다시처음화면으로돌아갑니다. 이번에는두번째 [Show Contacts View Controller] 버튼을선택합니다. 그림 1-7 Show Contacts View Controller 버튼선택 연락처선택화면에서선택한연락처정보가화면에표시됩니다. 018 -
그림 1-8 Contacts View Controller 에보이는연락처정보 이번에는앞에서코드로작성한정보로연락처정보를변경해봅니다. [Close] 버 튼을눌러화면을닫고첫화면하단의 [Edit Contact Information] 버튼을선 택합니다. 그림 1-9 Edit Contact Information 버튼선택 1 새로운연락처프레임워크 - 019
이애플리케이션에서연락처정보에코드로접근하는것이처음이라면다음과같 은경고가발생합니다. 연락처정보에접근하는것을허용하기위해 [OK] 를선택 해주세요. 그림 1-10 연락처정보접근허용여부를묻는경고창 이후특별한오류로그가없다면정상적으로편집된것입니다. [Show Contacts View Controller] 버튼을선택하여변경된연락처정보를확인해봅니다. 미리 코드로변경하려고지정해둔정보들이편집된것을확인할수있습니다. 그림 1-11 수정된연락처정보 020 -
이처럼 Contacts 프레임워크와 ContactsUI 프레임워크를사용하면기존의 Address Book보다더편리하고쉽게사용자의연락처에접근하고수정할수있습니다. 또한, 기본 UI로깔끔하게연락처정보를표현할수있습니다. 사용자가미리지정해둔문구들을연락처에삽입하는등의기능을담은애플리케이션을만들어보면좋을것같은데요? 1.2 돌아보기 1 장에사용한클래스를간단히정리해보겠습니다. 각항목에관한자세한내용은 링크를참고해주시기바랍니다. 구분설명참고링크 CNContacts CNMutableContacts CNLabeledValue Contacts와 ContactsUI 프레임워크에서연락처정보를담는역할을합니다. CNContacts 객체를수정할수있도록확장한클래스입니다. CNContacts 객체에서연락처속성을표현할때사용하는클래스입니다. https://goo.gl/j6qedd https://goo.gl/6caaew https://goo.gl/deywdq CNContactStore CNSaveRequest CNContactPickerView Controller 연락처정보저장, 불러오기등을할때사용되는클래스입니다. CNContactStore에연락처정보를저장하거나수정하기를요청하는데필요한클래스입니다. 연락처정보를선택하여정보를가져오는데사용하는뷰컨트롤러클래스입니다. https://goo.gl/ld4cth https://goo.gl/r6jy1h https://goo.gl/zttgqh CNContactViewController 연락처정보를보여주기위해사용되 https://goo.gl/owwdrm 는뷰컨트롤러클래스입니다. 1 새로운연락처프레임워크 - 021
022 -
chapter 2 SafariServices 프레임워크 2.1 SFSafariViewController ios 9 전에는웹페이지를제대로탐색할수있는화면을구현하려면웹뷰 (WebView) 와 [ 앞으로가기 ], [ 뒤로가기 ] 버튼을포함한툴바를함께구현해야했습니다. 심지어는 URL을입력하는필드도없었습니다. ios 9부터기존의 SafariServices 프레임워크에사파리뷰컨트롤러가추가되어이귀찮음을단방에해결해줄수있습니다. 이제간편하게웹뷰를볼수있는컨트롤러를코드몇줄로바로보여줄수있다는뜻입니다! 별다른설명이필요없죠! 신나게만들어봅시다. 먼저 EasySafari 라는이름으로새로운 Single View Application 프로젝트를생성합니다 ( 새로운프로젝트를생성하는방법은 [ 그림 1-2] 를참고하세요 ). 새로운프로젝트를생성하면코드를작성합니다. 코드는정말간단합니다! 몇줄쓰지않아도되니얼른작성해봅시다. ViewController.swift 파일로이동하여다음코드를작성합니다. 자세한내용은코드주석을참고하시기바랍니다. [ 코드 2-1] EasySafari 프로젝트의 ViewController.swift 파일전체코드 import UIKit // 더욱강력해진 SafariServices 프레임워크를 import 합니다. 2 SafariServices 프레임워크 - 023
import SafariServices // ViewController 객체가 SafariViewControllerDelegate의역할을수행할것을명시합니다. class ViewController: UIViewController, SFSafariViewControllerDelegate { // MARK: - IBActions @IBAction func clickshowsafariviewcontroller() { // NSURL 객체생성에실패할확률이있으므로 if-let 구문을사용하여 nil이반환되지않는지확인합니다. if let url = NSURL(string: http://blog.yagom.net ) { // 사파리뷰컨트롤러를원하는 URL을사용하여생성하고화면에보여줍니다. let safariviewcontroller = SFSafariViewController(URL: url) safariviewcontroller.delegate = self self.presentviewcontroller(safariviewcontroller, animated: true, completion: nil) // MARK: - SFSafariViewControllerDelegate // 사파리뷰컨트롤러의 Done( 완료 ) 버튼을선택했을때호출되는델리게이트메서드입니다. func safariviewcontrollerdidfinish(controller: SFSafariViewController) { // 모달로올라온화면을내려줍니다. self.dismissviewcontrolleranimated(true, completion: nil) /* // 또다른 SFSafariViewControllerDelegate 메서드입니다. // 특정 Activity를특정 URL에맞게제공할수있습니다. func safariviewcontroller(controller: SFSafariViewController, activityitemsforurl URL: NSURL, title: String?) -> [UIActivity] { */ 코드를작성한후에는 Main.storyboard 파일로이동하여버튼하나를올려주 024 -
고액션도연결합니다. 그림 2-1 스토리보드에서액션연결 이제준비끝! 바로실행해봅시다! 단축키 [command + R] 또는 Xcode 상단의 [ 실행 ] 버튼을눌러애플리케이션을실행한후스토리보드에서액션을연결한버 튼을선택해주세요. 여기서는 [Show Safari View Controller] 를선택합니다. 그림 2-2 EasySafari 애플리케이션첫실행화면 완벽한사파리화면이반겨줄거예요! 버튼도다양하게있습니다. 오른쪽아래사 파리아이콘버튼을선택하면현재보고있는페이지가사파리애플리케이션에서 보이게됩니다. 2 SafariServices 프레임워크 - 025
그림 2-3 사파리뷰컨트롤러의모습 SFSafariViewController 에서보는페이지들은기본내장사파리애플리케이 션과세션, 쿠키모두연동되니참고하시기바랍니다. 지난몇년간의제바람이이 제야실현되어개인적으로는너무나기쁘네요. :) 2.2 돌아보기 2 장에사용한컨트롤러를간단히정리했습니다. 항목에관한자세한내용은링크 를참고해주시기바랍니다. 구분설명참고링크 SFSafariViewController 실제사파리애플리케이션과유사한화면구조로웹페이지를서핑할수있는뷰를제공하는뷰컨트롤러입니다. https://goo.gl/t7kzmm 026 -