Dev2019. 12. 24. 16:13

 

Mac Keyboard

Symbol Keyboard Key
Command
Option
Control
Shift
Delete
Escape
Enter

 

주로 쓰는 Xcode 단축키를 정리해봤다.

 

Run ⌘ + R
Build ⌘ + B
Clean the project ⌘ ⇧ + k
Clean build folder
⌘ ⌥ ⇧ + k
Move forcus (네비게이터 영역) ⌘ ⇧ + J
Move focus (에디터영역) ⌘ + J
디버그 창 보이기 / 숨기기
⌘ ⇧ + Y
Inspectors 창 보이기 / 숨기기 ⌘ ⌥ + 0
breakpoint 활성 / 비활성 ⌘ + Y
breakpoiont 추가/ 삭제
+ \
open quickly ⌘ ⇧ + O
show code review ⌘ ⌥ ⇧ ↵
function list show ⌃ + 6
Debugging - Continue / Pause + Y

 

 

 

Posted by iDeveloper
Dev2019. 10. 14. 13:06

iOS 앱 개발에 필요한 프레임워크에 관하여 살펴보겠다.

앱 개발툴인 Xcode 에서 제공되는 중요한 프레임워크의 용도를 알아보는 것이 개발을 위한 필수 요건이기 때문이다.

 

Assets Library 프레임워크

어셋라이브러리 프레임워크는 iOS4.0부터 포함된 프레임워크로 사용자의 사진과 비디오를 쿼리 기반 인터페이스로 가져올 수 있다. 어셋라이브러리 프레임워크를 사용하여 사진앱이 관리하는 사진과 비디오(사용자가 앨범에 저장한 모든 사진과 비디오를 포함)에 접근할 수 있다. 또한 새로운 사진과 비디오를 사용자 앨범에 추가할 수도 있다.

 

AV Foundation 프레임워크

AV 파운데이션 프레임워크는 iOS2.2부터 포함된 프레임워크로 오디오 컨텐츠를 재생하는데 필요한 Objective-C클래스를 제공한다. 이 프레임워크를 사용하여 오디오 파일을 재생할 수 있으며 메모리에 로드된 사운드의 특정 구간의 임의 재생도 가능하다. iOS3.0부터는 오디오 녹음과 오디오 세션 관리 기능이 추가되었다. iOS4.0이후에는 아래와 같은 기능이 확충되었다.

  • 미디어 어셋 관리
  • 미디어 편집
  • 무비 캡쳐
  • 무비 재생
  • 트랙 관리
  • 미디어 아이템의 메타데이터 관리
  • 입체 음향 패닝
  • 사운드간의 정확한 동기화
  • 사운드 파일의 데이터 형식, 샘플 레이트, 채널수 등을 파악하는 Objective-C 인터페이스 제공

Core Audio 프레임워크

코어오디오는 C언어 기반 인터페이스로 스테레오 기반 오디오의 관리를 지원한다. iOS 에서 코어오디오를 사용하여 오디오 생성, 녹음, 믹스, 재생 을 하 수 있다. 또한 코어 오디오를 사용하여 장치 진동 기능을 사용할 수 있다.

  • CoreAudio.framework : 코어 오디오가 사용하는 오디오 데이터 타입을 정의한다.
  • AudioToolbox.framework : 오디오 파일과 스트림의 재생 및 녹음 서비스를 제공한다. 이 프레임워크는 오디오 파일 관리, 시스템 경고 사운드 재생, 진동 기능을 제공한다.
  • AudioUnit.framework : 오디오 프로세싱 모듈인 내장 오디오 유닛을 사용할 수 있도록 해 준다.

Core Graphics 프레임워크

코어그래픽스 프레임워크는 쿼츠2D 드로잉 API를 위한 인터페이스를 포함한다. 쿼츠는 벡터 기반 드로잉 엔진으로 Mac OS X의 것과 동일하다. 패쓰 기반 드로잉, 안티엘리어싱, 그레디언트, 이미지, 색상, 좌표공간 변환, PDF문서 생성, 보이기, 파싱 기능 등을 제공한다. C기반으로 작성되었지만 객체지향추상화를 바탕으로 설계되었다.

 

Core Text 프레임워크

코어텍스트 프레임워크는 iOS3.2부터 포함된 프레임워크로 텍스트 레이아웃과 폰트 처리를 위한 간결하고 고성능의 C언어 기반 인터페이스를 제공한다. 코어 텍스트 프레임워크는 완벽한 텍스트 레이아웃 엔진을 제공하여 화면상에 텍스트의 위치를 자유롭게 관리할 수 있다. 코어 텍스트가 관리하는 텍스트는 텍스트간에 다른 폰트와 렌더링 속성을 가질 수 있다. 코어텍스트 프레임워크는 문서편집기류의 앱 제작 지원을 위해 만들어졌다.

 

Core Video 프레임워크

코어비디오는 iOS4.0부터 포함된 프레임워크로 코어미디어를 위한 버퍼와 버퍼풀을 지원한다. 대부분의 앱은 이 프레임워크를 직접적으로 사용할 필요가 없을 것이다.

 

Image I/O 프레임워크

이미지I/O프레임워크는 iOS4.0부터 포함된 프레임워크로 이미지데이터와 이미지 메타데이터를 가져오고 내보내는 인터페이스를 제공한다. 이 프레임워크는 코어그래픽스 데이터 타입과 함수의 상위층으로 구성되어 있다. 따라서 iOS에서 사용가능한 표준 이미지 타입을 모두 지원한다.

 

Media Player 프레임워크

