플랫폼 간 앱 사례 연구: TaskyCross-Platform App Case Study: Tasky

Tasky 이식 가능 은 간단한 할 일 목록 응용 프로그램입니다.Tasky Portable is a simple to-do list application. 이 문서에서는 플랫폼 간 응용 프로그램 빌드 문서의 지침에 따라 설계 및 구축 된 방법을 설명 합니다.This document discusses how it was designed and built, following the guidance of the Building Cross-Platform Applications document. 토론은 다음 영역을 다룹니다.The discussion covers the following areas:

디자인 프로세스Design Process

코딩을 시작 하기 전에 달성할 항목에 대 한도로 지도를 만드는 것이 좋습니다.It is advisable to create a of road-map for what you want to achieve before you start coding. 여러 가지 방법으로 노출 되는 기능을 구축 하는 플랫폼 간 개발의 경우 특히 그렇습니다.This is especially true for cross-platform development, where you are building functionality that will be exposed in multiple ways. 빌드를 명확 하 게 파악 하 여 개발 주기에서 나중에 시간과 노력을 절감할 수 있습니다.Starting with a clear idea of what you're building saves time and effort later in the development cycle.

요구 사항Requirements

응용 프로그램을 디자인 하는 첫 번째 단계는 원하는 기능을 식별 하는 것입니다.The first step in designing an application is to identify desired features. 이는 높은 수준의 목표 또는 자세한 사용 사례 일 수 있습니다.These can be high-level goals or detailed use cases. Tasky에는 다음과 같은 간단한 기능 요구 사항이 있습니다.Tasky has straightforward functional requirements:

  • 작업 목록 보기View a list of tasks
  • 작업 추가, 편집 및 삭제Add, edit and delete tasks
  • 작업 상태를 ' 완료 '로 설정 합니다.Set a task’s status to ‘done’

플랫폼별 기능의 사용을 고려해 야 합니다.You should consider your use of platform-specific features. Tasky는 iOS 지 오 펜싱 또는 Windows Phone 라이브 타일을 활용할 수 있나요?Can Tasky take advantage of iOS geofencing or Windows Phone Live Tiles? 플랫폼 특정 기능을 첫 번째 버전에서 사용 하지 않는 경우에도 비즈니스 & 데이터 계층이 이러한 기능을 수용할 수 있도록 미리 계획 해야 합니다.Even if you don't use platform-specific features in the first version, you should plan ahead to make sure your business & data layers can accommodate them.

사용자 인터페이스 설계User Interface Design

대상 플랫폼에서 구현할 수 있는 높은 수준의 디자인으로 시작 합니다.Start with a high-level design that can be implemented across the target platforms. 플랫폼 특정 UI 제약 조건을 주의 해야 합니다.Take care to note platform-specfic UI constraints. 예를 들어 iOS의 TabBarController은 5 개 이상의 단추를 표시할 수 있지만 Windows Phone 해당 하는 항목은 최대 4 개까지 표시할 수 있습니다.For example, a TabBarController in iOS can display more than five buttons, whereas the Windows Phone equivalent can display up to four. 선택한 도구를 사용 하 여 화면 흐름을 그립니다 (paper works).Draw the screen-flow using the tool of your choice (paper works).

데이터 모델Data Model

저장 해야 하는 데이터를 알면 사용할 지 속성 메커니즘을 결정 하는 데 도움이 됩니다.Knowing what data needs to be stored will help determine which persistence mechanism to use. 사용 가능한 저장소 메커니즘에 대 한 자세한 내용은 플랫폼 간 데이터 액세스 를 참조 하 고이를 결정 하는 데 도움을 줍니다.See Cross-Platform Data Access for information about the available storage mechanisms and help deciding between them. 이 프로젝트의 경우 SQLite.NET를 사용 합니다.For this project, we'll be using SQLite.NET.

Tasky는 각 ' TaskItem '에 대 한 세 가지 속성을 저장 해야 합니다.Tasky needs to store three properties for each 'TaskItem':

  • 이름 – 문자열Name – String
  • 참고 – 문자열Notes – String
  • Done – 부울Done – Boolean

핵심 기능Core Functionality

사용자 인터페이스에서 요구 사항을 충족 하기 위해 사용 해야 하는 API를 고려 합니다.Consider the API that the user interface will need to consume to meet the requirements. 할 일 목록에는 다음 함수가 필요 합니다.A to-do list requires the following functions:

  • 모든 작업 나열 – 사용 가능한 모든 작업의 기본 화면 목록을 표시 하려면List all tasks – to display the main screen list of all available tasks
  • 작업 행이 작업 될 때 하나의 작업을 가져옵니다 .Get one task – when a task row is touched
  • 작업 1 개 저장 – 작업을 편집 하는 경우Save one task – when a task is edited
  • 작업 삭제 – 태스크가 삭제 된 경우Delete one task – when a task is deleted
  • 빈 작업 만들기 – 새 작업을 만든 경우Create empty task – when a new task is created

코드 재사용을 위해이 API는 이식 가능한 클래스 라이브러리에서 한 번 구현 되어야 합니다.To achieve code reuse, this API should be implemented once in the Portable Class Library.

구현Implementation

