[출처] - http://www.cocoadev.co.kr/200




iPhone 어플리케이션은 Xcode란 개발툴에서 코코아터치 프레임워크와 Objective-C 언어를 사용하여 개발합니다. 코코아 터치는 맥 OS X의 핵심 프레임워크인 코코아를 기본으로 아이폰/터치라는 모바일 기기의 특성에 맞추어진 iPhone 개발의 기본 API입니다.

그렇기 때문에 아이폰 어플리케이션 개발을 위해 기본적으로 알아야할 사항은 통합개발 환경인 Xcode와 인터페이스 빌더라는 툴의 사용법, Cocoa Touch 프레임워크, Objective-C 크게 세가지입니다. 이번에는 간단히 iPhone OS의 계층구조를 중심으로 iPhone 어플리케이션 제작을 위해 접근하는 방법에 대해서 알아 보겠습니다.

1. iPhone OS 계층 구조
아래의 그림은 애플에서 설명하는 아이폰 OS의 기술 계층입니다. 이에 대한 자세한 내용은 아이폰 개발자 센터iPhone OS Technology Overview란 문서에 잘 정리되어 있습니다.


가장 로우레벨의 Core OS부터 가장 상위단계인 코코아 터치까지의 계층구조입니다. 주로 하단은 API가 C로 제공되며 상위로 올라 오면서 Objective-C로 제공됩니다. 많이 사용되는 로우레벨의 API들은 상위단계에서 쉽고 편하게 사용할 수 있는 프레임워크로 제공됩니다. 간 계층의 간단한 설명은 아래와 같습니다.

1) Core OS
메모리/프로세서 관리, 파일 시스템, 네트워크, 각종 하드웨어 드라이버등, 운영체제 하단의 커널 레벨에서 제공하는 커널 API 입니다. 흔히 이야기하는 시스템 프로그래밍에 관련된 C를 기반으로 한 라이브러리를 제공합니다.

2) Core Services
Core Foundation, CFNetwork, SQLite, POSIX threads와 같은 파일입출력, 저수준 데이터 타입, 소켓등에 관련된 서비스입니다. Core OS 레벨에 비교적 쉽게 접근할 수 있는 API를 제공합며 대부분 C로된 프레임워크를 제공됩니다. 여기서 제공하는 많은 기능들은 상단 코코아터치의 Foundation Framework에서 Objective-C 프레임워크로 제공됩니다.

  • Core Foundation - 배열, 스트링, 날짜, URL, 로우레벨 데이터등 아이폰 어플리케이션을 위한 기본적인 C API를 제공합니다.
  • CFNetwork - BSD 소켓 및 HTTP, FTP 프로토콜등 네트워크에 쉽게 접근할 수 있는 API를 제공하는 프레임워크입니다.
  • Core Location - GPS, 주변검색등에 사용할 수 있는 사용자의 현재 위치(위도, 경도) 정보와 관련된 API를 제공하는 프레임워크입니다.
  • SQLite - 아이폰 어플리케이션에서 쉽게 사용할 수 있는 파일기반의 경량 데이터베이스 입니다. SQLite에 관련된 보다 자세한 내용은 이전 포스팅을 참조해 주세요.
  • XML - XML 파싱을 위한 libXML2 라이브러리를 제공합니다.

이외에 보안, 주소록등에 관련된 서비스를 제공합니다.

3) Media
비디오, 오디오, 2D/3D 그래픽, 에니메이션을 구현할 수 있는 API를 제공합니다. Objective-C 또는 C로된 API를 제공합니다.

  • Quartz - OS X의 벡터를 기반으로 한 그래픽 엔진입니다. 선과 도형을 그리고 이미지, 비트맵, PDF를 출력하고 색상, 위치에 관련된 C로된 API를 Core Graphic 프레임워크를 통해 제공합니다.
  • Core Animation - 각종 에니메이션과 시각효과를 제공하는 Objective-C로된 프레임워크입니다.
  • OpenGL ES - 게임등과 같은 고성능의 2D/3D 그래픽 출력을 위한 OpenGL ES 1.1에 기반한 C 프레임워크입니다. OpenGL ES를 사용한 게임은 이를 지원하는 다양한 모바일 플랫폼에서의 포팅을 쉽게 할 수 있습니다. 자세한 내용은 공식 홈페이지를 참조하시기 바랍니다.
  • Core Audio - 마이크를 통해 녹음하고 음악파일을 출력하고 각종 음향효과를 제공하는 C로된 오디오 관련 프레임워크입니다.
  • OpenAL - OpenGL ES와 유사한 개념의 크로스 플랫폼을 지원하는 게임등을 위한 고성능 3D 오디오 라이브러리입니다. 자세한 내용은 공식 홈페이지를 참조 하시기 바랍니다.
  • 동영상 - mov, mp4, 3gp와 같은 각종 동영상 파일을 출력을 지원합니다. 이는 Objective-C를 기반으로 한 Media Player framework를 이용하여 손쉽게 접근할 수 있습니다.

4) Cocoa Touch
iPhone개발의 기본이 되는 계층으로 Objective-C를 기반으로 한 핵심적인 두개의 프레임워크를 가지고 있습니다. 사용자 인터페이스, 이벤트 처리등과 함께 위에서 언급한 로우레벨의 기술들을 보다 쉽게 사용할 수 있는 프레임워크를 제공합니다.

  • Foundation Framework - 배열, 스트링, 날짜 로우레벨 데이터등에 관련된 클래스를 제공하는 기본적인 프레임워크입니다. 위의 Core Foundation에서 제공하는 기본 API들의 Objective-C 레퍼 클래스를 제공합니다.
  • UIKit Framework -각종 컨트롤, 윈도우등의 UI, 이벤트 처리등 iPhone 어플리케이션의 사용자 인터페이스와 관련된 API를 제공하는 프레임워크입니다.


2. Mac or iPhone
Mac의 Cocoa와 iPhone의 Cocoa touch는 이름에서 부터 알 수 있듯이 매우 비슷합니다. 가장 큰 차이점은 역시 인터페이스에 관련된 부분으로 이와 관련하여 Mac에서는 AppKit이란 프레임워크를 iPhone에서는 UIKit이란 프레임워크를 제공합니다.

Foundation Framework는 거의 유사하지만 아이폰의 특성상 제거 또는 변경된 부분이 있습니다. 아이폰은 코코아 바인딩, Objective-C 2.0의 가비지 컬렉션, 애플스크립트, NSUndoManage등은 지원하지 않습니다.

개인적으론 시간이 충분하다면 맥에서 코코아 프로그래밍으로 시작한 후에 코코아 터치로 넘어가도 큰 어려움은 없을 것 같습니다.


3. C or Objective-C
대표적인 코코아 프로그래밍 서적인 Cocoa Programming for MAC OS X (번역본:코코아 프로그래밍)의 저자 아론 힐리가스는 그의 저서에서 아래와 같이 이야기 했습니다.

"C와 Java/C++같은 객체지향 언어를 알고 있다면 두시간이면 Objective-C를 마스터할 수 있다"

OOP와 프로그래밍 언어에 대한 개념만 있다면 Objective-C를 익히는 것은 쉽다라는 의미인 것 같습니다.

사실 어느 언어나 기본지식만 있으면 언어 자체를 익히는데는 그다지 어려움이 없습니다. 하지만 해당 플랫폼에 대한 지식과 핵심 라이브러리나 프레임워크를 배우는데 더욱 많은 시간을 소비해야 합니다. 아이폰도 Xcode, 인터페이스빌더의 사용법, OS X에서의 프로그래밍에대한 이해와 코코아 API를 배우는데 Objective-C 언어 자체를 배우는 것보다 더 많은 시간이 필요합니다.

1) C의 선행학습이 필요한가?
개발경험이 있으신 분들은 그동안의 경험을 바탕으로 어떻게 공부해야 할지 나름대로 방법이 있을 것입니다. 하지만 처음 시작하시는 분들은 Objective-C가 C를 기반으로 하고 있기 때문에, 반드시 C를 공부한 후에 Objective-C를 공부해야하는 지에 대해 질문을 하시는 분들이 있습니다.

이 부분은 아마 많은 분들이 차이가 있을 것 같습니다. 제 생각은 "반드시 필요하지는 않다" 입니다. Objective-C는 C에서 확장된 슈퍼셋이라고 하지만 Objective-C를 공부하기 위해 반드시 C를 먼저 공부해야 할 필요는 없을 것 같습니다.

C를 이해한 후에 Objective-C를 시작하는 것이 이론상으로도 맞고, 정상적인 방법일 것입니다. 하지만 대부분의 Objective-C 서적이나 메뉴얼에는 기본적인 문법에 대한 설명이 있고, 전문 C 서적보다는 범위가 작습니다. Objective-C를 사용할 수 있을 만큼 최소한의 문법만 알고 시작하는 것이 더 접근이 쉬울 것 같습니다.

아래는 iPhone 어플케이션의 샘플 소스중에 한부분입니다. 기존에 C/C++ 개발자들도 이런 Objective-C의 문법을 처음 보게되면, 이것이 C와 관련이 있고 C에서 확장되었다는 사실이 잘 이해가 가지 않을 것입니다.
 

처음 시작하시는 분이라면 차라리 이런 혼란을 피하고 코코아 어플리케이션을 바로 제작할 수 있는 Objective-C로 시작하는 것도 한 방법이라고 생각됩니다.

2) 접근방법
사실 가장 좋은 것은 아래와 같이 가장 로우레벨단계 부터 이해하고 올라 가는 것이 기초도 탄탄하고 가장 좋은 방법일 것입니다.

  1. 메모리/CPU등 컴퓨터 하드웨어에 대한 이해
  2. OS에 대한 이해
  3. 컴파일러에 대한 이해
  4. C언어
  5. 시스템 프로그래밍
  6. 자료구조/알고리즘
  7. Objective-C
  8. OOP, 디자인 패턴
  9. Cocoa API

위의 단계대로 차례로 지식과 실력을 쌓아서 접근하면 좋겠지만, 당장 아이폰 어플리케이션을 만들고 싶은데 지루하고 많은 시간을 필요로 합니다. 흥미를 잃지 않고 접근하는 방법은 위의 순서와 반대로 접근하는 것입니다.

Objective-C에 대한 메뉴얼을 대충(?) 한번 읽어 보고 바로 책, 웹사이트, 동영상등의 간단한 튜토리얼등을 따라해 보면서 실제 실행되는 모습을 보면 계속 흥미를 유지할 수 있습니다.

그후에 어느정도 감이 생기면 직접 만들고 싶은 어플리케이션을 목표로 잡습니다. 첫 목표는 과한 욕심은 버리고 간단하고 쉬운 어플리케이션 부터 시작합니다. 아무리 간단해도 따라해 보며 만들었던 것과는 달리 원하는 기능을 직접 구현하는 것은 매우 어렵습니다. 자료도 많이 찾아 보아야되고, 다른 샘플 소스에서 복사해 와야 하는 경우도 있고, 관련 커뮤니티를 통해 도움을 받을 수도 있습니다. 관련자료들은 이전의 iPhone 어플리케이션 개발을 위한 준비 - 3. 관련 자료 포스팅을 참고하시기 바랍니다.

우여곡절끝에 만들어 내면 부족한면이나 필요한 부분이 무엇인지 조금씩 보이게 될 것 입니다. 필요에 의해 공부를 하다보면 아마 위의 순서를 거슬러 올라 접근하게 되는 경우가 많을 것 같습니다. 그러면 차차 복잡하고 어려운 어플리케이션을 만들 수 있을 것입니다.

막상 처음 시작하게 되면 알아야 할 것은 많고 답답한 마음만 드실 것입니다. 하지만 안타깝게도 왕도는 없습니다. 흥미와 열정을 유지하면서 차근차근 해 나가다 보면 어느새 바라는 어플리케이션을 만들수 있는 날이 눈앞에 와있을 것 입니다.