미디어 플레이어 프레임워크는 앱내에 포함된 오디오 및 비디오 재생의 고수준 인터페이스를 지원한다. iOS3.0에서는 사용자의 아이튜즈 라이브러에 접근하는 인터페이스가 추가 되었다. 따라서 뮤직 트랙 및 재생 목록을 재생할 수 있고 노래 검색 기능과 미디어 픽커 인터페이스를 사용할 수 있다. iOS3.2에서는 크기 조절이 가능한 뷰 내에서 비디오 재생이 가능하게 되었으며 비디오 재생을 위한 설정과 관리를 위해 다양한 인터페이스가 추가 되었다.

 

OpenAL 프레임워크

iOS 는 코어오디오 외에도 OpenAL(Open Audio Library)을 지원한다. OpenAL인터페이스는 오디오 재생을 위한 크로스 플랫폼 표준 인터페이스이다. 거리감, 공간감 있는 음향 출력이 필요한 게임이나 프로그램에서 OpenAL을 사용하여 고성능, 고품질 음향 효과를 구현할 수 있다.

 

OpenGL ES 프레임워크

OpenGL ES 프레임워크는 2D 또는 3D컨텐츠를 그리는 도구를 제공한다. C언어 기반 프레임워크로 높은 프레임률을 지원하는 풀스크린 게임 스타일앱 제작에 사용되며 하드웨어 성능에 영향을 많이 받는다. 항상 EAGL인터페이스와 결합하여 OpenGL프레임워크를 사용한다.

 

Quartz Core 프레임워크

쿼츠 코어 프레임워크는 코어 애니메이션 인터페이스를 포함한다. 코어애니메이션은 고급 애니메이션과 조합 기술로 복잡한 애니메이션과 비주얼 효과를 구현하기 위해 사용된다. 코어애니메이션은 고수준의 Objective-C인터페이스를 지원해 애니메이션과 효과를 구성할 수 있다. 코어애니메이션은 iOS의 많은 부분에 통합되어 있다. 예를 들어 UIKit의 UIView는 표준 시스템 행위를 위한 애니메이션을 제공한다. 또한 커스텀 애니메이션을 만들기 위해서도 코어 애니메이션을 사용할 수 있다.

 

MobileCoreService 프레임워크

모바일 코어 서비스는 iOS3.0부터 포함된 프레임워크로 저수준 데이터 타입에 대해 고유한 타입 식별자(UTI) 상수를 제공한다. UTI 는 앱과 앱, 디바이스와 디바이스 간에 데이터를 전송해야 할 때 필요하다.

 

SystemConfiguration 프레임워크

시스템 구성 프레임워크는 접근 가능성, 사용 가능성을 판단하는 인터페이스를 제공한다. 시스템 구성 프레임워크를 사용하여 장치의 네트워크 구성을 결정할 수 있다. 시스템 구성 프레임워크를 가장 자주 사용하는 예는 장치가 특정 호스트에 접근하는데 Wi-Fi 또는 전화망(3G)을 사용할 수 있는지 판단하는 루틴이다.

 

AddressBook 프레임워크

주소록 프레임워크는 사용자의 장치에 저장된 연락처 정보를 프로그래밍으로 접근할 수 있는 인터페이스를 제공한다. 주소록 프레임워크를 사용하여 사용자의 연락처 정보를 접근하고 수정할 수 있다. 예를 들어, 채팅앱에서 연락 가능한 친구 목록을 만들기 위해서 주소록 프레임워크를 사용할 수 있다.

 

QuickLook 프레임워크

퀵룩은 iOS4.0부터 포함된 프레임워크로 당신이 만든 앱이 지원하지 않는 파일의 미리보기 기능을 다이렉트로 지원한다. 네트워크에서 받은 파일이나 출처를 알 수 없는 파일의 미리보기를 지원하기 위해서 만들어진 프레임워크이다. 특정 파일에 미리보기를 하려면 이 프레임워크를 사용하여 파일의 내용을 보여주는 뷰컨트롤러를 만들면 된다.

 

StoreKit 프레임워크

스토어킷 프레임워크는 iOS3.0부터 포함된 프레임워크로 앱 내에서 추가 컨텐츠나 서비스를 구매할 수 있는 인터페이스를 제공한다.

 

EventKit 프레임워크

이 벤트킷 프레임워크는 iOS4.0부터 포함된 프레임워크로 사용자 장치의 저장된 캘린더 이벤트에 접근할 수 있는 인터페이스를 제공한다. 이 프레임워크를 사용하여 기존의 이벤트 데이터에 접근할 수 있고 새로운 이벤트를 사용자의 캘린더에 추가할 수도 있다. 캘린터 이벤트는 알람을 포함할 수 있으며 알람 규칙을 설정할 수도 있다.

 

CFNetwork 프레임워크

CFNetwork 프레임워크는 고성능의 C언어 기반 인터페이스로 여러 네트워크 프로토콜을 사용하기 위한 객체 지향 추상화를 제공한다. 이 추상화는 프로토콜 스택의 세세한 컨트롤을 제공하고 BSD소켓과 같은 저수준 구조를 쉽게 사용할 수 있게 해 준다. 이 프레임워크를 사용하여 FTP와 HTTP서버와 쉽게 통신할 수 있다. CFNetwork 프레임워크를 사용하여 아래의 내용을 수행할 수 있다.

  • BSD소켓 사용
  • SSL 또는 TLS를 사용하여 암호화된 연결 생성
  • DNS호스트 리졸브(resolve)
  • HTTP 통신,
  • FTP 통신
  • 봉쥬르 서비스 통신

Foundation 프레임워크