응용 프로그램 디자인을 동의한 후에는 플랫폼 간 응용 프로그램으로 구현 하는 방법을 고려해 야 합니다.Once the application design has been agreed upon, consider how it might be implemented as a cross-platform application. 이는 응용 프로그램의 아키텍처가 됩니다.This will become the application’s architecture. 플랫폼 간 응용 프로그램 빌드 문서의 지침에 따라 응용 프로그램 코드는 다음 부분으로 분류 됩니다.Following the guidance in the Building Cross-Platform Applications document, the application code should be broken down into the following parts:

  • 일반 코드 – 작업 데이터를 저장 하는 데 재사용 가능한 코드를 포함 하는 공용 프로젝트입니다. 모델 클래스 및 API를 노출 하 여 데이터의 저장 및 로드를 관리 합니다.Common Code – a common project that contains re-useable code to store the task data; expose a Model class and an API to manage the saving and loading of data.
  • 플랫폼별 코드 – 일반적인 코드를 ' 백 엔드 '로 활용 하 여 각 운영 체제에 대 한 네이티브 UI를 구현 하는 플랫폼별 프로젝트입니다.Platform-specific Code – platform-specific projects that implement a native UI for each operating system, utilizing the common code as the ‘back end’.

이러한 두 부분에 대해서는 다음 섹션에서 설명 합니다.These two parts are described in the following sections.

일반 (PCL) 코드Common (PCL) Code

Tasky 이식 가능한 클래스 라이브러리 전략을 사용 하 여 공통 코드를 공유 합니다.Tasky Portable uses the Portable Class Library strategy for sharing common code. 코드 공유 옵션에 대 한 설명은 코드 공유 옵션 문서를 참조 하세요.See the Sharing Code Options document for a description of code-sharing options.

데이터 액세스 계층, 데이터베이스 코드 및 계약을 비롯 한 모든 공통 코드는 라이브러리 프로젝트에 배치 됩니다.All common code, including the data access layer, database code and contracts, is placed in the library project.

전체 PCL 프로젝트가 아래에 나와 있습니다.The complete PCL project is illustrated below. 이식 가능한 라이브러리의 모든 코드는 각 대상 플랫폼과 호환 됩니다.All of the code in the portable library is compatible with each targeted platform. 배포 되 면 각 네이티브 앱이 해당 라이브러리를 참조 합니다.When deployed, each native app will reference that library.

아래 클래스 다이어그램에서는 계층 별로 그룹화 된 클래스를 보여 줍니다.The class diagram below shows the classes grouped by layer. SQLiteConnection 클래스는 Sqlite-NET 패키지의 상용구 코드입니다.The SQLiteConnection class is boilerplate code from the Sqlite-NET package. 나머지 클래스는 Tasky의 사용자 지정 코드입니다.The rest of the classes are custom code for Tasky. TaskItemManagerTaskItem 클래스는 플랫폼별 응용 프로그램에 노출 되는 API를 나타냅니다.The TaskItemManager and TaskItem classes represent the API that is exposed to the platform-specific applications.

네임 스페이스를 사용 하 여 레이어를 분리 하면 각 계층 간의 참조를 관리할 수 있습니다.Using namespaces to separate the layers helps to manage references between each layer. 플랫폼별 프로젝트는 비즈니스 계층에 대 한 using 문만 포함 해야 합니다.The platform-specific projects should only need to include a using statement for the Business Layer. 비즈니스 계층에서 TaskItemManager에 의해 노출 되는 API를 통해 데이터 액세스 계층과 데이터 계층을 캡슐화 해야 합니다.The Data Access Layer and Data Layer should be encapsulated by the API that is exposed by TaskItemManager in the Business Layer.

참조 항목References

이식 가능한 클래스 라이브러리는 플랫폼 및 프레임 워크 기능에 대해 다양 한 수준의 지원을 제공 하는 여러 플랫폼에서 사용할 수 있어야 합니다.Portable class libraries need to be usable across multiple platforms, each with varying levels of support for platform and framework features. 따라서 사용할 수 있는 패키지 및 프레임 워크 라이브러리에 대 한 제한 사항이 있습니다.Because of that, there are limitations on which packages and framework libraries can be used. 예를 들어 Xamarin.ios는 c # dynamic 키워드를 지원 하지 않으므로 이식 가능한 클래스 라이브러리는 Android에서 작동 하는 경우에도 동적 코드에 종속 된 패키지를 사용할 수 없습니다.For example, Xamarin.iOS does not support the c# dynamic keyword, so a portable class library can't use any package that depends on dynamic code, even though such code would work on Android. Mac용 Visual Studio를 사용 하면 호환 되지 않는 패키지 및 참조를 추가할 수 없지만 나중에 발생 하는 것을 방지 하기 위해 제한을 염두에 두어야 합니다.Visual Studio for Mac will prevent you from adding incompatible packages and references, but you'll want to keep limitations in mind to avoid surprises later on.

참고: 프로젝트에서 사용 하지 않은 프레임 워크 라이브러리를 참조 하는 것을 볼 수 있습니다.Note: You'll see that your projects reference framework libraries that you haven't used. 이러한 참조는 Xamarin 프로젝트 템플릿의 일부로 포함 됩니다.These references are included as part of the Xamarin project templates. 앱이 컴파일되면 링크 프로세스에서 참조 되지 않은 코드를 제거 하므로 System.Xml 참조 된 경우에도 Xml 함수를 사용 하지 않으므로 최종 응용 프로그램에 포함 되지 않습니다.When apps are compiled, the linking process will remove unreferenced code, so even though System.Xml has been referenced, it will not be included in the final application because we are not using any Xml functions.

데이터 계층 (DL)Data Layer (DL)