간혹 주위에 개발경험이 전혀 없는 분들로 부터 "무엇부터 시작해야 아이폰 어플리케이션을 만들 수 있냐?"는 질문을 들으면서 이와 관련해서 간단히 포스팅을 해보아야 겠다고 생각했습니다.

정리는 해보았는데 역시 어렵네요. 제가 봐도 이상한 용어들만 난무하고 설명도 중구난방이고, 개발을 처음 하시는 분들이 보면 잘 이해가 안가실 것 같다는 생각이 듭니다.

* 관련링크
iPhone 어플리케이션 개발을 위한 준비 - 1. 하드웨어
iPhone 어플리케이션 개발을 위한 준비 - 2. 소프트웨어
iPhone 어플리케이션 개발을 위한 준비 - 3. 관련 자료
iPhone 어플리케이션 개발을 위한 준비 - 4. 시작하기

출처 : http://blog.naver.com/PostView.nhn?blogId=seogi1004&logNo=110085696098
Posted by 오늘마감

출처 - http://shapeace.tistory.com/27

 

 

iPhone Programming for Dummy

1. iPhone SDK 설치


1.1. 시작하기

iPhone SDK 는 Apple 사에서 무료로 배포하고 있는 개발 도구로서, 누구든지 애플 개발 사이트에 등록하면 다운로드 받을 수 있다. 여기에는 Gcc 를 기반으로 한 Xcode 개발 환경과, Mac 에서 모든 것을 테스트 할 수 있는 에뮬레이터, 그리고 실제 장비에서 실행시키면서 수행 성능을 튜닝할 수 있는 성능 측정 프로그램 등 실제 개발 업무에 필요한 모든 것들이 포함되어 있다.

설치하기전, 먼저 다음과 같은 사항이 준비되었는지 확인하자.

  • Intel CPU 기반의 Mac Computer
기본적으로 iPhone SDK 는 Intel 기반의 Mac 에서만 사용할 수 있다. PPC 기반의 Mac 에서 SDK 를 설치한다면,
iPhone 과 관련된 사항은 설치되지 않는다. 그런데, PPC 기반의 Mac 에서도 전혀 불가능 한 것은 아니다.
이것에 대해서는 1.3. PPC 에서 설치하기 부분에서 다시 다루도록 하겠다.

  • 10.5.3 이상의 Mac OS X
이 버전 이하의 Mac OS 에서는 Xcode 가 설치되지 않게 되어 있다. 처음에는 그렇지 않았는데,
SDK Beta 6 부터에서 이런 제약이 생겼다.

  • C 프로그래밍 언어에 대한 기본 이해
정확하게는 Objective-C 언어에 대한 이해가 있어야 한다. Mac 에서 사용하는 Xcode 개발 환경은 기본적으로 Objective-C 언어에 기반하고 있으며, 그 역사는 NeXT Step 시스템으로 까지 거슬러 올라간다. 문제는 Objective-C 언어에 대해 아는 사람이 그리 많지 않다는 것이지만, 다행이도 Objective-C 언어는 C++ 만큼 어려운 언어는 아니다. 이 문서에서는 Objective-C 언어 자체에 대해 깊이 다루는 것은 피하도록 할 것이다. 단, C 언어 자체에 대한 이해조차 없다면 iPhone SDK 를 사용한 개발은 잠시 접어두고 C 언어 공부를 하고 오는 것을 권한다. 이 문서에서도 독자가 C 언어에 익숙하다는 것을 전제로 한다.


1.2. SDK 설치하기

Developer Connection 에 등록된 사람이라면 http://developer.apple.com/iphone/index.action 에서 SDK 를 다운로드 받을 수 있다.

약 1.2 GB 의 dmg 파일이 다운로드된다. 다 받았다면, 당연히 다운받은 dmg 파일을 마운트한다.
마운트하면 다음과 같은 내용이 보이는 디스크 이미지가 나타날 것이다.

두 번째 보이는 iPhone SDK 패키지 파일을 더블 클릭하여 설치를 시작하면 된다. Packages 폴더의 내용은 특별히 볼 필요 없다. 설치 과정에서 이 폴더에 있는 내용들이 로컬 디스크에 설치될 것이다. 단, PPC 환경에서 SDK 를 설치하는 사용자는 나중에 이 폴더를 열어볼 일이 생긴다.

설치 과정은 간단하다. 디스크 볼륨을 선택해주고, 별다른 설정 변경 없이 기본값으로 선택해서 진행하면 모든 것이 OK 이다.
설치 프로그램을 몇 단계 진행한 후 시스템 관리자 암호 창이 뜨고, 여기에 암호를 입력하면 다음 그림과 같은 화면이 나타나면서 설치가 진행된다. 십분 이상을 기다리면 설치가 완료된다.



설치 시간이 생각보다 길다고 불평하는 사람이 있을 지도 모르겠다. 하지만 이것은 단지 iPhone 응용 프로그램만을 만들기 위한 환경이 아니라, Java를 포함해서 Mac OS 용 프로그램을 만들 수 있는 모든 개발 환경이 포함되어 있는 것이다.

소프트웨어 설치가 끝나면, /Developer/Application 아래에 몇 가지 개발 프로그램들이 설치되어 있는 것을 확인할 수 있다.

Intel CPU 기반의 Mac 을 사용하는 사람이라면, 이제 기본적인 준비는 끝마친 셈이다.


1.3. PPC 에서 설치하기

이상의 과정을 모두 거치더라도 불쌍하게도 PowerPC 기반의 Mac을 사용하는 경우에는 iPhone 응용 프로그램 개발을 할 수 없다. 단지 Mac 데스크탑용 프로그램을 개발할 수 있는 Xcode 환경이 설치되어 있을 뿐이다. Apple 에서도 공식적으로는 PPC 기반의 Mac 에서 iPhone 응용 프로그램을 개발할 수 없다고 선언하고 있다.

그러나 방법은 있다. 다음의 과정을 통해서 G4, G5 Mac 에서도 iPhone 프로그램 개발을 해볼 수 있다. 단, 미리 말하지만 몇가지 사용할 수 없는 기능들이 있다고 하는데, 아직 정확하게 파악하지는 못했다. 그러나 기본적인 거의 모든 기능들을 문제없이 사용할 수 있다.

먼저, 설치하기 위해 마운트했던 디스크 이미지로 돌아가보자.
여기에는 앞서 말했듯이 packages 라는 이름의 폴더가 있다. 여기로 들어가 보면 각종 설치 패키지들이 보일 것이다.

SDK 설치 과정에서 자동으로 설치되었던 각종 패키지들이 여기에 있다. 그런데, 설치하면서 보았을 지도 모르겠지만, PPC 사용자들은 iPhone 관련 항목들이 설치되지 않았다. 선택 항목이 비활성화 되어서 임의로 선택할 수도 없었을 것이다.

이 제 할 일은, 여기서 iPhone 으로 시작하는 이름을 가진 5개 패키지를 하나씩 일일이 수동으로 설치하는 것이다. 설치 과정에서 설치할 폴더의 위치를 변경할 수 있는 단계도 나오는데, 일단 5개 모두 기본으로 설치하도록 클릭해서 넘어가도록 한다.

이런 식의 화면을 보면서 일일이 설치해야 한다...

모두 설치했다면, Finder 로 하드디스크의 루트(/) 위치를 살펴보자. 여기에 'Platforms' 라는 폴더가 생겼을 것이다.그리고 그 아래에는 두 개의 폴더가 있는데, 이 두 개의 폴더를 전부 /Developer/Platforms 아래로 이동한다.
겹 치는 폴더와 파일이 많기 때문에, 중복 확인 창이 뜨면 '대치' 하도록 해야 하는데, 여기서 기존 위치의 폴더 속성 문제로 한번에 파일 이동이 되지 않을 것이다. 문제가 되는 부분들을 하나씩 찾아서 하면 큰 문제 없이 모든 파일을 옮길 수 있을 것이다.

이제 힘든 대부분의 과정을 거쳤다.
마지막 단계가 하나 있는데, 일단 아래 경로를 찾아가서 파일들을 확인한다.

/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specification

꽤나 길다. 최종 목적지에 다다르면 3개의 파일이 있을 것이다.
여기서 iPhone Simulator Architectures.xcspec 이라는 이름의 파일을 텍스트 편집기로 열자.
이 파일의 내용은 아래와 같다. 이것은 iPhone 시뮬레이터용으로 컴파일러가 코드를 생성할 때 어떤 타겟으로 만들 수 있는지에 대한 설정값이다.

 
/**
    iPhone Simulator Architectures.xcspec
   
    Copyright (c) 2008 Apple Inc.  All rights reserved.

    Architecture specifications in the iPhone Simulator platform.
*/
(
    // 32-Bit
    {   Type = Architecture;
        Identifier = Standard;
        Name = "Standard (iPhone Simulator: i386)";
        Description = "32-bit iPhone Simulator architectures";
        ListInEnum = YES;
        SortNumber = 1;
        RealArchitectures = ( i386 );
        ArchitectureSetting = "ARCHS_STANDARD_32_BIT";
    },

    // Old-style Debug
    {    Type = Architecture;
        Identifier = Native;
        Name = "Native Architecture of Build Machine";
        Description = "32-bit for build machine";
        ListInEnum = YES;
        SortNumber = 101;
        ArchitectureSetting = "NATIVE_ARCH";
    },

    // Intel
    {   Type = Architecture;
        Identifier = i386;
        Name = "Intel";
        Description = "32-bit Intel";
        PerArchBuildSettingName = "Intel";
        ByteOrder = little;
        ListInEnum = NO;
        SortNumber = 105;
    },
)

원본 파일은 만약을 위해 각자 편한 방식으로 백업해 두길 권한다.
그리고 이 파일의 내용을 다음과 같이 수정한 후 저장하자.

 /**
    iPhone Simulator Architectures.xcspec
   
    Copyright (c) 2008 Apple Inc.  All rights reserved.

    Architecture specifications in the iPhone Simulator platform.
*/
(
    // 32-Bit
    {   Type = Architecture;
        Identifier = Standard;
        Name = "Standard (iPhone Simulator: ppc)";
        Description = "32-bit iPhone Simulator architectures";
        ListInEnum = YES;
        SortNumber = 1;
        RealArchitectures = ( ppc );
        ArchitectureSetting = "ARCHS_STANDARD_32_BIT";
    },

    // Old-style Debug
    {    Type = Architecture;
        Identifier = Native;
        Name = "Native Architecture of Build Machine";
        Description = "32-bit for build machine";
        ListInEnum = YES;
        SortNumber = 101;
        ArchitectureSetting = "NATIVE_ARCH";
    },

    // G5 32-bit
    {   Type = Architecture;
        Identifier = ppc;
        Name = "PowerPC G5 32-bit";
        Description = "32-bit PowerPC for G5 processor";
        ByteOrder = big;
        ListInEnum = NO;
        SortNumber = 203;
    }
)

이 작업을 하지 않으면 코드를 작성하더라도 에뮬레이터를 사용할 수 없다. 이렇게 힘든 과정을 모두 통과하였다면 PPC 사용자들도 이제 iPhone SDK 를 사용할 자격을 비로소 얻게 된다.


자, 이제 모두 출발선에 섰다. 계속 달려갈 결심을 하는 일 만 남은 셈이다.
Intel 이건 PPC 건, 이제 구분하지 말고 Xcode 의 얼굴을 구경해보자. Xcode 가 어디있냐고? 보나마나 /Developer 아래 어딘가에 있겠지만 알게 뭔가. 그냥 Spotlight 에서 Xcode 라고 타이핑 한 후 Enter 키를 눌러보면 되지. 그리고 나서 Xcode 는 그냥 Dock 에 등록해 버리자.



환 영합니다. Dummy 여러분.

 