파운데이션 프레임워크는 코어 파운데이션 프레임워크의 기능을 Objective-C로 랩핑한 프레임워크이다. 파운데이션 프레임워크는 아래의 기능들을 지원한다.

  • 데이터 컬렉션(배열, 집합, 사전 등)
  • 번들
  • 날짜 및 시간 연산
  • 원시 데이터 블록(Raw data block) 처리
  • 환경 설정 관리
  • URL 및 스트림 처리
  • 스레드와 런루프
  • 봉쥬르
  • 통신 포트 관리
  • 국제화
  • 정규 표현식 매칭
  • 캐쉬 지원

CoreTelephony 프레임워크

코어텔레포니 프레임워크는 iOS4.0부터 포함된 프레임워크로 전화망 서비스를 제공하는 서비스 제공자의 정보를 얻거나 현재 전화망의 정보를 얻는 인터페이스를 제공한다. 이 프레임워크를 사용하여 서비스 제공자가 VoIP 서비스의 지원 여부를 판단할 수 있다.

 

CoreMedia 프레임워크

코어미디어 프레임워크는 iOS4.0부터 포함된 프레임워크로 AV Foundation이 사용하는 저 수준 미디어 타입을 제공한다. 대부분의 앱에서는 이 프레임워크가 필요하지 않지만 오디오와 비디오 컨텐츠를 세세하고 정밀하게 다뤄야 하는 개발자들에게는 필수 프레임워크이다.

 

CoreMotion 프레임워크

코어모션프레임워크는 앱이 장치 하드웨어로부터 움직임 데이터를 받을 수 있고 처리할 수 있는 인터페이스를 제공한다. 장치 하드웨어는 가속도계, 자이로스코프 등이다.

 

CoreLocation 프레임워크

코어로케이션 프레임워크는 장치의 현재 위도와 경도를 알려주는 인터페이스를 제공한다.

 

CoreFoundation 프레임워크

코어파운데이션 프레임워크는 C언어 기반 인터페이스로 iOS앱의 기본 데이터 관리와 서비스 기능을 제공한다. 이 프레임워크는 아래의 내용을 지원한다

  • 데이터 컬렉션(배열, 집합, 사전 등)
  • 번들
  • 문자열 연산
  • 날짜 및 시간 연산
  • 원시 데이터 블록 처리
  • 환경 설정 관리
  • URL 및 스트림 처리
  • 스레드 및 런루프
  • 포트와 소켓 통신

코어파운데이션 프레임워크는 파운데이션 프레임워크와 밀접한 관계를 가지고 있다. 파운데이션 객체와 코어파운데이션 데이터 타입을 혼합해서 써야 할 때 “톨프리브릿징” 기술을 사용하여 이점을 얻을 수 있다. 톨프리브릿징기술은 코어파운데이션과 파운데이션 데이터 타입을 메서드나 함수에 상호교환적으로 사용할 수 있게 해주는 기술이다.

 

CoreData 프레임워크

코어데이터 프레임워크는 iOS3.0부터 포함된 프레임워크로 모델-뷰-컨트롤러 앱에서 데이터 모델을 관리하는 인터페이스를 제공한다.

Posted by iDeveloper
Dev/Swift2018. 6. 13. 02:00

Static TableView는 말그대로 아이폰 설정이나 회원가입과 같은 정적인 테이블뷰를 구현하는데 사용된다.

기존에는 잘 안써봐서 다이나믹 프로토타입으로 구현한 적도 많았다.

하지만 불필요한 코드도 생기기도 하고 셀의 재사용 때문에 이슈가 발생 될수도 있을 것이다.


스샷은 많아보이지만 코드작성하는 부분은 없다. ;)

스태틱 테이블 뷰의 구현 방법은 다음과 같다.





메인 스토리보드에 ViewController를 지운다.

스태틱 태이블뷰는 UITableViewController에서만 사용이 가능하다.

그래서 테이블뷰컨트롤러를 추가 하고 Is Initial View Controller를 체크 했다.





테이블뷰 컨트롤러를 네비게이션 컨트롤러의 루트뷰로 설정하자.


 테이블뷰 컨트롤러를 선택하고 메뉴막대에서 Editor -> Embed In -> Navigation Controller 클릭하면

테이블뷰가 네비게이션의 루트뷰가 된걸 확인 할 수 있다.






테이블뷰를 선택하고 어트리뷰트 인스펙터에서 컨텐츠를 Static Cells로 변경하자.



아차.. 테이블뷰의 스타일을 Grouped로 변경하는게 좋아 보일듯하다.

그룹스타일로 변경하자.



테이블뷰 섹션을 클릭하면 

섹션헤더와 푸터의 텍스트를 설정할수 있다.

row는 1개로 변경 했다.




레이블두개와 스위치를 셀에 추가했다.





row를 2개로 변경하면

방금 라벨과 스위치를 스위치를 추가했던 셀이 그대로 하나 더 생기는 걸 확인 할수 있다.

row를 추가하면 마지막 셀이 그대로 하나 더 생긴다고 이해하면 될듯 하다.

여기서 텍스트만 살짝 바꾸도록 하자. ㅋㅋ





섹션을 한번 2로 변경해보았다.

row를 늘렸던 것처럼 섹션도 동일한 스타일의 섹션이 추가된 것을 확인 할 수있을 것이다.


자, 실행을 해보자.



이상없이 잘 나온다.




Posted by iDeveloper
Dev2018. 6. 6. 23:53

모든 iOS 개발자가 Instruments에서해야 할 일

Introduction