데이터 계층에는 데이터베이스, 플랫 파일 또는 기타 메커니즘과 관련 된 데이터의 실제 저장소를 수행 하는 코드가 포함 되어 있습니다.The Data Layer contains the code that does the physical storage of data – whether to a database, flat files or other mechanism. Tasky 데이터 계층은 SQLite 네트워크 라이브러리와 연결에 추가 된 사용자 지정 코드의 두 부분으로 구성 됩니다.The Tasky data layer consists of two parts: the SQLite-NET library and the custom code added to wire it up.

Tasky는 Frank Kreuger에서 게시 한 Sqlite-net nuget 패키지를 사용 하 여 ORM (개체-관계형 매핑) 데이터베이스 인터페이스를 제공 하는 SQLite-NET 코드를 포함 합니다.Tasky relies on the Sqlite-net nuget package (published by Frank Kreuger) to embed SQLite-NET code that provides an Object-Relational Mapping (ORM) database interface. TaskItemDatabase 클래스는 SQLiteConnection에서 상속 되며 SQLite에 데이터를 읽고 쓰는 데 필요한 만들기, 읽기, 업데이트, 삭제 (CRUD) 메서드를 추가 합니다.The TaskItemDatabase class inherits from SQLiteConnection and adds the required Create, Read, Update, Delete (CRUD) methods to read and write data to SQLite. 다른 프로젝트에서 다시 사용할 수 있는 일반적인 CRUD 메서드의 간단한 상용구 구현입니다.It is a simple boilerplate implementation of generic CRUD methods that could be re-used in other projects.

TaskItemDatabase는 단일 항목 이므로 동일한 인스턴스에 대 한 모든 액세스가 발생 합니다.The TaskItemDatabase is a singleton, ensuring that all access occurs against the same instance. 잠금은 여러 스레드의 동시 액세스를 방지 하는 데 사용 됩니다.A lock is used to prevent concurrent access from multiple threads.

Windows Phone의 SQLiteSQLite on Windows Phone

IOS와 Android는 모두 SQLite를 운영 체제의 일부로 제공 하지만 Windows Phone에는 호환 되는 데이터베이스 엔진이 포함 되지 않습니다.While iOS and Android both ship with SQLite as part of the operating system, Windows Phone does not include a compatible database engine. 세 플랫폼 모두에서 코드를 공유 하려면 Windows phone 네이티브 버전 SQLite가 필요 합니다.To share code across all three platforms a Windows phone-native version of SQLite is required. Sqlite의 Windows Phone 프로젝트를 설정 하는 방법에 대 한 자세한 내용은 로컬 데이터베이스 작업 을 참조 하세요.See Working with a Local Database for more information about setting up your Windows Phone project for Sqlite.

인터페이스를 사용 하 여 데이터 액세스 일반화Using an Interface to Generalize Data Access

데이터 계층은 기본 키가 필요한 추상 데이터 액세스 메서드를 구현할 수 있도록 BL.Contracts.IBusinessIdentity에 대 한 종속성을 사용 합니다.The Data Layer takes a dependency on BL.Contracts.IBusinessIdentity so that it can implement abstract data access methods that require a primary key. 그런 다음 인터페이스를 구현 하는 모든 비즈니스 계층 클래스를 데이터 계층에 유지할 수 있습니다.Any Business Layer class that implements the interface can then be persisted in the Data Layer.

인터페이스는 기본 키 역할을 할 정수 속성만 지정 합니다.The interface just specifies an integer property to act as the primary key:

public interface IBusinessEntity {
    int ID { get; set; }
}

기본 클래스는 인터페이스를 구현 하 고 SQLite-NET 특성을 추가 하 여 자동 증가 기본 키로 표시 합니다.The base class implements the interface and adds the SQLite-NET attributes to mark it as an auto-incrementing primary key. 이 기본 클래스를 구현 하는 비즈니스 계층의 모든 클래스는 데이터 계층에 유지 될 수 있습니다.Any class in the Business Layer that implements this base class can then be persisted in the Data Layer:

public abstract class BusinessEntityBase : IBusinessEntity {
    public BusinessEntityBase () {}
    [PrimaryKey, AutoIncrement]
    public int ID { get; set; }
}

인터페이스를 사용 하는 데이터 계층의 제네릭 메서드 예는이 GetItem<T> 메서드입니다.An example of the generic methods in the Data Layer that use the interface is this GetItem<T> method:

public T GetItem<T> (int id) where T : BL.Contracts.IBusinessEntity, new ()
{
    lock (locker) {
        return Table<T>().FirstOrDefault(x => x.ID == id);
    }
}

동시 액세스를 방지 하기 위한 잠금Locking to prevent Concurrent Access

데이터베이스에 대한 동시 액세스를 방지하기 위해 TaskItemDatabase 클래스 내에서 잠금이 구현됩니다.A lock is implemented within the TaskItemDatabase class to prevent concurrent access to the database. 이는 다른 스레드의 동시 액세스가 serialize 되도록 하기 위한 것입니다. 그렇지 않으면 UI 구성 요소에서 백그라운드 스레드가 업데이트 하는 동시에 데이터베이스를 읽으려고 시도할 수 있습니다.This is to ensure concurrent access from different threads is serialized (otherwise a UI component might attempt to read the database at the same time a background thread is updating it). 잠금이 구현 되는 방법의 예는 다음과 같습니다.An example of how the lock is implemented is shown here:

static object locker = new object ();
public IEnumerable<T> GetItems<T> () where T : BL.Contracts.IBusinessEntity, new ()
{
    lock (locker) {
        return (from i in Table<T> () select i).ToList ();
    }
}
public T GetItem<T> (int id) where T : BL.Contracts.IBusinessEntity, new ()
{
    lock (locker) {
        return Table<T>().FirstOrDefault(x => x.ID == id);
    }
}