출처 : http://blog.naver.com/PostView.nhn?blogId=seogi1004&logNo=110086946825
Posted by 오늘마감
XCODE2011.04.09 11:13
출처 - http://www.cocoadev.co.kr/55






프로젝트 진행 시에 다수 작업, 디버깅, 백업의 의미로 버젼관리는 매우 중요합니다. Xcode에서는  CVS, Subversion, Perforce, 3종류의 SCM(Software Configuration Management) 시스템을 지원합니다.

CVS
오픈소스로 유닉스/리눅스 계열에서 가장 오랫동안 많이 사용하는 버젼관리 시스템입니다. OS X에는 기본으로 설치가 되어있어 바로 사용이 가능합니다.

Subversion
CVS를 대체하기 위해서 나온 버젼관리 시스템으로, CVS에 비해 많은 장점을 가지고 있습니다. 여기서는 Subversion을 이용해 보겠습니다.

Perforce
Perforce Software에서 제공하는 상용 버젼관리 툴입니다.

SVS와 Subversion에 관한 자세한 사항은 아래의 KLDP Wiki를 확인하시고, 여기서는 Xcode에서 Subversion을 사용하는 방법에 대해서 간단히 알아 보겠습니다.


1. Subversion 다운로드/설치

이곳을 클릭하시고 맥 OS X용 Subversion 설치파일(dmg)을 다운로드 받습니다.

현재 버젼은 1.4.4로 설치 프로그램을 실행하시면 간단히 설치하실 수 있습니다.

(소스코드설치를 원하시면 Subversion 사이트에 서 다운로드 받으실 수 있습니다.)

설치가 완료되면 /usr/local/bin/에 실행파일들이 위치합니다. .bash_profile의 PATH에 /usr/local/bin을 추가하시면 터미널에서 사용이 편리합니다.


2. 프로젝트에 Subversion 적용

저 는 Test란 프로젝트에 적용해 보겠습니다. 프로젝트명, 위치등은 각자 환경에 맞게 변경하여 작업하시면 됩니다. 우선 아래와 같이 저장소 디렉토리 svn_test를 생성합니다.

>/usr/local/bin/svnadmin create ~/svn_test


프로젝트를 가져오기 위하여 아래와 같이 tmp라는 임시폴더와 그 아래 trunk, branches, tags 디렉토리를 각각 생성합니다. 그 후에 cp 명령으로 적용시킬 프로젝트를 임시 디렉토리로 복사합니다.  [프로젝트 디렉토리]는 가져 올 프로젝트가 위치한 경로 입니다.

> mkdir tmp
> mkdir tmp/Test
> cd tmp/Test
> mkdir trunk
> mkdir branches
> mkdir tags
> cp -r [프로젝트 디렉토리] ~/tmp/Test/trunk


이 제 svn_test 저장소로 프로젝트를 저장합니다. [계정아이디]는 현재 계정 아이디를 입력하시면 됩니다. 아래의 이미지를 클릭하시면 확대하여 확인하실 수 있습니다.

>/usr/local/bin/svn import ~/tmp/Test file:///Users/[계정아이디]/svn_test --message 'Start...'



그 후에 작업할 디렉토리로 프로젝트를 가지고 옵니다. [프로젝트 디렉토리]는 Test 프로젝트를 저장소로 부터 가져 올 디렉토리이며 전 ~/Projects란 디렉토리로 설정하였습니다. 위와 같이 아래의 이미지를 클릭하여 보시면 이해가 빠르실 겁니다.

> cd [프로젝트 디렉토리]
> /usr/local/bin/svn checkout file:///Users/[계정아이디]/svn_test Test


임 시 폴더를 아래와 같이 삭제하고,  확인을 위하여 Xcode를 실행합니다.

> cd ~/tmp/
> rm -fR Test/


3. Xcode 설정 및 확인


이제 Xcode의 Open메뉴에서 터미널에서 설정하였던 디렉토리의 trunk/[프로젝트명]에서 프로젝트 파일을 가지고 옵니다. 저는 Projects/Test/trunk/Test로 되어 있습니다.

프로젝트 정보창을 열어 Genral  메뉴 하단의 SCM 설정을 아래와 같이 Subversion으로 선택하고 Enable SCM을 체크합니다.

이제 소스코드를 수정하여 봅니다. 확인을 위하여 아래와 같이 기존 소스에 "NSLog..." 라인을 추가하였습니다.

이제 Xcode의 SCM 메뉴에서 Compare With Revision... 을 실행합니다. 비교할 버젼을 선택한 후 [Compare] 버튼을 클릭하시면 이전 버젼과 현재 파일의 차이점을 아래와 같이 확인하실 수 있습니다.

이 제 SCM 메뉴의 Commit Changes... 을 클릭하여 현재 상태를 새로 저장합니다. 변경에 대한 간단한 메시지를 작성한 후 [commit] 버튼을 클릭합니다. Get SCM Info를 클릭하시면 아래와 같이 Test.m 파일에 관한 버젼 히스토리를 확인할 수 있습니다.




출처 : http://blog.naver.com/PostView.nhn?blogId=seogi1004&logNo=110085698583

'XCODE' 카테고리의 다른 글

Xcode 삭제  (0) 2011.04.09
[Objective-C] Xcode프로젝트 창  (0) 2011.04.09
[펌] Xcode 에 Subversion 적용하기  (0) 2011.04.09
XCODE용 디버그 메크로  (0) 2011.04.09
새로운 개발툴 XCODE 4  (0) 2011.04.09
[OSX] Xcode 맥과 아이폰 프로그래밍의 준비  (0) 2011.04.09
Posted by 오늘마감
출처 - http://www.cocoadev.co.kr/185




이번에는 CoreData를 이용하는 간단한 샘플을 만들어 보겠습니다. 이전에 Xcode 2.*대에서 이와 비슷한 어플리케이션을 만드는 "간단한 ToDo 어플리케이션 만들기"란 포스팅을 한적이 있습니다. 소스코드에 추가 없이 마우스 클릭만으로 간단히 만드는 예제였는데 Xcode 3에서는 그 마우스 클릭도 최소한으로 줄이고 자동화여, 누구나 쉽게 간단한 어플리케이션을 만들 수 있습니다.

Core Data에 대한 자세한 내용은 아래의  ADC 문서들을 참조하시기 바랍니다.



1. 프로젝트 생성
Xcode를 실행하고 새로운 프로젝트를 생성하기 위해 메뉴에서 File / New Project.. 를 클릭합니다. 아래와 같이 Mac OS X / Application 항목에서 Core Data Document-based Application을 선택하고 Choose...를 클릭합니다.
프로젝트 명에 'BookList'를 입력하고 save 버튼을 클릭하여 완료합니다.


2.  Data Model
1) Data Modeling tool
좌측과 같이 Xcode의 Groups & Files아래에 BookList / Models에서 MyDocument.xcdatamodel을 더블클릭합니다.

아래와 같은 데이터 모델링 툴이 오픈됩니다.
2) Entity 추가
위의 이미지에서 붉은색 화살표가 가르키는 Entity 항목 하단의 + 버튼을 클릭하여 새로운 Entity를 추가합니다. 생성된 항목을 더블클릭하거나 우측의 설정창에서 Name: 항목의 입력창을 이용하여 아래와 같이 'Books'로 이름을 변경합니다.


3) Attribute 설정
* 추가
이제 Books에 속성(Attribute)를 추가합니다. Property창 하단의 + 버튼을 클릭하여 나오는 항목중 Add Attrribute를 클릭합니다. 2번 더 반복하여 3개의 속성을 생성합니다.

* 설정
속성들의 이름을 각각 titile, writer, press로 입력하고 아래와 같이 항목들을 설정합니다.




3. 인터페이스 빌더
Xcode에서 MyDocument.xib를 더블클릭하여 인터페이스 빌더를 오픈합니다. 먼저 윈도우에 기본으로 생성되어 있는 "Your document contetents here'  라벨을 삭제합니다.

그리고 라이브러리 윈도우의 Cocoa / Objects & Controllers / Core Data 항목에서 좌측과 같은 Core Data Entity를 드래그하여 윈도우로 가져다 놓습니다.



1) Core Data Entity 생성
윈도우로 드래그를 완료하면 설장창이 오픈됩니다. 아래와 같이 entity를 Books로 선택하고 Next 버튼을 클릭하고 각 단계별로 아래와 같이 진행합니다.
2) 윈도우 크기 조절
생성된 항목에 맞추어 아래와 같이 윈도우의 크기를 적당히 조절합니다.

4. Build & Test
현재까지의 작업만으로 기본적인 동작을 수행할 수 있는 작업이 완료되었습니다. 이제 빌드를 하고 어플리케이션을 실행하여 테스트 합니다.
어플리케 이션이 실행되면 등록, 변경, 삭제, 검색 등과 파일 저장/오픈이 동작하는지 확인합니다.





출처 : http://blog.naver.com/PostView.nhn?blogId=seogi1004&logNo=110085700513
Posted by 오늘마감
출처 - http://www.cocoadev.co.kr/183



Xcode3 에서 간단한 코코아 UI 샘플을 만들어 보는 튜토리얼입니다. 아래와 같이 하나의 입력 창과 세개의 버튼을 가진 간단한 어플리케이션 입니다.

각각의 버튼들의 기능은 아래와 같습니다. 라벨의 이동시에는 animator를 이용해 간단한 효과를 주었습니다.

텍스트에 입력된 내용을 상단의 라벨에 출력합니다.

라벨이 원래 있던 좌측의 위치로 이동하도록 합니다.

라벨이 우측 끝으로 이동하도록 합니다.


1. 프로젝트 생성
Xcode를 실행하고 메뉴에서 File/New Project...를 클릭합니다. 좌측에서 Mac OS X/Application을 선택하고 Cocoa Application 템플릿을 선택한 후, Choose... 버튼을 클릭합니다. 

(iPhone SDK 설치되어 있지 않으면 좌측의 메뉴가 조금 다를 수도 있습니다)

프로젝트가 저장될 디렉토리를 선택한 후에 프로젝트명(Control1)을 입력하고 Save 버튼을 클릭합니다.



2. 인터페이스 빌더
1) 인터페이스 빌더 실행
좌측과 같이 Xcode의 Groups & Files/Resources의 MainMenu.xib를 더블클릭하여 인터페이스 빌더를 실행합니다.







2) 라이브러리 윈도우
인터페이스 빌더의 메뉴에서 Tools/Library를 클릭하거나 단축키(Shift+Command+L)를 이용하여 아래와 같은 라이브러리 윈도우를 오픈합니다. 이 윈도우 하단의 아이템중에서 필요한 각종 오브젝트나 컨트롤들을 원하는 위치에 드래그하여 사용할 수 있습니다.



3) 윈도우
라이브러리 윈도에서 아래와 같이 Label, Text Field, Push Button을 드래그 해서 윈도우에 아래와 같이 배치하고 윈도우 크기를 적당하게 조절합니다.


라이브러리 윈도우에서 각 컨트롤의 위치는 아래와 같습니다.

  • Label - Cocoa / Views & Cell / Input & Values
  • Text Field - Cocoa / Views & Cell / Input & Values
  • Puish Button - Cocoa / Views & Cell / Buttons


3. AppController
1) 소스파일 생성
다시 Xcode로 돌아와 Groups & Files에서 Classes를 우클릭을 하거나 단축키(Command+N)를 이용하여 파일생성 창을 오픈합니다.


Mac OS X/Cocoa에서 Objective-C class를 선택하고 Next 버튼을 클릭합니다.

파일명에 AppController.m을 입력하고 Finish 버튼을 클릭합니다.

좌측과 같이 AppController.h와 AppController.m 소스 파일이 Classes 아래에 생성되었습니다.

먼저 AppController.h를 클릭하여 소스를 변경합니다.


2) AppController.h
헤더 파일에서 아래에 푸른색으로 되어 있는 부분을 입력합니다.
#import <Cocoa/Cocoa.h>