방금 반짝 반짝 빛나는 새로운 iOS 프로젝트에 개발을 마무리하고 앱이 충돌하지 않고 테스트 장치에서 정상적으로 작동하지만 제출할 준비가되었는지 확인하기 위해 최선을 다 했습니까? Instruments에서 프로파일 링을 수행하지 않았다면 대답은 아마도 부정입니다. 충돌이 발생하지 않는다고해서 그것이 사용자의 기기에서 올바르게 작동하고 작동한다는 것을 의미하지는 않습니다.

Xcode에는 모든 종류의 다양한 측정 항목을 사용하여 응용 프로그램을 프로파일 링하는 데 사용할 수있는 Instruments라는 성능 튜닝 응용 프로그램이 포함되어 있습니다. 여기에는 CPU 사용량, 메모리 사용량, 누출, 파일 / 네트워크 활동 및 에너지 사용량을 검사하는 도구가 있습니다. Xcode에서 앱 프로파일 링을 시작하는 것은 정말 쉽습니다. 그러나 프로파일 링시 표시되는 내용을 이해하는 것이 쉽지 않을 수 있습니다. 따라서 일부 개발자는이 도구를 최대한 활용할 수 없게됩니다.

당신이 프로파일 링 할 수있는 많은 것들을 어떻게보아야할까요? 분명히 느린 네트워크 요청이나 느린 스크롤과 같이 즉시 성능 문제가있는 경우 먼저 해당 문제를 대상으로해야합니다. 하지만 상황이 정상적으로 진행되고 있다면, 응용 프로그램을 몇 번 실행하는 동안 적어도 CPU 및 메모리 사용량을 고려하여 모든 것이 생각대로 작동하는지 확인하는 것이 좋습니다.

When to Profile

우리 대부분은 마감일과 기대에 부응해야 하기 때문에 당신의 애플리케이션을 프로파일링 하는 것은 옆으로 밀려나기도 하지만, 당신이 프로파일링 해야 할 몇가지 사항에 대해 이야기해 봅시다.

앱 스토어에 제출하기 전에 최소한 이 작업을 수행해야 합니다. 앱이 검토를 통과하고 사용자의 손에 들어가서 앱을 사용하는 동안 나쁜 일이 발생하는 것을 원하지 않습니다. 여러분은 나쁜 리뷰를 많이 받게 될 것이고, 그것은 여러분의 다운로드에 심각한 타격을 줄것입니다.

몇가지 새로운 주요 기능을 완성한 후에는 간단한 프로필을 작성하여 모든 기능이 제대로 작동하는지 확인하는 것이 좋습니다. 더 오래 기다릴수록 잠재적인 문제를 발견할 수 있으며 더 큰 작업 항목으로 쌓여 시작을 지연시킬 수 있습니다. 팀 차원에서 이러한 체크 인 중 일부를 개발 계획의 일부로 정의할 수 있으므로 시간이 할당됩니다.

다른 시간은 당신이 Instrument를 시작하는 것이 당신이 익숙하지 않은 프레임 워크의 다른 부분들로 작업 할 때라고 제안 할 것입니다. iOS 프레임 워크 및 라이브러리의 양이 지속적으로 늘어남에 따라 익숙하지 않은 프레임 워크로 작업 할 가능성이 큽니다. 대부분의 개발자는 이것이 언제인지 알고 있으며, 그러한 느낌이 들면 몇 가지 빠른 프로필을 실행하여 작업이 나머지 응용 프로그램과 원활하게 작동하는지 확인해야합니다. 타사 라이브러리를 가져 오는 것은 추가하는 라이브러리가 제어 할 수없는 메모리 문제를 일으키지 않는지 확인하기위한 프로필 작성에 좋은 시간이 될 수 있습니다.

Profiling in Xcode

Xcode는 'Debug Navigator'를 확장하여 이전에는 Instruments 내부에 묻혀 있던 많은 정보를 포함 시켰습니다. CMD-6에 충돌하면 애플리케이션에 대한 성능 정보를 보여주는보기를 불러올 수 있습니다. 여기서 CPU / 메모리 / 에너지 / 디스크 / 네트워크 활동에 대한 간단한 요약을 볼 수 있으며 즉각적인 문제가 있는지 확인할 수 있습니다. 여기에서 맨 위의 '프로파일의 인스투르먼트 (Instrument in Profile)'버튼을 클릭하여 인스트루먼트를 시작하여 인스트루먼트에서 디버그 세션을 전송하거나 새 세션을 시작할 것을 요청할 수도 있습니다.

CPU Profiling

가장 먼저 살펴볼 것은 CPU 사용량을 프로파일 링하는 것입니다. CPU 프로파일 링을 시작하기 위해 '프로파일'제품 명령을 선택하고 장치를 대상으로 선택합니다. CPU 프로파일 링을 할 때 실제 장치를 사용하여 CPU 사용에 대한 정확한 정보를 얻고 싶습니다. 시뮬레이터를 목표로한다면 실제 시스템에서 실행되는 CPU 정보가 아니라 매우 다른 CPU 정보를 얻을 수 있습니다. 이상적으로는 가장 느린 장치를 사용하여 원하는 장치로 빠르게 작업 할 수 있습니다.

CPU 프로파일 링은 설정된 간격으로 실행되는 프로세스 샘플을 취하여 작동합니다. 기본적으로 1ms마다 샘플링되지만 필요에 따라 동작을 사용자 정의 할 수 있습니다. 스냅 샷간에 실행중인 프로세스를 확인하여 실행중인 프로세스의 기간을 결정할 수 있습니다. 프로파일 빌드가 끝나면 인스 트루먼 테이션이 시작되고 사용할 프로파일 링 템플릿을 묻습니다. CPU 사용량에 대해서는 '시간 프로파일 러'를 사용합니다.