대부분의 데이터 계층 코드는 다른 프로젝트에서 다시 사용할 수 있습니다.Most of the Data Layer code could be re-used in other projects. 계층의 응용 프로그램별 코드는 TaskItemDatabase 생성자의 CreateTable<TaskItem> 호출 뿐입니다.The only application-specific code in the layer is the CreateTable<TaskItem> call in the TaskItemDatabase constructor.

DAL (데이터 액세스 계층)Data Access Layer (DAL)

TaskItemRepository 클래스는 TaskItem 개체를 만들고, 삭제 하 고, 검색 하 고, 업데이트할 수 있는 강력한 형식의 API를 사용 하 여 데이터 저장소 메커니즘을 캡슐화 합니다.The TaskItemRepository class encapsulates the data storage mechanism with a strongly-typed API that allows TaskItem objects to be created, deleted, retrieved and updated.

조건부 컴파일 사용Using Conditional Compilation

클래스는 조건부 컴파일을 사용 하 여 파일 위치를 설정 합니다 .이는 플랫폼 확산을 구현 하는 예제입니다.The class uses conditional compilation to set the file location - this is an example of implementing Platform Divergence. 경로를 반환 하는 속성은 각 플랫폼에서 다른 코드로 컴파일됩니다.The property that returns the path compiles to different code on each platform. 코드 및 플랫폼별 컴파일러 지시문이 다음과 같이 표시 됩니다.The code and platform-specific compiler directives are shown here:

public static string DatabaseFilePath {
    get {
        var sqliteFilename = "TaskDB.db3";
#if SILVERLIGHT
        // Windows Phone expects a local path, not absolute
        var path = sqliteFilename;
#else
#if __ANDROID__
        // Just use whatever directory SpecialFolder.Personal returns
        string libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); ;
#else
        // we need to put in /Library/ on iOS5.1+ to meet Apple's iCloud terms
        // (they don't want non-user-generated data in Documents)
        string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); // Documents folder
        string libraryPath = Path.Combine (documentsPath, "..", "Library"); // Library folder
#endif
        var path = Path.Combine (libraryPath, sqliteFilename);
                #endif
                return path;
    }
}

플랫폼에 따라 출력은 iOS의 경우 "/라이브러리/r o d e r/r e n t 3"이 고, Android의 경우 "/pbbdb3"이 고 Windows Phone의 경우 "TaskDB." 뿐입니다.Depending on the platform, the output will be “/Library/TaskDB.db3” for iOS, “/Documents/TaskDB.db3” for Android or just “TaskDB.db3” for Windows Phone.

비즈니스 계층 (BL)Business Layer (BL)

비즈니스 계층은 모델 클래스와이를 관리 하기 위한 외관을 구현 합니다.The Business Layer implements the Model classes and a Façade to manage them. Tasky에서 모델은 TaskItem 클래스 이며 TaskItemManager TaskItems을 관리 하기 위한 API를 제공 하는 외관 패턴을 구현 합니다.In Tasky the Model is the TaskItem class and TaskItemManager implements the Façade pattern to provide an API for managing TaskItems.

FaçadeFaçade

TaskItemManager는 응용 프로그램 및 UI 계층에서 참조 되는 Get, Save 및 Delete 메서드를 제공 하도록 DAL.TaskItemRepository를 래핑합니다.TaskItemManager wraps the DAL.TaskItemRepository to provide the Get, Save and Delete methods that will be referenced by the Application and UI Layers.

필요한 경우 비즈니스 규칙 및 논리가 여기에 배치 됩니다. 예를 들어 개체를 저장 하기 전에 충족 해야 하는 유효성 검사 규칙을 사용할 수 있습니다.Business rules and logic would be placed here if required – for example any validation rules that must be satisfied before an object is saved.

플랫폼별 코드에 대 한 APIAPI for Platform-Specific Code

공용 코드를 작성 한 후에는 사용자 인터페이스를 빌드하여이를 통해 노출 되는 데이터를 수집 하 고 표시 해야 합니다.Once the common code has been written, the user interface must be built to collect and display the data exposed by it. TaskItemManager 클래스는 응용 프로그램 코드에서 액세스할 수 있는 간단한 API를 제공 하는 외관 패턴을 구현 합니다.The TaskItemManager class implements the Façade pattern to provide a simple API for the application code to access.

각 플랫폼별 프로젝트에서 작성 된 코드는 일반적으로 해당 장치의 네이티브 SDK와 긴밀 하 게 결합 되며 TaskItemManager에서 정의한 API를 사용 하 여 공통 코드에만 액세스할 수 있습니다.The code written in each platform-specific project will generally be tightly coupled to the native SDK of that device, and only access the common code using the API defined by the TaskItemManager. 여기에는 TaskItem 같이 노출 하는 메서드 및 비즈니스 클래스가 포함 됩니다.This includes the methods and business classes it exposes, such as TaskItem.

이미지는 플랫폼 간에 공유 되지 않지만 각 프로젝트에 독립적으로 추가 됩니다.Images are not shared across platforms but added independently to each project. 이는 각 플랫폼에서 서로 다른 파일 이름, 디렉터리 및 해상도를 사용 하 여 이미지를 다르게 처리 하기 때문에 중요 합니다.This is important because each platform handles images differently, using different file names, directories and resolutions.