@interface AppController : NSObject {
    IBOutlet NSTextField    *textLabel;
    IBOutlet NSTextField    *inputField;
   
    IBOutlet NSButton    *refreshButton;
    IBOutlet NSButton    *leftButton;
    IBOutlet NSButton    *rightButton;

    NSPoint    originalPoint;
}

- (IBAction)setLabel:(id)sender;
- (IBAction)moveLeft:(id)sender;
- (IBAction)moveRight:(id)sender;

@end

인터페이스 빌더에서 생성한 각각의 컨트롤들을 연결하기 위해 IBOutlet 변수와 버튼을 클릭했을 경우에 처리할 IBAction 메소드를 선언합니다.

3) AppController.m
 소스코드에서 아래에 푸른색으로 되어 있는 부분을 입력합니다.
#import "AppController.h"

@implementation AppController

- (void)awakeFromNib {
   
    // 버튼 이미지를 지정
    NSImage *buttonImage = [NSImage imageNamed:NSImageNameRefreshTemplate];
    [refreshButton setImage:buttonImage];

    buttonImage = [NSImage imageNamed:NSImageNameGoLeftTemplate];
    [leftButton setImage:buttonImage];
   
    buttonImage = [NSImage imageNamed:NSImageNameGoRightTemplate];
    [rightButton setImage:buttonImage];
   
    originalPoint = [textLabel frame].origin;
}

- (IBAction)setLabel:(id)sender {
   
    // 입력한 문자를 라벨에 지정하고 라벨의 크기를 문자열의 길이만큼 변경
    [textLabel setStringValue:[inputField stringValue]];   
    [textLabel sizeToFit];
}

- (IBAction)moveLeft:(id)sender {
   
    // 라벨을 초기 위치로 이동
    [[textLabel animator] setFrameOrigin:originalPoint];
}

- (IBAction)moveRight:(id)sender {
    CGFloat xPos;
   
    // 우측 모서리로 이동하도록 윈도우의 크기에서 라벨의 크기를 뺀 위치로 설정
    xPos = [[[NSApp mainWindow] contentView] bounds].size.width;
    xPos -= [textLabel frame].size.width;
   
    // 에니메이션과 함께 라벨의 위치 변경
    NSPoint targetPoint = NSMakePoint(xPos, originalPoint.y);
    [[textLabel animator] setFrameOrigin:targetPoint];
}

@end


4. 연결
다시 인터페이스 빌더로 돌아 가서 작업을 마무리 합니다

1) AppController 인스턴스 생성
라이브러리 윈도우에서 좌측과 같은 Object를 MainMenu.xib 윈도우로 드래그해서 가져다 놓습니다.

Object는 라이브러리 윈도우에서 Cocoa / Objects & Controllers / Controllers내에 있습니다.

아래와 같이 Object가 생성된 것을 확인하시고 Object가 선택된 상태에서 인터페이스 빌더의 Tools/Inspector 메뉴를 클릭하거나 단축키 (Shift + Command + I)를 이용하여 Inspector 창을 오픈합니다.

Inspector 창에서 좌측과 같이 6번째에 있는 App Controller Identity를 선택합니다. (단축키: Command + 6)

Class메뉴의 콤보박스를 클릭하고 Xcode에서 이전 단계에서 생성한 AppController를 선택합니다.


2) 연결
MainMenu.xib 창에서 App Controller를 선택한 상태에서 마우스 우클릭을 하면 아래와 같이 연결 창이 오픈됩니다.


연결창의 각 항목 좌측에 있는 원 모양의 영역에 마우스를 가져가면 우측과 같이 '+' 모양으로 변경됩니다. 이 상태에서 마우스로 '+'를 클릭한 후에 드래그 하여 각각의 해당 항목들에 연결합니다.

마우스를 클릭한 상태에서 파란색 선을 연결할 컨트롤로 가져가면 아래와 같이 컨트롤의 이름과 함께 선택되었을 때 마우스 클릭을 해제합니다.


이런 방식으로 Outlet과 Action을 각각의 컨트롤들과 연결합니다.

  • Outlets / inputField -> Text Field 
  • Outlets / textLabel -> Label
  • Outlets / refreshButton -> Button (첫번째)
  • Outlets / leftButton -> Button (두번째)
  • Outlets / rightButton -> Button (세번째)

  • Received Actions / setLabel -> 버튼 (첫번째)
  • Received Actions / moveLeft -> 버튼 (두번째)
  • Received Actions / moveRight -> 버튼 (세번째)

작업이 완료되면 아래와 같이 연결되었는지 확인합니다.

 
3) 빌드 및 테스트
이제 모든 작업이 완료되었습니다. 인터페이스 빌더와 Xcode에서 변경된 내용을 저장하고, Xcode에서 좌측의 툴바를 클릭하거나 단축키(command + R)를 이용하여 빌드하고 테스트 해 봅니다.


Xcode를 처음 해보시는 분들도 따라 하실 수 있게 최대한 자세하게 설명을 할려고 했습니다. 하지만 제 생각대로 처음 하시는 분들도 무리없이 하실 수 있을지는 잘 모르겠습니다.

잘 안되시는 분들은 아래의 프로젝트 파일을 다운로드 받아서 비교해 보시기 바랍니다.



출처 : http://blog.naver.com/PostView.nhn?blogId=seogi1004&logNo=110085700437

'아이폰어플개발정보' 카테고리의 다른 글

[펌] 2. 간단한 Core Data 예제  (0) 2011.04.09
애플 앱스토어 등록 Tip  (0) 2011.04.09
[펌] 1. Xcode3 첫 어플리케이션  (0) 2011.04.09
[펌] 1.10 기본 콘트롤 사용법  (0) 2011.04.09
[펌] Delegate  (0) 2011.04.09
아이폰 사운드 재생방법  (0) 2011.04.09
Posted by 오늘마감
[출처] - http://www.cocoadev.co.kr/94





흔히 사용되는 컨트롤들의 간단한 사용법을 알아 보겠습니다.
만들려는 예제의 모습은 좌측과 같습니다. 각 컨트롤들의 설정에 따라서 상단 텍스트 필드의 내용을 변경하여 보여주는 샘플을 작성해 보겠습니다.

이 예제를 따라 해보기 위해서는 인터페이스 빌더의 사용법과  인스턴스 생성, 인스턴스와의 연결 등에 관한 기본 내용을 알고 있어야 합니다. 잘 이해가지 않는 분들은 이전 포스트를 확인해 보신 후에 다시 보시기 바랍니다.



1. AppController 생성

XCode 에서 Cocoa Application으로 새로운 프로젝트를 생성합니다. 다시 New File에서 Objective-C Class를 선택한 후에 AppController란 이름으로 새로운 클래스를 생성합니다.

1) AppController.h 변경
이번 장에서 사용할 컨트롤들은 아래와 같습니다. 아래의 컨트롤들을 인터페이스 빌더에서 연결하기 위해 IBOutlet 변수들을 생성합니다.
NSTextField, NSTableView, NSMatrix, NSComboBox, NSColorWell, NSSlider, NSButton, NSProgressIndicator  

사용자의 조작으로 컨트롤의 상태가 변하는 알림 메시지를 받을 메소드를 생성합니다. 각 메소드는 아래와 같습니다.

- (IBAction)setDisplayText:(id)sender;
- (IBAction)adverbSelecterChanged:(id)sender;
- (IBAction)alignSliderChanged:(id)sender;
- (IBAction)notCheckerChanged:(id)sender;
- (IBAction)subjectMatrixChanged:(id)sender;
- (IBAction)colorWellChanged:(id)sender;

AppController.h
#import <Cocoa/Cocoa.h>

@interface AppController : NSObject {
    IBOutlet NSTextField* displayString;
    IBOutlet NSTableView* wordList;
    IBOutlet NSMatrix* subjectMatrix;
    IBOutlet NSComboBox* adverbSelecter;
    IBOutlet NSColorWell* colorWell;
    IBOutlet NSSlider* alignSlider;
    IBOutlet NSButton* notChecker;
    IBOutlet NSProgressIndicator* progressBar;   
}

- (int)numberOfRowsInTableView:(NSTableView *)tableView;
- (id)tableView:(NSTableView *)tableView
    objectValueForTableColumn:(NSTableColumn *)tableColumn
            row:(int)row;

- (IBAction)setDisplayText:(id)sender;
- (IBAction)adverbSelecterChanged:(id)sender;
- (IBAction)alignSliderChanged:(id)sender;
- (IBAction)notCheckerChanged:(id)sender;
- (IBAction)subjectMatrixChanged:(id)sender;
- (IBAction)colorWellChanged:(id)sender;

@end


2) AppController.m 변경

TableView는 좌측과 같이 테이블 형식으로 목록을 보여주는 컨트롤입니다. 각 셀에 데이터를 입력하기 위해서는 데이터를 등록하여 주는 dataSource를 지정해야 합니다.

여기서는  나중에 인터페이스 빌더에서 AppController를 dataSource로 등록하겠습니다. tableView의 dataSource가 되면 데이터를 요구하는 메시지에 응답하기 위해서 아래와 같은 두개의 메소드를 구현해야 합니다.

- (int)numberOfRowsInTableView:(NStableView *)tableView;
목록의 갯수를 반환합니다.

- (id)tableView:(NSTableView *)tableView
    objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row

각 셀의 데이터를 반환합니다. 이 반환된 값들로 각 셀들이 채워집니다. 셀에 데이터를 등록하는 것은 다음 포스팅에서 구현해 보겠습니다.

메시지를 처리하는 각 메소드들은 실제 기능을 구현하기 전에 정확히 동작하는지 확인하기 위해서 NSLog를 추가합니다. 소스파일 전체는 아래와 같습니다.

AppController.m
#import "AppController.h"

@implementation AppController

- (void)awakeFromNib
{
}

- (void)dealloc
{
    [super dealloc];
}

- (IBAction)setDisplayText:(id)sender
{
    NSLog(@"Button colicked");
}

- (IBAction)adverbSelecterChanged:(id)sender
{
    NSLog(@"adverbSelecter changed");
}

- (IBAction)alignSliderChanged:(id)sender
{
    NSLog(@"alignSlider Changed");
}

- (IBAction)notCheckerChanged:(id)sender
{
    NSLog(@"notChecker changed");
}

- (IBAction)subjectMatrixChanged:(id)sender
{
    NSLog(@"subject matix");
}

- (IBAction)colorWellChanged:(id)sender
{
    NSLog(@"colorWell changed");
}

- (int)numberOfRowsInTableView:(NSTableView *)tableView
{
    NSLog(@"tableView getRowCount");
    return 1;
}

- (id)tableView:(NSTableView *)tableView
    objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
{
    NSLog(@"tableView getColumnValue");
    return nil;
}

@end


2. 인터페이스 빌더에서 작업
 
1) 컨트롤 배치

윈도우에 각 컨트롤들이 배치되어야 할 모습은 아래와 같습니다.


팔레트에서 마우스 포인터를 해당 컨트롤 위에 놓으면 좌측의 빨간 화살표가 가르키는 것과 같이 컨트롤의 종류를 확인할 수 있습니다.

위의 이미지를 참조하여 팔레트에서 각각의 콘트롤들을 드래그로 가지고 와서 배치 합니다.





2) 속성 설정
각각의 콘트롤들의 속성을 변경합니다.

NSTextField
텍스트필드의 옵션을 좌측과 같이 설정합니다. 사용자의 입력은 받지 않기 때문에 Editable, Enabled를 해제합니다.


NSTableView
Attributes에서 Columns를 2로 설정합니다.
NSTableView를 더블클릭하면 좌측과 같이 푸른 테두리가  나타납니다. 이 상태에서 컬럼을 더블클릭하여 입력 모드로 변경되면 이름을 변경할 수 있습니다.