그러면 Time Profiler 뷰 설정으로 초기 인스트루먼트 뷰를 볼 수 있습니다. 이제 실제로 프로파일러를 실행하려면 프로파일 링을 시작 레코드 단추를 클릭해야합니다. 어떤 이유로 인해 기록 버튼이 비활성화된 경우, 프로파일러 트랙 오른쪽 상단에서 이유를 알려줍니다.

장치가 오프라인 상태라고 말한 상태에서 멈추는 것을 보았습니다. 장치를 다시 부팅하면 일반적으로 문제가 해결됩니다. 녹음 버튼을 클릭하면 애플리케이션에서 발생하는 상황에 대한 정보가 표시되기 시작합니다.

상단에 녹화 중 시간 경과에 따른 CPU 사용량의 차트가 표시되고 하단에는 실행 된 프로세스의 호출 트리가 표시됩니다. 프로세스의 초기 덤프는 실제로 콜 트리의 최상위를 보여 주므로 실제로 유용하지는 않습니다. 그리고 실제로 발생하는 항목을 드릴하기 위해 항목을 확장해야합니다. 또한 시스템 라이브러리 활동에 관심이 있거나없는 모든 종류의 시스템 활동을 보여줍니다. 대다수의 시간은 아마도 작성한 코드에만 관심이있을 것입니다. 다행히도 중요한 정보를보다 빨리 얻기 위해 변경할 수있는 몇 가지 빠른 설정이 있습니다. '디스플레이 설정'(⌘2)의 오른쪽에있는 기어를 클릭하면 '통화 트리'에 대한 여러 가지 옵션이 있습니다. 기본적으로 이러한 옵션의 대부분은 꺼져 있으므로 켜기를 원할 것입니다. 이 옵션이하는 일을 살펴 보겠습니다

  • Separate by Thread - 과도한 스레드를 진단하는 데 도움이되는 스레드별로 프로세스를 표시합니다.
  • Invert Call Tree - 뒤쪽 부분을 보여주기 위해 스택을 뒤집습니다. 보통은 훨씬 더 유용합니다.
  • Hide System Libraries - 코드에만 집중할 수 있도록 시스템 라이브러리 프로세스를 제거합니다.
  • Flatten Recursion - 재귀 호출을 하나의 단일 항목으로 결합합니다.
  • Top Functions - 함수가 사용 된 시간과 해당 함수에서 호출 된 함수가 소비 한 시간을 더합니다. 이렇게하면 더 비싼 진단 방법을 찾을 수 있습니다.

필자는 일반적으로 프로파일링 할 때 이러한 모든 확인란을 선택하여 응용 프로그램에 대해 원하는 정보를 빠르게 얻을 수 있다는 것이 가장 유용하다는 것을 알게 되었습니다. 이를 확인하면 CPU를 사용하고있는 애플리케이션 메소드를 보여주는 Call Tree가 훨씬 더 유용해진다는 것을 알 수 있습니다.

이제 고가의 CPU 메소드를 필터링 한 목록에서 응용 프로그램의 특정 부분을 최적화하려고 시도 할 수 있습니다. 당신이 많이 할 수없는 것들이 있을지 모르나, 당신이 최적화 할 수있는 것들을 보게 될 것입니다. 어떻게 애플리케이션을 최적화 할 수 있는지에 대해서는 자세하게 설명하지 않지만 고려해야 할 사항은 다음과 같습니다.

  • non UI 프로세스를 다른 스레드로 오프로드하기
  • 여러번 사용되는 것(캐시이미지, 데이터 등등)들은 항상 리로드 할 필요가 없다.
  • UI 업데이트 수를 줄이면 때때로 UI를 불필요하게 업데이트 할 수 있습니다.

언급 할 수있는 간단한 팁은 'Call Tree'섹션의 오른쪽에있는 'Extended Detail'섹션 (디스플레이 설정 옆에있는 아이콘 또는 ⌘3)을 사용하여 선택한 항목에 대한 특정 스택 추적을 볼 수 있다는 것입니다 그 스택에있는 라인을 두 번 클릭하면 Instruments가 코드의 정확한 라인으로 이동합니다. 거기에서 Xcode로 되돌아 가서 작은 방법으로 작업 할 수있는 작은 Xcode 아이콘을 클릭 할 수 있습니다.

성능 문제를 해결하기 위해 업데이트를 한 후 프로파일러에서 동일한 단계를 다시 실행하고 성능이 더 좋은지 확인하고 성능에 만족할 때까지 이 프로세스를 계속하십시오.

Memory Profiling

우리가 살펴볼 프로파일의 다음 유형은 메모리 프로파일 링입니다. 이것은 종종 문제를 일으키지 않기 때문에 iOS 앱을 개발할 때 간과 할 수없는 문제 중 하나입니다. 메모리 누수가 발생하여 사용자가 계속해서 앱을 사용하면 메모리 부족 상황에 도달하여 앱이 다운 될 때까지 메모리가 증가하고 커집니다. 앱에 좋지 않을뿐 아니라 다른 앱의 메모리 부족 상황을 초래할 수있는 사용자 앱의 앱 시민이 아닙니다. 인스트루먼트를 사용하여 메모리가 누출되지 않았는지 확인하고 어떻게 이러한 상황을 해결할 수 있는지 살펴 보겠습니다.

시간이 지남에 따라 메모리 사용량을 살펴볼 때 시간이 지남에 따라 계속 증가하지 않도록 해야 합니다.

당신은 이런 증가를 원하지 않을겁니다.

당신은 이와 비슷한 것을 보아야 합니다.