나머지 섹션에서는 Tasky UI의 플랫폼별 구현 세부 정보에 대해 설명 합니다.The remaining sections discuss the platform-specific implementation details of the Tasky UI.

iOS 앱iOS App

데이터를 저장 하 고 검색 하기 위해 일반적인 PCL 프로젝트를 사용 하 여 iOS Tasky 응용 프로그램을 구현 하는 데 필요한 클래스는 몇 가지 뿐입니다.There are only a handful of classes required to implement the iOS Tasky application using the common PCL project to store and retrieve data. 전체 iOS Xamarin.ios 프로젝트는 다음과 같습니다.The complete iOS Xamarin.iOS project is shown below:

클래스는 계층으로 그룹화 된이 다이어그램에 표시 됩니다.The classes are shown in this diagram, grouped into layers.

참조 항목References

IOS 앱은 플랫폼별 SDK 라이브러리를 참조 합니다 (예:).The iOS app references the platform-specific SDK libraries – eg. Xamarin.ios 및 Monotouch.dialog-1.Xamarin.iOS and MonoTouch.Dialog-1.

TaskyPortableLibrary PCL 프로젝트도 참조 해야 합니다.It must also reference the TaskyPortableLibrary PCL project. 참조 목록이 여기에 표시 됩니다.The references list is shown here:

응용 프로그램 계층 및 사용자 인터페이스 계층은 이러한 참조를 사용 하 여이 프로젝트에서 구현 됩니다.The Application Layer and User Interface Layer are implemented in this project using these references.

응용 프로그램 계층 (AL)Application Layer (AL)

응용 프로그램 계층에는 PCL에서 노출 한 개체를 UI에 ' 바인딩 ' 하는 데 필요한 플랫폼별 클래스가 포함 되어 있습니다.The Application Layer contains platform-specific classes required to ‘bind’ the objects exposed by the PCL to the UI. IOS 관련 응용 프로그램에는 작업을 표시 하는 데 도움이 되는 두 가지 클래스가 있습니다.The iOS-specific application has two classes to help display tasks:

  • EditingSource –이 클래스는 작업 목록을 사용자 인터페이스에 바인딩하는 데 사용 됩니다.EditingSource – This class is used to bind lists of tasks to the user interface. 작업 목록에 MonoTouch.Dialog를 사용 했기 때문에 UITableView에서 살짝 밀기-삭제 기능을 사용 하려면이 도우미를 구현 해야 합니다.Because MonoTouch.Dialog was used for the Task list, we need to implement this helper to enable swipe-to-delete functionality in the UITableView . 살짝 밀기-삭제는 iOS에서 일반적 이지만 Android 또는 Windows Phone에는 적용 되지 않으므로 iOS 관련 프로젝트는이를 구현 하는 유일한 프로젝트입니다.Swipe-to-delete is common on iOS, but not Android or Windows Phone, so the iOS specific project is the only one that implements it.
  • Taskdialog –이 클래스는 단일 작업을 UI에 바인딩하는 데 사용 됩니다.TaskDialog – This class is used to bind a single task to the UI. MonoTouch.Dialog 리플렉션 API를 사용 하 여 입력 화면의 형식이 올바르게 지정 될 수 있도록 올바른 특성이 포함 된 클래스를 사용 하 여 TaskItem 개체를 ' 래핑 ' 합니다.It uses the MonoTouch.Dialog Reflection API to ‘wrap’ the TaskItem object with a class that contains the correct attributes to allow the input screen to be correctly formatted.

TaskDialog 클래스는 MonoTouch.Dialog 특성을 사용 하 여 클래스의 속성을 기반으로 화면을 만듭니다.The TaskDialog class uses MonoTouch.Dialog attributes to create a screen based on a class’s properties. 클래스는 다음과 같습니다.The class looks like this:

public class TaskDialog {
    public TaskDialog (TaskItem task)
    {
        Name = task.Name;
        Notes = task.Notes;
        Done = task.Done;
    }
    [Entry("task name")]
    public string Name { get; set; }
    [Entry("other task info")]
    public string Notes { get; set; }
    [Entry("Done")]
    public bool Done { get; set; }
    [Section ("")]
    [OnTap ("SaveTask")]    // method in HomeScreen
    [Alignment (UITextAlignment.Center)]
    public string Save;
    [Section ("")]
    [OnTap ("DeleteTask")]  // method in HomeScreen
    [Alignment (UITextAlignment.Center)]
    public string Delete;
}

OnTap 특성에는 메서드 이름이 필요 합니다. 이러한 메서드는 MonoTouch.Dialog.BindingContext를 만든 클래스 (이 경우 다음 섹션에서 설명 하는 HomeScreen 클래스)에 있어야 합니다.Notice the OnTap attributes require a method name – these methods must exist in the class where the MonoTouch.Dialog.BindingContext is created (in this case, the HomeScreen class discussed in the next section).

UI (사용자 인터페이스 계층)User Interface Layer (UI)