각각 목적어, 동사로 변경합니다.

NSMatrix
Rows 는 1 Cols는 2로 설정하고 Mode가 'Radio'로 되어 있음을 확인합니다.

NSComboBox
좌측과 같이 Visible Items를 4로 입력하고 4개의 항목을 추가합니다.

추가는 하단의 입력필드에서 이름을 입력 후에 [+] 버튼을 클릭합니다. 삭제는 아이템을 선택한 후에 [-]버튼을 클릭합니다.



NSColorWell
변 경없이 기본값을 유지합니다.

NSSlider
좌측과 같이 최소값을 0.0, 최대값을 100.0, 기본값을 50.0으로 설정합니다. 세단계만 선택되게 하기 위해 Number Of Markers를 3으로  Stop on ticks marks only를 체크 합니다.


NSButton
Type이  'CheckBox'로 되어 있음을 확인하고 Title에 '부정어로 만듭니다.'로 입력합니다.

NSProgressIndicator  
MinumRange 는 0.0, MaximumRange는 100.0으로 설정하고 Indeterminate를 체크 합니다.

2) AppControll 인스턴스 생성
AppController.h 를 인터페이스 빌더의 MainMenu.nib 윈도우로 드래그 해 놓습니다. Classes 항목에서 AppController를 우클릭하여 Instantiate AppController를 선택하여 인스턴스를 생성합니다.

이제 아래의 연결된 모습을 참조하여 윈도우의 각 항목들을 AppController의 IBOutlet 변수와 IBAction 메소드로 연결합니다.

각 컨트롤들은 아래의 AppController의 IBAction 메소드와 연결됩니다.
  • adverbSelecterChanged <- NSComboBox
  • alignSliderChanged <- NSSlider
  • notCheckerChanged <-NSButton (Check Box)
  • subjectMatrixChanged <- NSMatrix
  • colorWellChanged <- NSColorWell
  • setDisplayText <- NSButton (적용 Button)
 
마지막으로 위에 설명한 대로 좌측과 같이  TableView의 dataSource를 AppControll로 설정합니다.








이 제 컴파일 하고 실행한 후에 각각의 콘트롤의 값과 상태를 변경하여 봅니다. 그리고 RunLog 창에서 아래와 같이 메시지를 보내고 받는지 확인합니다.

잘 동작하지 않는 분들은 아래의 샘플 파일을 다운로드 받으신 후에 비교해 보시기 바랍니다.





이전 포스트에 이어서 프로그램을 완성해 보겠습니다. 이전의 소스에서 아래의 청색으 로 된 부분을 추가합니다.

1. AppController.h 수정

#import <Cocoa/Cocoa.h>

@interface AppController : NSObject {
    NSMutableString *curString;
    NSString* dataArray[3][2];
   
    IBOutlet NSTextField* displayString;
    IBOutlet NSTableView* wordList;
    IBOutlet NSMatrix* subjectMatrix;
    IBOutlet NSComboBox* adverbSelecter;
    IBOutlet NSColorWell* colorWell;
    IBOutlet NSSlider* alignSlider;
    IBOutlet NSButton* notChecker;
    IBOutlet NSProgressIndicator* progressBar;   
}

- (int)numberOfRowsInTableView:(NSTableView *)tableView;
- (id)tableView:(NSTableView *)tableView
    objectValueForTableColumn:(NSTableColumn *)tableColumn
            row:(int)row;

- (IBAction)setDisplayText:(id)sender;
- (IBAction)adverbSelecterChanged:(id)sender;
- (IBAction)alignSliderChanged:(id)sender;
- (IBAction)notCheckerChanged:(id)sender;
- (IBAction)subjectMatrixChanged:(id)sender;
- (IBAction)colorWellChanged:(id)sender;
- (IBAction)wordListChanged:(id)sender;
@end


2. 인터페이스 빌더에서 수정

변경한 소스를 저장한 후에 변경된 사항을 인터페이스 빌더에 적용하기 위해서 다시 AppController.h 파일아이콘을 드래그 하여 인터페이스 빌더의 MainMenu.nib에 놓습니다.

좌측과 같이 윈도우의 TableView중에 목적어 컬럼을 선택합니다. 속성창을 열어 Identifier 항목을 1로 설정합니다.

이와 동일하게 동사 컬럼의 Identifier는 2로 설정합니다.




AppController에서 새로 추가한 메소드인 wordListChanged르 TableView에 연결합니다.

TableView를 선택하고 Control키를 클릭한 채 마우스로 드래그 하여 AppController 인스턴스에 가져다 놓습니다. 좌측의 속성 화면에서 wordListChanged를 선택하고 연결합니다.

(연결이 어려우신 분들은 이전 포스트를 참조하세요.)


3. AppController.m 수정

#import "AppController.h"

@implementation AppController

- (id)init
{
    self = [super init];
   
    curString = [[NSMutableString alloc] init];

    /* 목적어 데이터 설정 */

    dataArray[0][0] = [[NSString alloc] initWithUTF8String:"철수를"];
    dataArray[1][0] = [[NSString alloc] initWithUTF8String:"영희를"];
    dataArray[2][0] = [[NSString alloc] initWithUTF8String:"바둑이를"];
   
    /* 동사 데이터 설정 */
    dataArray[0][1] = [[NSString alloc] initWithUTF8String:"사랑했다"];

    dataArray[1][1] = [[NSString alloc] initWithUTF8String:"싫어했다"];
    dataArray[2][1] = [[NSString alloc] initWithUTF8String:"때렸다"];
   
    return self;
}

- (void)awakeFromNib
{
}

- (void)dealloc
{
    int i, j;
   
    /* 할당된 오브젝트 해제 */
    for(i = 0; i < 3; i++)
    {
        for(j = 0; j < 2; j++)
        {
            [dataArray[i][j] dealloc];
        }
    }
   
    [curString dealloc];
    [super dealloc];
}

- (IBAction)setDisplayText:(id)sender
{
    int pos = [wordList selectedRow]; // 테이블뷰에서 현재 선택된 열
    if(pos == -1) // 없으면 실행하지 않는다
        return;
   
    /** 조건에 따른 문자열 설정 */
    if([[subjectMatrix selectedCell] tag] == 0)
        [curString setString:[NSString stringWithUTF8String:"나는 "]];
    else
        [curString setString:[NSString stringWithUTF8String:"너는 "]];
   
    [curString appendString:dataArray[pos][0]];
    [curString appendString:@" "];
    [curString appendString: [adverbSelecter stringValue]];
       
    if([notChecker state] == NSOnState)
        [curString appendString:[NSString stringWithUTF8String:" 안 "]];
   
    [curString appendString:dataArray[pos][1]];
   
    /* 색상 설정 */
    [displayString setTextColor:[colorWell color]];
   
    /* 정렬 설정 */
    int align = [alignSlider intValue];

    if(align == 0)
        [displayString setAlignment:NSLeftTextAlignment];
    else if(align == 50)
        [displayString setAlignment:NSCenterTextAlignment];
    else
        [displayString setAlignment:NSRightTextAlignment];
   
    /* 텍스트 출력 */
    [displayString setStringValue:curString];
   
    /* 진행 상태바 에니메이션 중지 */
    [progressBar stopAnimation:self];

}

- (IBAction)adverbSelecterChanged:(id)sender
{
    /* 변경시 진행 상태바 에니메이션 시작 */
    [progressBar startAnimation:self];
}

- (IBAction)alignSliderChanged:(id)sender
{
    [progressBar startAnimation:self];
}

- (IBAction)notCheckerChanged:(id)sender
{
    [progressBar startAnimation:self];
}

- (IBAction)subjectMatrixChanged:(id)sender
{
    [progressBar startAnimation:self];
}

- (IBAction)colorWellChanged:(id)sender
{
    [progressBar startAnimation:self];
}

- (IBAction)wordListChanged:(id)sender
{
    [progressBar startAnimation:self];
}

- (int)numberOfRowsInTableView:(NSTableView *)tableView
{
    /* 테이블 열 갯수 3 반환 */
    return 3;

}

- (id)tableView:(NSTableView *)tableView
    objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
{
    int pos;

    /** 현재 설정되어야 할 TableView의 컬럼을 반환한다. */
    if([[tableColumn identifier] characterAtIndex:0] == '1')
        pos = 0;
    else
        pos = 1;
   
    return dataArray[row][pos];
}

@end


이제 빌드를 하고 실행 하시면 좌측과 같이 어플리케이션이 실행됩니다. 각각의 옵션을 선택하고 [적용] 버튼을 클릭하면 선택된 옵션에 맞추어 상단에 텍스트가 출력됩니다.

옵션에 변동이 일어나면 하단의 바가 에니메이션되며 [적용] 버튼을 클릭하여 적용이 완료되면 진행 상태바의 에니메이션이 중지 됩니다.

전체 프로젝트 소스파일은 아래를 클릭해서 다운로드 받이스면 됩니다.











출처 : http://blog.naver.com/PostView.nhn?blogId=seogi1004&logNo=110085699616
Posted by 오늘마감

Objecive-C를 좀 보고, Xcode 좀 봐보고 Interface Builder 좀 보고 Hello, World 같은 거 한 번 만들어보고...

슬슬 깊이 들여다보려고 하면 많이 눈에 띄는 것들이 있다.
어쩌구View, 어쩌구Controller 그리고 어쩌구Delegate 이런것들이다.
그 중에 오늘은 delegate에 대해서 한 번 알아보자. 이건 맥/아이폰/팟용 어플을 개발하는데 꼭 알고 넘어가야 할 부분이다.

뭔가 낯설은 단어 delegate. 그치만 단어 그 자체로 받아들이면 된다. 대리인.
delegate을 처음 접한다면 아직 뭔소린지 잘 감이 오질 않을것이다. 그치만 이 글을 다 읽고 나면, 아! delegate 대리인!이 머리속에 자리잡힐 것이다.

우선 기존 개발을 하시던 분이라면,
서브클래싱, 혹은 클래스를 상속받아서 새로운 클래스를 만들어서 사용하는 것
또는 델파이/C++Builder 쪽에서 보면 Event 같은 것이라고 볼 수 있다.

자 그럼 본격적으로.....
UITextField 클래스를 예로 들어보자. UITextField는 사용자에게 텍스트를 입력받는 기능을 하는 클래스이다.
이 클래스의 인스턴스를 하나 만들고 사용을 하면, text 속성을 통해서 입력받은 텍스트를 알아낼 수 있고 textColor 속성으로 글자의 색을 변경할 수 있는 등의 작업을 할 수 있다.

그런데, 만일 이 TextField에서 사용자가 키보드 입력을 시작했을 때 특정한 일을 하게 하고 싶으면 어떻게 할까?
(델파이/C++Builder 사용하는 개발자라면, Edit1->OnChange=Edit1Change; 로 이벤트 연결을 시켜주면 될 것이다.)
Cocoa에서는 TextField에 delegate(대리인)을 지정해주고 그 delegate(대리인)이 지정된 함수를 만들고 그 안에서 하고자 하는 일을 하면 된다.

// <UITextFieldDelegate>라고 입력해서 MyController가 UITextField의 delegate 역할을 할것임을 알려준다.
@interface MyController: NSObject <UITextFieldDelegate> {
UITextField *textField;
}
@end

@implement MyController
-(id)init {
if(self = [super init]) {
textField = [[UITextField alloc] init];
textField.delegate = self; // MyController를 textField의 delegate(대리인)으로 지정한다.
// MyController가 textField에서 지정된 역할을 처리할 수 있게 되었다는 의미이다. 
}
return self;
}
// UITextFieldDelegate의 Method 구현
// UITextFieldDelegate를 도움말에서 찾으면 어떤 Method들이 있는지 확인해볼 수 있고,
// 거기서 필요한 것들을 구현해주면 된다.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
// 이곳에 textField에서 사용자가 무언가 입력을 시작할 때 
// 처리하고 싶은 일을 처리하면 된다.
}
@end