메모리 사용량을 파악하는 가장 쉬운 방법은 다시 'Debug Navigator'를 사용하는 것입니다. 여기서 'Memory'패널을 선택하고 시간 경과에 따른 메모리 사용량을 확인할 수 있습니다. 여기서 차트를 검색하면 사용량이 지속적으로 증가하고 절대 감소하지 않는 등 즉각적인 메모리 문제를 확인할 수 있습니다.

메모리 사용량을 자세히 보려면 'Profile in Instruments'버튼을 클릭하십시오.이 세션을 전송할 것인지 또는 새 세션으로 다시 시작할 것인지 묻습니다. Instrument를 사용하여 세션을 다시 시작하도록 선택하십시오.

전송을 하면서 몇몇 정보가 분실된 것 같아서  운이 좋지 않았어요. Instruments가 열리고 Allocations and Leaks 템플릿이 포함되어 모든 메모리 할당과 발생할 수있는 누출 가능성을 확인할 수 있습니다.

누수 패널에서 너무 자세히 설명하지는 않겠지 만 지정된 간격으로 스냅 샷을 가져 와서 할당되었지만 할당을 취소 할 수없는 메모리가 있는지 확인합니다. 이것은 Objective-C로 작업하고 할당 된 메모리를 해제 할 책임이있는 일부 C 라이브러리를 사용하는 경우 자주 발생합니다. 일반적으로 '분석'빌드 옵션을 사용하여 이러한 것들을 대부분 찾을 수 있지만 때때로 분석 도구에서 아무것도 찾지 못했지만 Instruments가 문제를 파악한 경우가 있습니다. Swift에서 작업하는 경우 Objective-C에서 수행해야했던 작업 중 일부를 처리하므로 이러한 누출이 덜 일반적입니다.

메모리 프로파일러가 실행 중일 때, 유용한 일은 일련의 이벤트를 여러 번 수행하고 각 시퀀스 이후에 메모리 생성을 표시하는 것입니다. 그런 다음 각 스냅 샷 간의 메모리 증가를 분석 할 수 있습니다. 메모리의 스냅 샷을 찍으려면 오른쪽의 '디스플레이 설정'섹션에서 '생성 생성'버튼을 클릭하십시오. 시퀀스 중에 세대를 표시하는 것을 잊어 버린 경우에는 사실 이후에 새로운 세대를 추가 한 다음 원하는 자리로 옮길 수 있습니다. 상단 근처의 깃발을 클릭 한 상태로 이동하면됩니다. 소수의 세대가 생기면, 나는 그것을 성장에 따라 분류하고, 'Allocation Type'을 'All Heap Allocations'로 변경하여 원시 크기로 정렬하고 제어 할 수없는 시스템 일부를 제거합니다. 그런 다음 메모리 사용량 측면에서 볼 때 몇 가지 사항을 볼 수는 있지만 작성한 객체를 보거나 공간을 사용하고있는 프리미티브 중 일부를 쉽게 볼 수는 없습니다.

이제 메모리 할당 목록을 얻었으므로 모든 것이 순서대로되어 있는지 살펴 보는 시간이지만이 데이터의 초기 표시는 즉시 유용하지 않습니다. Swift에서 작업하는 경우 모든 Swift 객체에 응용 프로그램 이름이 접두어로 붙어 있으므로 필터에서 응용 프로그램 이름을 검색하여 객체의 메모리에있는 모든 것을 볼 수 있습니다. Objective-C로 작업하고 있다면이 정보를 얻는 것이 약간 까다 롭습니다. 당신은 기본적으로 당신이 찾고있는 것들의 이름을 알아야합니다. 만약 당신이 파일의 접두어를 붙이면 그 접두사를 검색하여 모든 객체를 그런 식으로 볼 수 있습니다. 또는 모든 뷰 컨트롤러 이름을 ViewController로 가정했을 때 사용한 네이밍 스키마를 검색 할 수도 있습니다. 'ViewController'및 모든 해당 객체를 참조하십시오.

여기 예제 화면에서는 4 개의 스냅 샷을 만들었고 ViewController라는 이름으로 객체를 필터링하고 있습니다. 각 세대 스냅 샷간에 ServiceViewController가 누출되고 있음을 알 수 있습니다.

이 아티클의 목적을 위해 유지주기를 발생시키기 위해 ViewController에 뭔가를 넣었으므로 이 코드가 내 코드에서 정확히 무엇인지 여기에서 알게되었지만 그러나 당신의 코드에서는 누출 된 객체의 일부가 공개되는 것을 막아서 파헤쳐 야합니다. 유지주기는 서로에 대한 강력한 참조를 가지며 할당 취소를 방지하는 두 개의 오브젝트가있는 경우입니다. 유지 사이클의 원인에 대한 자세한 내용은 다루지 않겠지 만, 먼저 대리인과 블록 / 클로저를 살펴 보는 것이 좋습니다.그들은 가장 드라마를 일으키는 것 같습니다. 대리인이 약하고 블록 / 클로저에서 약한 (또는 Swift에서 소유되지 않은) 참조를 사용하고 있는지 확인해야합니다.