사용자 인터페이스 계층은 다음 클래스로 구성 됩니다.The User Interface Layer consists of the following classes:

  1. AppDelegate – 응용 프로그램에 사용 되는 글꼴 및 색의 스타일을 표시 하는 모양 API에 대 한 호출을 포함 합니다.AppDelegate – Contains calls to the Appearance API to style the fonts and colors used in the application. Tasky는 간단한 응용 프로그램 이므로 FinishedLaunching에서 실행 되는 다른 초기화 작업이 없습니다.Tasky is a simple application so there are no other initialization tasks running in FinishedLaunching .
  2. Screen – 각 화면 및 해당 동작을 정의 하는 UIViewController의 서브 클래스입니다.Screens – subclasses of UIViewController that define each screen and its behavior. 응용 프로그램 계층 클래스 및 공용 API (TaskItemManager)를 사용 하 여 UI를 함께 연결 합니다.Screens tie together the UI with Application Layer classes and the common API ( TaskItemManager ). 이 예제에서는 코드에서 화면을 만들지만 Xcode의 Interface Builder 또는 스토리 보드 디자이너를 사용 하 여 디자인할 수 있습니다.In this example the screens are created in code, but they could have been designed using Xcode’s Interface Builder or the storyboard designer.
  3. 이미지 – 시각적 요소는 모든 응용 프로그램에서 중요 한 부분입니다.Images – Visual elements are an important part of every application. Tasky에는 iOS 용 시작 화면 및 아이콘 이미지가 있고,이 이미지는 regular 및 레 티 나 resolution에서 제공 되어야 합니다.Tasky has splash screen and icon images, which for iOS must be supplied in regular and Retina resolution.

홈 화면Home Screen

홈 화면은 SQLite 데이터베이스의 작업 목록을 표시 하는 MonoTouch.Dialog 화면입니다.The Home Screen is a MonoTouch.Dialog screen that displays a list of tasks from the SQLite database. DialogViewController에서 상속 하 고 Root를 표시 하기 위해 TaskItem 개체의 컬렉션을 포함 하도록 설정 하는 코드를 구현 합니다.It inherits from DialogViewController and implements code to set the Root to contain a collection of TaskItem objects for display.

작업 목록과 상호 작용을 표시 하 고 상호 작용 하는 데 관련 된 두 가지 주요 메서드는 다음과 같습니다.The two main methods related to displaying and interacting with the task list are:

  1. PopulateTable – 비즈니스 계층의 TaskManager.GetTasks 메서드를 사용 하 여 표시할 TaskItem 개체의 컬렉션을 검색 합니다.PopulateTable – Uses the Business Layer’s TaskManager.GetTasks method to retrieve a collection of TaskItem objects to display.
  2. 선택 됨 – 행이 작업 될 때 새 화면에 작업을 표시 합니다.Selected – When a row is touched, displays the task in a new screen.

작업 세부 정보 화면Task Details Screen

작업 세부 정보는 작업을 편집 하거나 삭제할 수 있는 입력 화면입니다.Task Details is an input screen that allows tasks to be edited or deleted.

Tasky는 MonoTouch.Dialog의 리플렉션 API를 사용 하 여 화면을 표시 하므로 UIViewController 구현이 없습니다.Tasky uses MonoTouch.Dialog’s Reflection API to display the screen, so there is no UIViewController implementation. 대신, HomeScreen 클래스는 응용 프로그램 계층에서 TaskDialog 클래스를 사용 하 여 DialogViewController을 인스턴스화하고 표시 합니다.Instead, the HomeScreen class instantiates and displays a DialogViewController using the TaskDialog class from the Application Layer.

이 스크린샷에서는 이름메모 필드의 워터 마크 텍스트를 설정 하는 Entry 특성을 보여 주는 빈 화면을 보여 줍니다.This screenshot shows an empty screen that demonstrates the Entry attribute setting the watermark text in the Name and Notes fields:

작업 정보 화면의 기능 (예: 작업 저장 또는 삭제)은 HomeScreen 클래스에서 구현 해야 합니다 .이는 MonoTouch.Dialog.BindingContext를 만든 위치 이기 때문입니다.The functionality of the Task Details screen (such as saving or deleting a task) must be implemented in the HomeScreen class, because this is where the MonoTouch.Dialog.BindingContext is created. 다음 HomeScreen 메서드는 작업 세부 정보 화면을 지원 합니다.The following HomeScreen methods support the Task Details screen:

  1. Showtaskdetails – 화면을 렌더링 하는 MonoTouch.Dialog.BindingContext을 만듭니다.ShowTaskDetails – Creates a MonoTouch.Dialog.BindingContext to render a screen. 리플렉션을 사용 하 여 TaskDialog 클래스에서 속성 이름 및 형식을 검색 하는 입력 화면을 만듭니다.It creates the input screen using reflection to retrieve property names and types from the TaskDialog class. 입력란의 워터 마크 텍스트와 같은 추가 정보는 속성에 대 한 특성으로 구현 됩니다.Additional information, such as the watermark text for the input boxes, is implemented with attributes on the properties.
  2. Savetask -이 메서드는 OnTap 특성을 통해 TaskDialog 클래스에서 참조 됩니다.SaveTask – This method is referenced in the TaskDialog class via an OnTap attribute. 저장 을 누를 때 호출 되며 MonoTouch.Dialog.BindingContext를 사용 하 여 TaskItemManager를 사용 하 여 변경 내용을 저장 하기 전에 사용자가 입력 한 데이터를 검색 합니다.It is called when Save is pressed, and uses a MonoTouch.Dialog.BindingContext to retrieve the user-entered data before saving the changes using TaskItemManager .
  3. Deletetask -이 메서드는 OnTap 특성을 통해 TaskDialog 클래스에서 참조 됩니다.DeleteTask – This method is referenced in the TaskDialog class via an OnTap attribute. TaskItemManager를 사용 하 여 기본 키 (ID 속성)를 사용 하 여 데이터를 삭제 합니다.It uses TaskItemManager to delete the data using the primary key (ID property).