UITextField의 Instance인 textField는 사용자가 텍스트 입력을 시작하면, delegate가 지정되어 있다면 delegate에게 "야! 사용자가 입력시작했다. 뭐 처리할 것 있으면 해!"라고 알려준다. 그럼 delegate(대리인, 위 예에서는 MyController)는 지정된 함수를 구현하고 있으면 되는 것이다.

필수로 구현해야하는 것들도 있고, 옵션으로 필요한 경우에만 구현해도 되는 것들이 있으니 도움말을 참고해서 필요한 것들을 구현해주면 된다.


자, 그럼 이번에는 내가 만드는 클래스에서도 delegate를 한 번 만들어 사용해보자.
//-------------------------------------- MyTestDelegate interface
@interface NSObject (MyTestDelegate)
-(void) testDidBeginSomething:(UIMyClass*)myClass;
-(void) testDidEndSomething;(UIMyClass*)myClass withArgument:(int)arg;
@end
//-------------------------------------- MyTestClass interface
@interface MyTestClass{
id delegate;
...
}
@property (nonatomic, assign) id delegate;
-(void) myMethod1;
-(void) myMethod2;
...
@end;
//-------------------------------------- MyTestClass implementation
@implement MyTestClass
@synthesize delegate;
-(void) myMethod1 {
...
if(delegate && [delegate respondsToSelector:@selector(testDidBeginSomething:)])
[delegate testDidBeginSomething:self];
...
}
-(void) myMethod2 {
...
if(delegate && [delegate respondsToSelector:@selector(testDidEndSomething:withArgument:)])
[delegate testDidEndSomething:self withArgument:100];
...
}
@end
//-------------------------------------- MyTestController interface
@interface MyTestController {
MyTestClass *test;
...
}
...
@end
//-------------------------------------- MyTestController implementation
@implementation MyTestController
-(id)init {
if(self = [super init]) {
test = [[MyTestClass alloc] init];
test.delegate = self; // MyTestController를 test의 delegate로 지정
}
return self;
}
// MyTestClass의 delegate로써 처리할 method들 구현
-(void)testDidBeginSomething:(MyTestClass*)testClass {
// 이곳에 처리할 일들을 처리하면 됨.
// 처리해야할 것이 없으면 이 Method 자체를 구현 안해도 됨.
}
-(void)testDidEndSomething:(MyTestClass*)testClass withArgument:arg1 {
// 이곳에서도 처리할 일들을 처리하면 됨.
// 처리해야할 것이 없으면 이 Method 자체를 구현 안해도 됨.
}
@end

delegate interface를 선언하는 방법은 위처럼 NSObject (Delegate이름) 을 이용해서 선언할 수도 있고, protocol 을 사용할 수도 있는데, protocol을 사용하는 방법은 다음번에 기회가 되면 설명하도록 하겠다.
혹 지금 당장 궁금하다면, 구글링을 하러 고고! (대략 delegate가 어떤 것인지 감이 잡혔다면 금방 이해가 될 것이다.)

아이폰/팟 어플리케이션에서는 UITableView를 이용하는 경우가 많은데, delegate에 대해 감을 잡고 있으면 쉽게 사용할 수 있다. 도움말에서 UITableView와 UITableViewDelegate를 한 번 찾아서 살펴보면 음..이렇게 구성되어 있구나..라고 생각하면 된다.


갑자기 엉뚱한 소리지만, Cocoa를 공부하면서 다시 한 번 C++Builder(델파이) 사용자로서....C++Builder/델파이가 참 초직관적으로 잘 만들어져있다는 생각이 든다......Visual Studio에서 MFC사용하는 것에 비해서는 두말할 나위도 없이...
다 나름대로의 장단점들이 있겠지만, 직관성에 있어서는 C++Builder/델파이가 압승!


출처 : http://blog.naver.com/PostView.nhn?blogId=seogi1004&logNo=110087691887
Posted by 오늘마감
오브젝트C2011.04.09 10:46
커널패닉 채널에서 peniar님과 xcode 예기를 하다가 xcode가 gcc를 사용한다는 소리를
듣고서 gcc를 사용한다면 리눅스에서도 obj-c 개발 환경 구성이 가능하지 않을까 싶어
검색해보았습니다.