객체의 일부를 파악하는 데 문제가있는 경우 Instruments를 사용하여 문제의 개체에 대한 할당 요약에 대한 추가 정보를 얻을 수 있습니다. 객체 옆에있는 작은 화살표를 클릭하면 해당 객체의 모든 할당과 누가 그 객체를 생성 할 책임이 있는지를 보여줍니다. 그런 할당 중 하나 옆에있는 작은 화살표를 클릭하면 보유 및 릴리스 수에 대한 자세한 정보를 볼 수 있습니다. 그 수가 0에 이르지 않으면 할당이 해제되지 않습니다. 몇몇의 기술을 필요로하는 경우가 있습니다 만, 'Responsible Library'가 애플리케이션이거나 'libsystem_blocks'인 곳을보고 'UIKit'을 건너 뛰는 것이 좋습니다. 검색 상자에 해당 항목을 입력하여 목록을 필터링 할 수 있습니다. 그런 다음 'Extended Detail (확장 세부 사항)'을 표시하고 각각의 상황에 대한 스택 추적을 볼 수 있습니다.

결론

이것은 실제로 Instruments가 하는 모든 일의 겉핥기 식 일 뿐입니다. 하지만 이 정보를 통해 Instruments를 시작하는 것을 쉽게 이해할 수 있기를 바랍니다. 툴링에 익숙해지면 더 많은 도구를 사용하게 되고 코드가 더 좋아 집니다. 문제의 원인이 될 수 있는 항목을 보다 사전에 확인할 수 있으며 표준 워크 플로우의 일부가 됩니다.

Instruments 사용에 대해 더 자세히 알고 싶다면 2014 년부터 WWDC 비디오를 시청하는 것이 좋습니다. - Improving your app with Instruments 이 아티클에서 논의 된 몇 가지 팁과 트릭을 통해 살펴볼 것이다. Instruments와에 대해 더 알고 싶다면 Apple에서 사용자 가이드를 확인하십시오.

원문: https://medium.com/@kazmiekr/what-every-ios-developer-should-be-doing-with-instruments-d1661eeaf64f

view raw Instruments.md hosted with ❤ by GitHub
Posted by iDeveloper
Dev/Swift2018. 6. 5. 10:27

strong, weak, unowned - Reference Counting in Swift

이 아티클에서는 스위프트에서의 Apple의 메모리 관리 방법을 설명합니다. 대부분 자동으로 처리 되더라도 여전히 몇 가지 함정이 있습니다. 객체 간의 관계를 설명하는 올바른 참조 유형을 선택하면 메모리 누수를 피할 수 있습니다.

Automatic Reference Counting

자동 추적 및 메모리 사용 관리를위한 Apple의 구현을 ARC (Automatic Reference Counting)라고합니다. 객체가 더 이상 참조되지 않을 때 자동으로 메모리를 비웁니다. 어떤 오브젝트가 아직 사용 중인지 알기 위해 참조 카운트를 증가 및 감소시켜 오브젝트 간의 관계를 추적합니다. 오브젝트는 참조 횟수가 0 일 때만 할당을 취소 할 수 있습니다.ARC는 클래스의 인스턴스에만 적용됩니다. 구조체, 열거 형 및 값 형식은 참조로 전달되지 않습니다. 이것은 가능할 때마다 클래스 대신에 Structs를 사용하는 또 하나의 큰 이유입니다.

Strong

Swift에서는 속성의 기본 선언이기 때문에 강력한 참조를 찾을 수 있습니다. 이것은 선형 참조 흐름(linear reference flow)이 있을 때 문제가 되지 않습니다. 부모를 할당 해제하고 보유 수를 줄이면 모든 자식도 감소합니다. 다음은 강력한 참조의 예입니다.

import Foundation

class Car {

    var brand: String

init(brand: String) {

        self.brand = brand

        print("Car of the brand (brand) allocated")

    }

deinit {

        print("Car of the brand (brand) is being deallocated")

    }

}

do {

    let tesla = Car(brand: "tesla")

}

Car 객체의 초기화는 do 블록에 래핑됩니다.

이렇게하면 주위에 범위가 만들어집니다. 범위의 끝에서 객체의 할당이 해제되고 모든 것이 잘됩니다.

Car of the brand tesla allocated

Car of the brand tesla is being deallocated

그러나 클래스 인스턴스간에 강력한 참조주기가 있는 코드를 작성할 수 있습니다.

이전 예제의 수정 된 버전은 참조주기를 보여줍니다.

import Foundation

class Car {
    var brand: String
    var owner: Owner?
 
    init(brand: String) {
       self.brand = brand
       print("Car of the brand \(brand) allocated")
    }
 
    deinit {
        print("Car of the brand \(brand) is being deallocated")
    }
}
class Owner {
    var name: String
    var car: Car?
 
    init(name: String) {
        self.name = name
        print("Owner \(name) allocated")
    }
 
    deinit {
        print("Owner \(name) deallocated")
    }
}
do {
    let tesla = Car(brand: "tesla")
    let misterX = Owner(name: "Mister X")
    tesla.owner = misterX
    misterX.car = tesla
}

car 객체는 이제 Owner에 대한 선택적 참조를 가지며 Owner는 Car에 대한 선택적 참조를가집니다.

출력은 다음과 같습니다.

Car of the brand tesla allocated

Owner Mister X allocated

그러나 클래스 인스턴스간에 강력한 참조주기가있는 코드를 작성할 수 있습니다. 이전 코드의 수정된 버전은 다음과 같은 참조주기를 보여줍니다.

import Foundation

class Car {
    var brand: String
    var owner: Owner?
 
    init(brand: String) {
       self.brand = brand
       print("Car of the brand \(brand) allocated")
    }
 
    deinit {
        print("Car of the brand \(brand) is being deallocated")
    }
}
class Owner {
    var name: String
    var car: Car?
 
    init(name: String) {
        self.name = name
        print("Owner \(name) allocated")
    }
 
    deinit {
        print("Owner \(name) deallocated")
    }
}
do {
    let tesla = Car(brand: "tesla")
    let misterX = Owner(name: "Mister X")
    tesla.owner = misterX
    misterX.car = tesla
}