Android 앱Android App

전체 Xamarin Android 프로젝트는 아래 그림에 나와 있습니다.The complete Xamarin.Android project is pictured below:

계층 별로 그룹화 된 클래스를 포함 하는 클래스 다이어그램:The class diagram, with classes grouped by layer:

참조 항목References

Android 앱 프로젝트는 Android SDK의 클래스에 액세스 하기 위해 플랫폼별 Xamarin Android 어셈블리를 참조 해야 합니다.The Android app project must reference the platform-specific Xamarin.Android assembly to access classes from the Android SDK.

또한 PCL 프로젝트를 참조 해야 합니다 (예:It must also reference the PCL project (eg. TaskyPortableLibrary)를 사용 하 여 공통 데이터 및 비즈니스 계층 코드에 액세스할 수 있습니다.TaskyPortableLibrary) to access the common data and business layer code.

응용 프로그램 계층 (AL)Application Layer (AL)

이전에 살펴본 iOS 버전과 마찬가지로, Android 버전의 응용 프로그램 계층에는 핵심에 의해 노출 되는 개체를 UI에 ' 바인딩 ' 하는 데 필요한 플랫폼별 클래스가 포함 되어 있습니다.Similar to the iOS version we looked at earlier, the Application Layer in the Android version contains platform-specific classes required to ‘bind’ the objects exposed by the Core to the UI.

Tasklistadapter – <T > 개체의 목록을 표시 하려면 ListView 사용자 지정 개체를 표시 하는 어댑터를 구현 해야 합니다.TaskListAdapter – to display a List<T> of objects we need to implement an adapter to display custom objects in a ListView. 어댑터는 목록의 각 항목에 사용 되는 레이아웃을 제어 합니다 .이 경우 코드는 Android 기본 제공 레이아웃 SimpleListItemChecked를 사용 합니다.The adapter controls which layout is used for each item in the list – in this case the code uses an Android built-in layout SimpleListItemChecked.

UI (사용자 인터페이스)User Interface (UI)

Android 앱의 사용자 인터페이스 계층은 코드 및 XML 태그의 조합입니다.The Android app’s User Interface Layer is a combination of code and XML markup.

  • 리소스/레이아웃 – 화면 레이아웃 및 행 셀 디자인은 xml 파일로 구현 됩니다.Resources/Layout – screen layouts and the row cell design implemented as AXML files. AXML은 Android 용 Xamarin UI 디자이너를 사용 하 여 직접 작성 하거나 시각적으로 레이아웃할 수 있습니다.The AXML can be written by hand, or laid-out visually using the Xamarin UI Designer for Android.
  • 리소스/그릴 모양 – 이미지 (아이콘) 및 사용자 지정 단추.Resources/Drawable – images (icons) and custom button.
  • Screen – 각 화면 및 해당 동작을 정의 하는 동작 서브 클래스입니다.Screens – Activity subclasses that define each screen and its behavior. 응용 프로그램 계층 클래스 및 공용 API (TaskItemManager)와 UI를 함께 연결 합니다.Ties together the UI with Application Layer classes and the common API (TaskItemManager).

홈 화면Home Screen

홈 화면은 작업 하위 클래스 HomeScreen 및 레이아웃 (단추 및 작업 목록의 위치)을 정의 하는 HomeScreen.axml 파일로 구성 됩니다.The Home Screen consists of an Activity subclass HomeScreen and the HomeScreen.axml file which defines the layout (position of the button and task list). 화면은 다음과 같습니다.The screen looks like this:

홈 화면 코드는 단추를 클릭 하 고 목록에서 항목을 클릭 하 고 작업 세부 정보 화면에서 변경한 내용을 반영 하도록 OnResume 메서드의 목록을 채우는 데 필요한 처리기를 정의 합니다.The Home Screen code defines the handlers for clicking the button and clicking items in the list, as well as populating the list in the OnResume method (so that it reflects changes made in the Task Details Screen). 데이터는 비즈니스 계층의 TaskItemManager 및 응용 프로그램 계층의 TaskListAdapter를 사용 하 여 로드 됩니다.Data is loaded using the Business Layer’s TaskItemManager and the TaskListAdapter from the Application Layer.

작업 세부 정보 화면Task Details Screen

작업 세부 정보 화면은 Activity 하위 클래스와 AXML 레이아웃 파일로 구성 되어 있습니다.The Task Details Screen also consists of an Activity subclass and an AXML layout file. 레이아웃은 입력 컨트롤의 위치를 결정 하 고 클래스 C# 는 TaskItem 개체를 로드 하 고 저장 하는 동작을 정의 합니다.The layout determines the location of the input controls and the C# class defines the behavior to load and save TaskItem objects.

PCL 라이브러리에 대 한 모든 참조는 TaskItemManager 클래스를 통해 진행 됩니다.All references to the PCL library are through the TaskItemManager class.

Windows Phone 앱Windows Phone App

전체 Windows Phone 프로젝트:The complete Windows Phone project:

아래 다이어그램에서는 계층으로 그룹화 된 클래스를 보여 줍니다.The diagram below presents the classes grouped into layers:

참조 항목References

플랫폼별 프로젝트는 올바른 Windows Phone 응용 프로그램을 만들기 위해 필요한 플랫폼별 라이브러리 (예: Microsoft.PhoneSystem.Windows)를 참조 해야 합니다.The platform-specific project must reference the required platform-specific libraries (such as Microsoft.Phone and System.Windows) to create a valid Windows Phone application.