참고한 사이트 :: [ http://ubuntuforums.org/showthread.php?t=1064045 ]

우분투 리눅스에서는 obj-c 관련 패키지가 gobjc더군요

$sudo apt-get install gobjc

하시게되면 관련 패키지가 여럿 설치가 됩니다.

objc 소스코드를 컴파일 하는 방법은
$gcc -o -Wall 실행파일 소스코드.m -lobjc

편집기로 vim을 사용하시는 분은 .vimrc 파일에 key mapping을 통해서 
vim 내에서 컴파일이 가능하게 할 수 있습니다.

.vimrc 파일 설정
filetype on
au FileType objc map <F2> : !gcc -o -Wall %< % -lobjc
au FileType objc map <F3> : !./%<


이렇게 지정 해두시면 F2를 누르면 컴파일, F3을 누르면 실행이 됩니다.

뭐 이렇게 설정한다고 해도 리눅스에서 아이폰/아이패드 개발이 가능한 것은 아닙니다 
흣 그저 간단히 obj-c 개발이 가능할 뿐이죠 =_=


출처 : http://blog.naver.com/PostView.nhn?blogId=nsjkim&logNo=140115657293
Posted by 오늘마감

iOS와 멀티미디어 프로그래밍

지난 2월, 많은 사람들이 관심을 갖고 있는 아이패드2와 iOS 4.3 버전, Xcode 4 등이 발표됐다. 특히 아이패드2의 경우 다른 애플 제품들이 발표됐을 때처럼 스티브잡스가 제품을 직접 들고 나와서 훌륭한 프리젠테이션으로 소개하기도 했다. 이번에도 역시 제품 출시 전 여러 가지 루머들이 있었지만 이들 소문이 무색할 정도로 뛰어난 사양의 제품이었다.

안경훈 linuxgood@gmail.com | 리눅스와 맥OS에 관심이 많으며, 모바일 디바이스에서 동작되는 사용자 중심의 프로그램을 개발하는 것에 흥미를 갖고 있다. 현재 삼성SDS에서 근무 중이다.

iOS에서 오디오와 비디오를 활용한 멀티미디어 프로그램을 작성하는 방법을 알아보자. 일반적으로 iOS에서 사용되는 오디오/비디오 리소스들은 멀티미디어 프레임워크를 사용해 프로그램 된다. 이를 통해 다음과 같은 기능들이 포함된 애플리케이션을 만들 수 있다.

- 오디오 레코딩과 플레이, 스트리밍 데이터를 활용한 AV 플레이
- 게임 등에 등장하는 간단한 사운드 플레이
- 실시간 음성 녹음
- 아이패드 라이브러리에서의 사운드 플레이
- 비디오 플레이와 레코딩의 지원
- 간단한 비디오 플레이와 레코딩의 지원

오디오 기능 사용
iOS 4.0이 나올 무렵 아이폰4와 아이패드 등의 보급이 활성화됐다. iOS에서 사용되는 오디오 프레임워크의 사용법을 살펴보자.
멀티미디어 데이터를 재생하기 위해 사용되는 프레임워크로는 다음과 같은 것들이 있다.

● MediaPlayer.framework
음악, 오디오 북, 오디오 팟 캐스트 등과 같은 리소스들을 플레이하기 위해 사용된다.

● AVFoundation.framework
간단히 음악을 플레이하거나 녹음을 할 때 사용되는 프레임워크로서 AVAnimation이나 캡처된 아이템 등을 플레이할 때도 자주 사용된다.

● AudioToolbox.framework
패킷을 통해 전달되는 오디오나 오디오 포맷을 변경할 때, 오디오 큐를 활용해 오디오 데이터 등을 변경할 때 사용된다.

● AudioUnit.framework
컴포넌트 입력이나 출력을 위해 오디오 데이터를 가공할 때 사용된다.

● OpenAL.framework
게임이나 특별한 목적으로 사용되는 오디오 데이터를 가공할 때 사용된다. iOS는 현재 OpenAL 1.1(http://openal.org/) 버전을 지원한다.

오디오 프레임워크 사용
오디오 프레임워크를 사용하기 위해서는 다른 프레임워크를 사용할 때와 마찬가지로 #import! 명령으로 해당 프레임워크를 코드에 포함하면 된다. 다음과 같은 형식으로 코드에 포함한다.
#import! <AVFoundation/AVFoundation.h>

iOS에서 지원되는 오디오 코덱
이제 iOS에서 지원되는 오디오 코덱을 살펴보자.

● 플레이를 위한 코덱
오디오 데이터와 같은 것이 iOS에서 사용될 때에는 기본적으로 압축을 하게 되는데 이러한 압축을 실시간으로 해제해 소리가 나도록 하는 것이 코덱이다. iOS에서 코덱을 사용해 플레이 될 수 있는 오디오 포맷에는 <표 1>과 같은 것들이 있다. 일반적으로 자주 사용되는 코덱은 모두 지원한다고 생각하면 된다. <표 1>에서 볼 수 있는 하드웨어 코덱과 소프트웨어 코덱들은 동시에 같은 타입의 디코딩을 지원할 수는 없다. 즉, 하드웨어로 오디오 데이터들을 디코딩하는 중에 다른 오디오 소스를 디코딩해야 할 일이 생기면 소프트웨어 코덱을 사용해야 한다는 말이다. 반대로 소프트웨어 코덱을 사용해 디코딩할 때도 마찬가지다.

<표 1> 지원되는 하드웨어, 소프트웨어 코덱

<표 2> 녹음을 위한 하드웨어, 소프트웨어 코덱

● 녹음을 위한 코덱
iOS에서 지원되는 녹음을 위한 오디오 포맷에는 <표 2>와 같은 것들이 있다. 하드웨어를 사용한 녹음은 AAC 타입으로만 사용될 수 있다. 다른 타입으로 녹음하려면 소프트웨어를 기반으로 인코딩해야 한다.

환경에 따른 오디오 세션의 활용
오디오가 플레이 될 경우 우리는 여러 가지 예외 상황을 맞을 때가 있다. 오디오를 순간적으로 음소거(Mute)시키거나 사용자가 정지시켰을 때, 헤드폰 잭을 꽂았을 경우와 뺀 경우, 스크린 락을 걸었을 때, 시계의 알람을 울릴 때 등 각종 오디오를 재시작했을 경우에 오디오를 조절하는 API들이 있는데 이것을 오디오 세션 API라고 한다. 오디오 세션 API 중 중요한 클래스들을 살펴보자. 

<화면 1>과 같이 디자인된 애플리케이션이 있다. (http:// developer.apple.com/library/ios/#samplecode/avTouch/Listings/Classes_avTouchController_mm.html)에서 가져온 ‘avTouch’라는 샘플코드로 AVAudioSession 클래스를 사용하는 좋은 예제다.

<화면 1> avTouchController 프로그램

<화면 1>에서 보는 바와 같이 각각의 기능들이 동작하면서 오디오 세션의 조절 기능을 하게 된다. sample.m4a라는 오디오 파일을 사용자의 조작에 의해 플레이하는 역할이다. 사용되는 오브젝트들을 중심으로 알아보자.

1.  다음과 같은 헤더 파일을 불러온다.

<UIKit/UIKit.h>
<AudioToolbox/AudioToolbox.h>
<AVFoundation/AVFoundation.h>

2. 오디오 플레이를 위한 델리게이트를 추가하고 각종 버튼들을 위한 코드를 추가한다. 추가돼야 할 것은 AVAudioPlayer Delegate와 다음에 열거된 오브젝트들이다. 각각의 버튼 이름들이 화면에서 보이는 기능을 의미한다.

...
IBOutlet UIButton *playButton
IBOutlet UIButton *ffwButton
IBOutlet UIButton *rewButton
IBOutlet UISlider *volumeSlider
IBOutlet UISlider *progressBar
IBOutlet UILabel *currentTime
IBOutlet UILabel *duration
...
AVAudioPlayer *player
UIImage *playBtnBG
UIImage *pauseBtnBG
NSTimer *updateTimer
NSTimer *rewTimer
NSTimer *ffwTimer
...

음악이 연주되면서 LevelMeter 등의 애니메이션이 동작하게 되는데 그 자세한 설명을 생략하겠다(시뮬레이터에서는 레벨메터 애니메이션이 동작하지 않을 수도 있다). 또한 재생을 멈췄다가 다시 플레이 할 경우에 사용되는 타이머도 있다(NSTimer).

3.  플레이와 앞으로 가기, 볼륨 슬라이더 등에 대한 액션을 처리하기 위해 다음의 함수들을 만든다. 앞으로 감거나 뒤로 감는 동작을 위해 각각의 버튼들에 대해 press와 release 함수를 만들었다. 볼륨 슬라이드와 프로그래스 바를 위한 함수도 있다. 백그라운드로 동작하거나 포그라운드로 동작할 때의 동작을 등록하기 위해 Notification 함수도 만든다.

(IBAction)playButtonPressed:(UIButton*)sender;
(IBAction)rewButtonPressed:(UIButton*)sender;
(IBAction)rewButtonReleased:(UIButton*)sender;
(IBAction)ffwButtonPressed:(UIButton*)sender;
(IBAction)ffwButtonReleased:(UIButton*)sender;
(IBAction)volumeSliderMoved:(UISlider*)sender;
(IBAction)progressSliderMoved:(UISlider*)sender;

(void)registerForBackgroundNotifications;

4. 각 함수에 해당되는 동작에 관한 코드를 작성한다. 플레이 버튼이 눌렸을 경우 AVAudioPlayer의 객체인 player의 playing 플래그를 사용해 현재 오디오가 플레이 중인지의 여부를 판단, 플레이 중이라면 pausePalybackForPlayer라는 함수를 동작시켜 오디오 플레이를 임시로 중단시키고 플레이 중이 아니라면 startPlaybackForPlayer라는 함수로 계속 소리가 나도록 한다. 각각의 함수가 동작할 때 버튼 이미지나 현재 상황을 업데이트 해 주며 업데이트를 위한 타이머가 작동한다(updateCurrentTimeForPlayer).

<리스트 1> 오디오 플레이 버튼 입력 함수

- (IBAction)playButtonPressed:(UIButton *)sender
{
   if (player.playing == YES)
      [self pausePlaybackForPlayer: player];
   else
      [self startPlaybackForPlayer: player];
}


오디오 볼륨을 위해 볼륨 슬라이드를 움직일 경우 UISlider로부터 전달된 player 객체의 볼륨 조절 함수가 동작해 볼륨값이 조절된다.

<리스트 2> 볼륨 슬라이더 조작 함수

- (IBAction)volumeSliderMoved:(UISlider *)sender
{
   player.volume = [sender value];
}


오디오가 재생되는 도중에 슬라이드 바를 움직일 경우 해당되는 지점으로 이동하는 동작이 필요하다. 이 때 사용되는 것이 progressSliderMoved 함수다.

<리스트 3> 프로그래스 바 조작 함수

- (IBAction)progressSliderMoved:(UISlider *)sender
{
   player.currentTime = sender.value;
   [self updateCurrentTimeForPlayer:player];
}


뒤로 감기 버튼이나 전진 버튼을 눌렀을 경우(Pressed)와 놓았을 경우(Released)에는 <리스트 4>와 같은 함수들이 사용된다. 실제로 동작할 때는 NSTimer를 사용해 스킵 간격을 조절하게 된다.

<리스트 4> 앞/뒤 감기 버튼 함수

- (IBAction)rewButtonPressed:(UIButton *)sender
{
   if (rewTimer) [rewTimer invalidate];
   rewTimer = [NSTimer scheduledTimerWithTimeInterval:SKIP_INTERVAL target:self selector:@selector(rewind) userInfo:player repeats:YES];
}

(IBAction)rewButtonReleased:(UIButton *)sender
{
   if (rewTimer) [rewTimer invalidate];
   rewTimer = nil;
}


오디오가 재생되는 중에 화면보호 기능 등이 동작하거나 사용자가 임의로 버튼을 눌렀더라도 지속적으로 오디오가 나와야 할 경우가 있을 것이다. 이를 위해 애플리케이션이 초기화되는 부분에서 AVAudioSessionCategoryPlayback을 사용, <리스트 5>와 같은 코드를 작성해 준다. 

<리스트 5> 오디오 세션의 지속적 플레이 함수

NSError *setCategoryErr = nil;
NSError *activationErr = nil;

[[AVAudioSession sharedInstance]
setCategory : AVAudioSessionCategoryPlayback
error: &setCategoryErr];
[[AVAudioSession sharedInstance]
setActive: YES
error : &activationErr];


다음으로 전화가 오거나 알람 설정 등으로 인해 발생되는 인터럽트 처리 방법을 알아보자.
오디오 재생 중에 발생되는 여러 가지 인터럽트들은 <표 3>과 같은 기술들로 처리된다.

<표 3> 오디오 기술과 인터럽트 처리 방식

AAC 타입을 위한 하드웨어 인코딩 방법
앞에서 오디오를 재생하고 녹음을 하는 동안 하드웨어의 인터럽트를 사용한 인코딩/디코딩 방식이 있다고 설명했다. 아이폰의 여러 가지 오프라인 모드에서도(알람이나 전화가 왔을 경우 벨소리) 별도로 오디오를 동작시키는 방법이 필요하다. 이러한 경우 주로 사용되는 오디오 포맷이 AAC인데 코덱을 이용할 수 있는 장치로는 아이폰 3GS 이상의 모델, 아이팟 2세대 이상, 아이패드 등이 있다. AudioConverterRef라는 메소드를 활용하면 오디오 변환을 위한 기능들을 사용할 수 있다. 오디오 변환과 관련된 서비스들에 대해서는 ‘Audio Converter Services Reference and Extended Audio File Services Reference’라는 문서를 참조하면 된다. 

오디오 재생이나 녹음이 진행될 때 인터럽트가 발생됐을 경우의 라이프 사이클은 <그림 1>과 같이 설명할 수 있다. 진행되는 순서에 따라 살펴보자.

<그림 1> 오디오 재생시 앱의 라이프사이클(출처 AudioSessionProgrammngGuide.pdf)

1. 애플리케이션의 오디오를 동작시킨다.
2. 전화가 와서 인터럽트가 걸린다. 폰 애플리케이션의 오디오 세션이 활성화된다.
3. 이 때 시스템이 사용자의 오디오 세션을 비활성화 시킨다.
4. 시스템이 사용자의 인터럽트 리스너 콜백 함수를 invoke시키거나 인터럽트가 시작됐다는 델리게이트 메소드를 호출한다. 사용중이던 애플리케이션은 잠시 비활성화 된다.
5. 사용자의 콜백 또는 델리게이트 메소드는 액션에 해당되는 동작을 하게 된다.
6. 만약 사용자가 인터럽트를 무시하는 동작을 하면(전화를 받지 않거나 할 경우) 시스템은 인터럽트가 끝났다고 간주하고 다음 동작을 할 것이다.
7. 사용자의 콜백 또는 델리게이트 메소드는 인터럽트 종료시 동작된다. 예를 들면 사용자 인터페이스를 업데이트하거나 오디오 재생 등을 다시 시작할 경우 쓸 수 있다.

오디오 세션을 위한 팁들
이제 오디오 세션을 동작시키기 위한 코드들을 살펴보면서 실제 예를 통해 어떤 방식으로 활용할 수 있을지 알아보자.

● 오디오 세션의 초기화
오디오 인터럽트를 위한 AV 델리게이트 등을 사용하려고 한다면 오디오 세션을 초기화 한 상태에서 가능할 것이다. 오디오 인터럽트와 연관된 여러 가지 함수들을 잘 사용하기 위해 AudioSessionInitialize라는 함수를 호출해야 한다. 이것은 애플리케이션이 시작될 때 한 번만 불리도록 만들면 된다. 애플리케이션에서 오디오 세션의 초기화 등을 하지 않았을 경우에는 iOS에서 기본으로 제공하는 싱글톤 오디오 세션 오브젝트가 로딩이 끝난 후에 사용할 수 있도록 제공된다. 함수는 <리스트 6>과 같이 제공되며 Audioservice.h에 정의돼 있다.

<리스트 6> 오디오 세션 초기화 함수
AudioSessionInitialize(CFRunLoopRef inRunLoop,
                     CFStringRef inRunLoopMode,
                     AudioSessionInterruptionListener inInterruptionListener,
                     void *inClientData
   );


첫 번째 인자는 main 함수의 loop를 위해 사용된다. 두 번째 인자는 main이 아닌 run loop 모드에서 사용된다. 세 번째 인자는 리스너 콜백 함수에 해당되며 <리스트 7>과 같이 정의돼 있다.

<리스트 7> 오디오세션 인터럽트 리스너 콜백 함수

typedef void (*AudioSessionInterruptionListener)(
                               void *  inClientData,
                               UInt32  inInterruptionState
   );


각종 인터럽트는 다음과 같은 장치들을 연결하거나 동작시키는 상황에서 발생된다.

“Headset” “Headphone” “Speaker” “SpeakerAndMicrophone” “HeadphonesAndMicrophone” “HeadsetInOut” “ReceiverAnd Microphone” “Lineout”

네 번째는 사용자 데이터로 정의돼 있는데 오디오 세션 오브젝트가 invoke됐을 때 사용자의 인터럽트 리스너 콜백 함수로 연결시키도록 만들어져 있다(간단히 말하면 사용자가 의도한 함수를 실행하게 만든다).

● 사용자 오디오 세션의 활성화/비활성화
AVFoundation framework를 활용해 오디오 세션을 활성화 할 경우의 코드를 보자.

NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive: YES error: &activationError];

이 경우 비활성화 할 때는 setActive 속성을 “NO”로 변경해 주면 된다. 다음과 같은 스타일로 오디오 세션을 활성화/비활성화 할 수도 있다.

OSStatus activationResult = NULL;
result = AudioSessionSetActive (true);

● 애플리케이션이 시작될 때 다른 오디오가 재생되고 있는지 확인
사용자가 애플리케이션을 시작할 때 이미 오디오 장치를 통해 소리가 나고 있다면 어떻게 할지에 대해 생각해 보자. 이런 경우는 주로 게임을 시작할 때 등에 해당될텐데 게임을 시작하기 전에 오디오 세션이 잘 초기화돼 있는지 등을 살펴보고 다음 동작으로 이어진다.

<리스트 8> 오디오 세션 체크 함수

UInt32 otherAudioIsPlaying;
UInt32 propertySize = sizeof (otherAudioIsPlaying); AudioSessionGetProperty(kAudioSessionProperty_OtherAudioIsPlaying, &propertySize, &otherAudioIsPlaying);

if (otherAudioIsPlaying) { [[AVAudioSession sharedInstance]
   setCategory: AVAudioSessionCategoryAmbient error: nil];
}
else { [[AVAudioSession sharedInstance]
   etCategory: AVAudioSessionCategorySoloAmbient error: nil];
}


오디오가 플레이되고 있는지의 여부를 판단하는 프로퍼티 ID에는 AudioServices.h에 다음과 같이 enum 값이 정의돼 있다. 이 값이 otherAudioIsPlaying 변수에 할당된다.

kAudioSessionProperty_OtherAudioIsPlaying = ‘othr’,
// UInt32(get only)

또한 AVAudioSession.h에는 <리스트 9>와 같이 정의돼 있다.

<리스트 9> 오디오 세션 플레이 체크 상수

extern NSString *const AVAudioSessionCategoryAmbient;     // 다른 오디오가 재생되고 있을  경우
extern NSString *const AVAudioSessionCategorySoloAmbient;   // 재생되고 있지 않을 경우


● 재생 중 믹싱 동작
두 가지 오디오 소스로부터 입력을 받아 믹싱한 후에 재생할 필요가 있을 경우에는 특별히 <리스트 10>과 같이 동작을 설정할 수 있다. 이 예는 Voicemail.caf 파일과 음악 파일을 동시에 재생할 경우 어떻게 처리하는지에 대해 설명한다.

<리스트 10> 오디오 믹싱과 재생 함수

AudioSessionInitialize( NULL, NULL, NULL, NULL );  
// 오디오 세션 초기화
UInt32 sessionCategory = kAudioSessionCategory_AmbientSound; AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
AudioSessionSetProprty(true);   //오디오 세션의 프로퍼티를 동작으로 설정한다. 이 경우 음악 등을 재생하고 있으면 계속 소리가 나오는 상태가 된다.

NSURL* musicFile = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:@"Voicemail"
ofType:@"caf"]];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicFile error:nil];
[audioPlayer play];   // 믹서의 동작으로 Voicemail.caf 파일을 재생하게 된다.