car 객체는 이제 Owner에 대한 선택적 참조를 가지며 Owner는 Car에 대한 선택적 참조를가집니다. 출력은 다음과 같습니다.

Car of the brand tesla allocated

Owner Mister X allocated

강력한 참조주기는 보유 수를 0으로 설정하여 할당을 해제하고 메모리를 확보합니다. 이 문제를 해결하려면 약한 참조가 필요합니다.

Weak

Strong 참조 과 달리 Weak은 보유 수를 1만큼 증가시키지 않습니다. 그래서 그들은 객체가 ARC에 의해 할당 해제되지 않도록 보호하지 않습니다. 할당 해제시 Weak 참조는 자동으로 nil로 설정됩니다. 이것이 모든 약한 참조가 선택적 변수를 변형시키는 이유입니다. 상수를 약한 것으로 정의하는 것은 불가능합니다.

앞의 예를 살펴 보겠습니다. 자동차와 소유자 사이의 Weak한 참조를 사용하면 할당 취소 문제를 해결할 수 있습니다.

class Car {
    weak var owner: Owner?
    ...
}
class Owner {
    weak var car: Car?
    ... 
}
...

이제 ARC는 모든 객체를 올바르게 할당 해제합니다.

Car of the brand tesla allocated

Owner Mister X allocated

Owner Mister X deallocated

Car of the brand tesla is being deallocated

참고 : Car 또는 Owner 클래스에서 하나의 Weak 참조만 사용하면 문제가 해결되어 강력한 참조 사이클이 해제됩니다.

Unowned

Unowned 참조는 약한 참조와 비슷합니다. 보유 수를 1만큼 증가시키지 않습니다. Unowned 참조와 달리 할당 해제시 nil로 자동 설정되지 않기 때문에 Optional 일 필요는 없습니다. 객체가 설정되면 객체가 전혀 삭제되지 않는다는 사실을 알고있을 때만 Unowned 참조를 사용하는 것이 중요합니다.

Apple에 따르면 참조와 참조 된 코드가 동시에 할당 해제 될 때 사용하는 것이 가장 좋습니다.

weak vs. unowned - an advice from Apple

"그 참조가 평생 동안 어떤 시점에서 무효가 될 때마다 weak 참조를 사용하십시오. 반대로 초기화가 완료되면 참조가 무조건 유지된다는 사실을 알게 될 때 unowned 참조를 사용하십시오. " Apple Documentation

fin

Apple의 자동 메모리 관리로 인해 메모리 누출이 발생하지 않습니다. 비선형 강한 참조(Non-linear strong references) 및 참조주기는 보유 수가 0이되지 않도록 방지 할 수 있습니다. weak 및 unowned 참조를 사용하면이 문제를 방지하고 앱 메모리를 균형있게 유지할 수 있습니다.

원문 : https://medium.com/@chris_dus/strong-weak-unowned-reference-counting-in-swift-5813fa454f30

Posted by iDeveloper
Dev/Objective-C2018. 5. 16. 15:48
- (void)boldRange:(NSRange)range;
- (void)boldSubstring:(NSString*)substring;
@implementation UILabel (BoldRangeLabel)
- (void)boldRange:(NSRange)range {
if (![self respondsToSelector:@selector(setAttributedText:)]) {
return;
}
NSMutableAttributedString *attributedText;
if (!self.attributedText) {
attributedText = [[NSMutableAttributedString alloc] initWithString:self.text];
} else {
attributedText = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
}
[attributedText setAttributes:@{NSForegroundColorAttributeName:[UIColor redColor],
NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]
}
range:range];
self.attributedText = attributedText;
}
- (void)boldSubstring:(NSString*)substring {
NSRange range = [self.text rangeOfString:substring];
if (![self respondsToSelector:@selector(setAttributedText:)]) {
return;
}
NSMutableAttributedString *attributedText;
if (!self.attributedText) {
attributedText = [[NSMutableAttributedString alloc] initWithString:self.text];
} else {
attributedText = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
}
while (range.location != NSNotFound)
{
[attributedText setAttributes:@{NSForegroundColorAttributeName:[UIColor redColor],
NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]
}
range:range];
NSRange rangeToSearch;
rangeToSearch.location = range.location + range.length;
rangeToSearch.length = self.text.length - rangeToSearch.location;
range = [self.text rangeOfString:substring options:0 range:rangeToSearch];
[attributedText setAttributes:@{NSForegroundColorAttributeName: [UIColor redColor],
NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]
}
range:range];
self.attributedText = attributedText;
}
}
@end
Posted by iDeveloper
Dev/Objective-C2018. 4. 26. 11:45
#define IS_IPAD [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad
- (IBAction)showAlert:(UIButton *)btn
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
[alert addAction:[UIAlertAction actionWithTitle:@"확인" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action){
// 확인
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"취소" style:UIAlertActionStyleCancel handler:NULL]];
if (IS_IPAD){
UIPopoverPresentationController *popPresenter = [alert popoverPresentationController];
popPresenter.sourceView = sender;
popPresenter.sourceRect = sender.bounds;
}
[self presentViewController:alert animated:YES completion:NULL];
}
view raw ViewContoller.m hosted with ❤ by GitHub
Posted by iDeveloper
Dev/Objective-C2018. 4. 26. 11:07
Posted by iDeveloper
Dev/Swift2018. 4. 5. 17:48



출처 : https://www.thorntech.com/2016/02/ios-tutorial-close-modal-dragging/





Posted by iDeveloper
Dev/Swift2018. 3. 27. 12:40
Posted by iDeveloper