또한 PCL 프로젝트를 참조 해야 합니다 (예:It must also reference the PCL project (eg. TaskyPortableLibrary)를 사용 하 여 TaskItem 클래스와 데이터베이스를 활용할 수 있습니다.TaskyPortableLibrary) to utilize the TaskItem class and database.

응용 프로그램 계층 (AL)Application Layer (AL)

또한 iOS 및 Android 버전과 마찬가지로, 응용 프로그램 계층은 사용자 인터페이스에 데이터를 바인딩하는 데 도움이 되는 비시각적 요소로 구성 됩니다.Again, as with the iOS and Android versions, the application layer consists of the non-visual elements that help to bind data to the user interface.

ViewModelsViewModels

ViewModels PCL (TaskItemManager)에서 데이터를 래핑하고 Silverlight/XAML 데이터 바인딩에서 사용할 수 있는 방식으로 표시 합니다.ViewModels wrap data from the PCL ( TaskItemManager) and presents it in way that can be consumed by Silverlight/XAML data binding. 플랫폼 특정 동작의 예입니다 (플랫폼 간 응용 프로그램 문서에서 설명).This is an example of platform-specific behavior (as discussed in the Cross-Platform Applications document).

UI (사용자 인터페이스)User Interface (UI)

XAML에는 태그에서 선언할 수 있는 고유한 데이터 바인딩 기능이 있으며 개체를 표시 하는 데 필요한 코드의 양을 줄일 수 있습니다.XAML has a unique data-binding capability that can be declared in markup and reduce the amount of code required to display objects:

  1. 페이지 – XAML 파일 및 해당 코드 숨김은 사용자 인터페이스를 정의 하 고 VIEWMODELS PCL 프로젝트를 참조 하 여 데이터를 표시 하 고 수집 합니다.Pages – XAML files and their codebehind define the user interface and reference the ViewModels and the PCL project to display and collect data.
  2. 이미지 – 시작 화면, 배경 및 아이콘 이미지는 사용자 인터페이스의 핵심 부분입니다.Images – Splash screen, background and icon images are a key part of the user interface.

MainPageMainPage

MainPage 클래스는 TaskListViewModel을 사용 하 여 XAML의 데이터 바인딩 기능을 사용 하 여 데이터를 표시 합니다.The MainPage class uses the TaskListViewModel to display data using XAML’s data-binding features. 페이지의 DataContext은 비동기적으로 채워지는 뷰 모델로 설정 됩니다.The page’s DataContext is set to the view model, which is populated asynchronously. XAML의 {Binding} 구문은 데이터가 표시 되는 방법을 결정 합니다.The {Binding} syntax in the XAML determines how the data is displayed.

TaskDetailsPageTaskDetailsPage

TaskDetailsPage에 정의 된 XAML에 TaskViewModel를 바인딩하여 각 작업을 표시 합니다.Each task is displayed by binding the TaskViewModel to the XAML defined in the TaskDetailsPage.xaml. 작업 데이터는 비즈니스 계층의 TaskItemManager을 통해 검색 됩니다.The task data is retrieved via the TaskItemManager in the Business Layer.

결과Results

결과 응용 프로그램은 각 플랫폼에서 다음과 같이 표시 됩니다.The resulting applications look like this on each platform:

iOSiOS

응용 프로그램은 탐색 모음에 배치 되는 ' 추가 ' 단추와 기본 제공 더하기 (+) 아이콘을 사용 하 여 iOS 표준 사용자 인터페이스 디자인을 사용 합니다.The application uses iOS-standard user interface design, such as the ‘add’ button being positioned in the navigation bar and using the built-in plus (+) icon. 또한 기본 UINavigationController ' 뒤로 ' 단추 동작을 사용 하 고 테이블에서 ' 살짝 밀기-삭제 '를 지원 합니다.It also uses the default UINavigationController ‘back’ button behavior and supports ‘swipe-to-delete’ in the table.

AndroidAndroid

Android 앱은 ' 틱 '이 표시 되어야 하는 행의 기본 제공 레이아웃을 포함 하는 기본 제공 컨트롤을 사용 합니다.The Android app uses built-in controls including the built-in layout for rows that require a ‘tick’ displayed. 하드웨어/시스템 뒤로 동작은 화상 뒤로 단추 외에도 지원 됩니다.The hardware/system back behavior is supported in addition to an on-screen back button.

Windows PhoneWindows Phone

Windows Phone 앱은 표준 레이아웃을 사용 하 여 위쪽의 탐색 모음 대신 화면 아래쪽에 있는 앱 표시줄을 채웁니다.The Windows Phone app uses the standard layout, populating the app bar at the bottom of the screen instead of a nav bar at the top.

요약Summary

이 문서에서는 다양 한 모바일 플랫폼 (iOS, Android 및 Windows Phone)에서 코드 재사용을 용이 하 게 하기 위해 계층화 된 응용 프로그램 디자인의 원리를 간단한 응용 프로그램에 적용 하는 방법에 대 한 자세한 설명을 제공 했습니다.This document has provided a detailed explanation of how the principles of layered application design have been applied to a simple application to facilitate code re-use across three mobile platforms: iOS, Android and Windows Phone.

응용 프로그램 계층을 설계 하는 데 사용 되는 프로세스를 설명 하 고 각 계층에서 구현 된 코드 & 기능에 대해 설명 했습니다.It has described the process used to design the application layers and discussed what code & functionality has been implemented in each layer.

Github에서 코드를 다운로드할 수 있습니다.The code can be downloaded from github.