현재 오디오의 동작 상태를 결정하는 AudioSessionSetActive 함수는 AudioServices.h에 다음과 같이 정의돼 있다.

extern OSStatus AudioSessionSetActive(Boolean active);  

이제 코드를 통해 애플리케이션에서 사용되는 사운드 재생법을 살펴보자(연재를 작성하는 중에 Xcode 4 버전이 발표돼 화면들은 새로운 버전을 기준으로 작성됐다).

1. View-based Application 프로젝트를 생성한다. 프로젝트의 이름은 AudioSample01로 만들었다(Xcode 4는 프로젝트의 이름을 정하면서 자체적으로 메소드 등에 대해 Unit Test를 할 수 있는 옵션을 제공한다).

<화면 2> View based template 선택

<화면 3> 프로젝트 이름 설정

<화면 4>와 같이 프로젝트가 생성됐다.

<화면 4> 프로젝트 정보 화면

2.  이번 예제에서는 화면 구성을 위해 Interface Builder를 사용했다. <화면 5>와 같이 재생중인 오디오 파일의 이름이 나오게 될 라벨과 오디오 재생 이벤트를 설정할 <확인> 버튼을 위치시켰다(Xcode 4에서는 인터페이스 빌더도 하나의 윈도우에 나타나도록 디자인됐다).

<화면 5> 인터페이스 빌더 화면

3. 오디오를 재생하게 될 <확인> 버튼과 오디오 파일의 정보를 표시할 라벨에 대해‘AudioSample01ViewController.h’에 <리스트 11>과 같이 코드를 작성한다.
    그리고 AudioToolbox.frame work을 추가한다.

<리스트 11> 버튼과 라벨 설정

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}


4. PlaySound라는 함수에 오디오 파일명을 <리스트 12>와 같이 입력한다. SystemSoundID라는 타입을 정의해 AudioServices CreateSystemSoundID, AudioServicesPlaySystemSound라는 형식으로 플레이하게 된다. 화면에서 <확인> 버튼을 누르면 type.wav 파일이 재생되면서 파일명이 라벨에 표시된다.
<리스트 12> 오디오 재생 함수

-(IBAction)PlaySound:(id)sender
{
   NSString *path = [[NSBundle mainBundle] pathForResource:@"type" ofType:@"wav"];
   SystemSoundID soundID;
   label.text = path;
      
   NSLog(@"path is %@", path); //null print on iphone
      
   AudioServicesCreateSystemSoundID((CFURLRef) [NSURL fileURLWithPath:path], &soundID);
   AudioServicesPlaySystemSound(soundID);
}

Xcode 4에 프레임워크 추가

기존에는 프로젝트 내비게이션 트리에서 오른 쪽 클릭으로 프레임워크를 추가할 수 있었다. 새로운 버전에서는 <화면 6>과 같이 프로젝트 메뉴를 선택하고 TARGETS 항목의 Build Project 영역을 선택해 Link Binary With Libraries라는 곳에서 ‘+’를 선택함으로써 프레임워크를 추가하면 된다. 프로젝트에서 사용되는 여러 가지 프로파일들을 한 곳에 모아두기 위한 방법이라고 생각된다.

<화면 6> 프레임워크 추가 화면


아이폰 시뮬레이터

아이폰이나 아이패드 개발 뿐만 아니라 임베디드 디바이스의 애플리케이션을 개발할 때는 테스트를 위해 소스 코드를 빌드한 후에 이미지를 실제 장비에 설치하게 된다. 하지만 간단한 UI나 디자인 등을 테스트하기 위해 실제 장비에 매번 이미지를 설치하는 작업은 시간이 필요 이상으로 많이 걸리는 일이다. 이럴 경우 임베디드 환경에서는 보통 시뮬레이터라고 하는 소프트웨어적인 가상의 장치를 사용하게 된다. 

아이폰에서 사용되는 시뮬레이터는 <화면 7>과 같은 형태인데 재미있는 기능이 있다. 아이폰(아이패드)에는 모바일 키노트 애플리케이션이나 동영상 애플리케이션의 화면을 TV 화면으로 보낼 수 있는 기능이 있다. ‘iOS Simulator’에도 이같은 기능이 있다. ‘Hardware’ 메뉴에 ‘TV Out’ 항목이 그것으로, 해상도별로 세 가지 모드를 시뮬레이션해 준다.

<화면 7> iOS 시뮬레이터

유튜브 화면을 플레이해 봤다. 시뮬레이터는 <화면 8>과 같은 화면으로 변경되고 <화면 9>와 같은 TV Out 화면이 나타난다.

<화면 8> 동영상 플레이 화면

<화면 9> TV Out 화면


참고자료

1. MultimediaProgrammingGuide.pdf
https://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/MultimediaPG/Introduction/Introduction.html%23//apple_ref/doc/uid/TP40009767
2. https://developer.apple.com/library/ios/#referencelibrary/GettingStarted/ GS_AudioVideo_iPhone/




출처 : http://blog.daum.net/_blog/hdn/ArticleContentsView.do?blogid=05JzW&articleno=16056926&looping=0&longOpen=
Posted by 오늘마감

[출처: http://maclove.pe.kr/32]

메모리 관리

많은 개발자들이 Objective-C 의 메모리 관리를 어렵게 느낀다. Objective-C 에서 객체는 참조 카운터를 이용해서 관리되기 때문에, 참조 카운터를 증가 시키고 감소하는 작업이 프로그래머의 몫이 된다. 여기서 혼돈이 오는 것이다. 참조 카운터를 증가시키는 함수는 retain 이다. 반대로 참조 카운터를 감소시키는 함수는 release와 autorelease 이다. 하지만 문제는 이미 만들어진 객체의 메서드가 내부에서 retain 을 몇번 부르는지를 별도로 알아낼 방법이 없다는 것이다. 다음을 보자.

UIImageView* imgView = [[UIImageView alloc] init];

이 코드에서 UIImageView 는 retain 내부에서 한번 호출해서 객체를 반환해 준다. 그렇기 때문에 우리는 더이상 필요하지 않을때,

[imgView release];

를 호출해야 한다. 하지만 다음을 보자.

NSString* output = [NSString stringWithFormat:@”My name : %@”, name];

이 코드는 NSString의 stringWithFormat 클래스 메서드를 이용해서 객체를 생성하는 코드이다. 이 녀석은 retain 이 아닌 autorelease 를 호출해서 객체를 반환한다. 이렇게 어떤 메서드는 객체를 retain 해서 반환하고, 또 어떤 객체는 autorelease 로 반환하기 때문에 혼돈이 온다.

참조 카운트를 관리하는 함수는 다음과 같다.

• retain
     - 참조 카운트를 1 증가 시킨다.
• release
     - 참조 카운트를 1 감소시킨다. 참조 카운트가 0이 되면 메모리가 해제된다.
• autorelease
     -  객체를 오토릴리즈 풀에 등록한다. 나중에 오토릴리즈 풀이 제거될때 release 를 호출해 준다.

객체의 참조를 관리하는 것은 위 3개의 메서드가 전부이지만, 문제는 클래스 내부 구현에서 위 함수들을 호출하는 지를 모른다는 점이다. 하지만 법칙이 있다. 애플이 작성한 모든 클래스는 정해진 규칙을 철저하게 따르기 때문에 이 법칙들만 알아두면 더 이상 햇갈릴 일이 없다.

* 규칙1 : alloc, copy, new를 이름에 포함하는 메서드는 retain 된 객체를 반환한다.

alloc, copy, new 가 메서드 이름에 포함되어 있다면, 그 때 반환되는 객체는 retain 되어 있다. 그래서 반드시 release 를 직접 호출해야 한다.

01: queue = [[NSOperationQueue alloc] init];
02: // 작업
03: [queue release];
04:
05: copyedObj = [name copy];
06: // 작업
07: [copyedObj release];

* 규칙2 : 결자해지

만약 자신이 retain 을 호출했다면, 책임지고 release 또는 autorelease 를 호출해 주자.

01: [objA retain];
02: // 작업
03: [objA release];

반드시 자신이 호출한 retain 에 대해서 release/autorelease 짝을 맞추도록 하자.

* 규칙3: 클래스 메서드가 객체를 생성해 줄때는 autorelease 객체를 반환한다.

클래스 메서드로 객체를 생성하는 경우 즉 stringWithFormat 과 같은 클래스 메서드가 반환하는 객체는 모두 autorelease 객체이다.

01: img = [UIImage imageNamed:@"test.png"];
02: imgView = [[UIImageView alloc] initWithImage:];
03: // 작업
04: [imgView release];

코드 1행의 imageNamed 메서드 처럼 클래스 메서드를 이용해서 객체를 생성하는 경우 그 객체는 autorelease 가 호출된 객체이다. 그렇기 때문에 별도로 release 를 호출하지 않아도 오토릴리즈 풀이 자동으로 release 를 호출해 준다. 하지만 이 객체에 retain 을 호출 했다면 호출한 만큼의 release 를 호출 해야한다.

* 규칙4: 포함 객체는 추가된 객체를 retain 하고, 항목을 제거할 때 release 한다.

NSArray,NSDictionay 등의 포함 객체는 항목으로 추가되는 객체에 대해서 retain 을 한번 호출한다. 그리고 객체가 포함객체에서 제거될때 release 를 호출해 준다.

13.9.5 규칙5: retain 속성을 갖는 접근자

프로퍼티를 구성할때 @property (retain) ... 과 같이 retain 속성을 지정하면 이 프로퍼티에 객체를 설정하면 retain 메서드를 호출한다.

01: myImage = [[UIImage alloc] init]; // myImage 에 retain –> 1
02: self.userImage = myImage; // myImage 에 retain –> 2
03: [myImage release]; // myImage 에 release –> 1
04: // ...
05: self.userImage = myImage2; // 예전 myImage 에 release -> 0 해제

이와 같이 객체를 설정하는 접근자는 일반적으로 그 객체에 대해서 retain 을 호출한다. 그리고 만약 다른 객체를 재설정하면, 예전 객체에 release 를 호출한다. 위 예제의 3행에서 release 를 호출한 이유를 이해할 것이다.

*규칙5: 메서드가 반환하는 객체는 autorelease

메서드가 객체를 반환한다면 autorelease 된 객체를 반환하는 것이 좋다.

01: -(NSString*) findTopPlayer {
02: NSString *ret = [[top objectAtIndex:0] copy];
03: [ret autorelease];
04: return ret;
05: }

[출처: http://maclove.pe.kr/32]



출처 : http://blog.naver.com/PostView.nhn?blogId=baek2187&logNo=150059860682
Posted by 오늘마감