Статьи

Введение в Swift 2.0 для iOS и OSX

Эта статья была обновлена ​​в феврале 2016 года, чтобы отразить изменения в Swift 2.0

Swift — это новая языковая опция Apple для программирования нативных приложений для iOS. Он дополняет Objective-C, и это будет иметь место в течение некоторого времени, сейчас, во второй версии , нет лучшего времени для изучения нового языка.

Разработчики Objective-C найдут много общего с дополнительными функциями, такими как вывод типа, строгая типизация, отсутствие зависимости от заголовочных файлов, обобщений и многого другого.

В этом уроке я покажу, как начать разработку приложений для iOS с помощью Swift 2. Я покажу, как настроить среду разработки, изучить основы языка и сравнить синтаксис с Objective-C, JavaScript и C #. В конце этого урока вы создадите простое, но полное приложение для iOS с использованием Swift.

Есть много случаев, когда Objective-C, C # и Swift имеют одинаковый синтаксис, обратитесь к этому файлу для полной ссылки.

Настройка вашей среды

Как и в Objective-C, Swift требует текущего Mac и Xcode. На момент написания статьи Xcode версии 7.2 является последней и загружается из магазина приложений Mac.

получить Xcode

Это большая загрузка, около 2,5 ГБ, поэтому может занять некоторое время. После завершения загрузки откройте каталог приложений и запустите Xcode. Установите любые дополнительные компоненты, необходимые при продвижении. Если у вас установлена ​​предыдущая версия Xcode, она будет обновлена ​​до последней версии.

Теперь вы готовы начать изучение и разработку со Swift.

Основы языка и синтаксис

Давайте посмотрим на синтаксис языка, отличия от Objective-C и его сравнение с другими современными языками.

Поскольку не представляется возможным подробно охватить все аспекты Swift в этом учебном пособии, я буду использовать простые примеры, демонстрирующие концепции высокого уровня.

Если вы хотите продолжить, откройте Xcode, выберите « Начать с игровой площадки» и введите каждый пример, чтобы увидеть его в действии.

Добро пожаловать в Xcode

Вы можете скачать код, который мы попробуем, с GitHub для быстрого ознакомления.

Переменные и константы

Чтобы объявить переменную в Swift, используйте ключевое слово var :

 var number = 1 

На других языках:

Objective-C

 int number = 1; 

C #

 var number = 1; 

Javascript

 var number = 1; 

Вы можете видеть, насколько похож синтаксис Swift, единственное отличие — отсутствие точки с запятой в конце объявлений.

Основное отличие Objective-C состоит в том, что вам не нужно определять тип переменной, потому что Swift использует вывод типа и может понять, что переменная является числом из-за ее начального значения.

Вы можете определить тип, если хотите:

 var number: Int = 1 

Давайте объявим строковую переменную в Swift:

 var language = "Swift" 

Здесь объявление в Swift выглядит намного чище и почти идентично C # и JavaScript. Как это соотносится с Objective-C?

 NSString *language = @"Swift"; 

В Swift нет необходимости использовать указатели памяти ( * ) или префикс строкового значения с символом @ .

Если вы работаете с платформой Foundation , вы можете использовать строку Swift в любом случае, если вы используете NSString и имеете доступ ко всему API NSString

Константы в Swift могут быть объявлены с помощью ключевого слова let :

 let language = "swift" 

Или

 let language: String = "Swift" 

На других языках то же объявление выглядит так:

Objective-C

 NSString *const language = @"Swift"; 

C #

 const string language = Swift"; 

С Swift, позволяющим выводить тип при объявлении констант.

Работа с переменными в Swift ничем не отличается от других языков, но у нее есть простой метод, позволяющий добавлять значения в строки:

 var designers = 4 var developers = 4 var teamSize = "The team has \(designers + developers) members" 

Массивы

В Swift вы создаете массивы и словари, используя квадратные скобки [ ] и получаете доступ к их элементам, записывая индекс или ключ в эти скобки.

 var arr = ["first" , "second"] 

На других языках то же объявление выглядит так:

Objective-C

 NSArray *arr = @[@"first", @"second"]; 

C #

 var arr = new[] { "first", "second" }; 

JavaScript

 var arr = ["first" , "second"]; 

Вы можете получить доступ к элементу из массива, используя значение индекса:

 var order = arr[0] 

И установите значение с помощью:

 arr[0] = "zero" 

Код такой же в Javascript и C #, но с точкой с запятой в конце оператора.

Objective-C

 NSString *order = arr[0]; 

Вы можете перечислить массив, используя цикл for:

 for item in arr { // do something } 

На других языках то же объявление выглядит так:

Objective-C

 for(NSString *item in arr) { // do something } 

C #

 foreach (var item in arr) { // do something } 

JavaScript

 for (index = 0; index < order.length; ++index) { //do something } 

Чтобы добавить другой элемент в массив, используйте оператор += :

 arr += ["fourth"] 

или функция добавления:

 arr.append("fifth") 

Словари

Объявите словарь в Swift, определив пары ключ-значение. При объявлении пустого словаря вы должны определить тип ключа и значение.

 var dict = Dictionary<String, String>() 

Вы можете объявить и присвоить значения:

 var dict = ["MEL": "Melbourne", "SYD": "Sydney"] 

На других языках такая же декларация выглядит так:

Objective-C

 NSDictionary *dict = @{ @"MEL" : @"Melbourne", @"SYD" : @"Sydney" }; 

C #

 var dict = new Dictionary<string, string> { { "MEL", "Melbourne" }, { "SYD", "Sydney" } }; 

Для доступа к элементу из словаря используйте:

 var entry = dict["MEL"] 

На других языках такая же декларация выглядит так:

Objective-C

 NSString *entry = dict[@"MEL"]; 

C #

 var entry = dict["MEL"]; 

Чтобы установить или добавить элемент в словарь, используйте:

 dict["PER"] = "Perth" 

На других языках такая же декларация выглядит так:

Objective-C

 dict[@"PER"] = @"Perth" 

C #

 dict["PER"] = "Perth"; 

Для перебора словаря используйте:

 for (cityCode, cityName) in dict { print("\(cityCode) : \(cityName)") } 

Переменная cityCode будет содержать ключ, а переменная cityName — значение.

На других языках такая же декларация выглядит так:

Objective-C

 for (id key in dict) { NSLog(@"key: %@, value: %@", key, dict[key]); } 

C #

 foreach(var item in dict) { var cityCode = item.Key; var cityName = item.Value; } 

Loops

Вы видели, как создавать элементы, давайте посмотрим, как их просматривать.

Во-первых, for синтаксиса цикла:

 for var number = 1; number < 5; number++ { //do something } 

Как и ожидалось, вы указываете значение и приращение, пока условие не будет выполнено. Синтаксис Objective-C и C # практически идентичен, как и JavaScript, но в нем отсутствует тип переменной.

Вы можете достичь того же результата, используя Swift for in варианта:

 for number in 1...5{ //do something } 

Swift создает числовую переменную и автоматически присваивает ей значение, повторяя указанное значение. 1…5 — это закрытый диапазон, который включает числа от 1 до 5.

Используя созданный ранее массив, вы можете перебирать города в массиве, используя этот синтаксис.

 for city in arr { print(city) } 

Swift предоставляет цикл while и repeat с синтаксисом, почти идентичным Objective-C, C # и JavaScript:

 while number < 10 { print(number) number++ } 

Переменная после оператора while является логическим значением, и код выполнится, когда он получит значение true .

repeat цикл ведет себя так же, но гарантирует, что код выполняется хотя бы один раз, прежде чем условие будет оценено.

 var number = 9 repeat { print(number) number++ } while number<10 

В этом примере показано, что числовое значение отображается до его увеличения и оценки оператором while.

Conditionals

Пока циклы управляют повторяющимися задачами в коде, операторы if и switch управляют потоком.

Синтаксис if в Swift может иметь круглые скобки, но не является обязательным, поэтому вы можете использовать любой стиль, который предпочитаете.

 if city == "MEL" { print("Melbourne") } 

или

 if (city == "MEL") { print("Melbourne") } 

if заявлениями может следовать оператор else if или else .

 if city == "MEL" { print("Melbourne") } else if city == "SYD" { print("Sydney") } else { print("Perth") } 

Операторы Switch в Swift сопровождаются проверкой регистра, но оператор break не требуется, так как не существует неявного провала. Это означает, что как только случай оценивается как true и выполняется, следующий случай не будет оцениваться. Но требуется действие по умолчанию.

 switch city { case "MEL": print("Melbourne") case "SYD": print("Sydney") default: print("Perth") } 

Оператор case может содержать несколько значений, разделенных запятой или диапазонами. В Swift вы можете использовать NSString в операторе switch, что невозможно в Objective-C.

функции

Функции — это большая тема, но базовые знания полезны, так что вы можете объявлять и использовать их.

Объявите функцию в Swift, используя ключевое слово func :

 func sayName() { print("Patrick") } 

Передайте параметры в скобках, указав имя переменной и тип.

 func sayName(name: String) { print(name) } 

Вы можете передать несколько параметров через запятую.

 func sayName(name: String, lastName: String) { print("\(name) \(lastname)") } 

Объявите функции, которые возвращают результаты, добавив -> после параметров и указав тип возвращаемого значения.

 func createName(name: String, lastName: String) -> String { return "\(name) \(lastname)" } 

Создание приложения для iOS с Swift

Изучение нового языка программирования лучше всего достигается написанием кода и созданием приложений. Итак, давайте создадим простое приложение для iOS, используя Swift.

Приложение подключится к TheMovieDB API , запросит список предстоящих фильмов, загрузит результаты JSON, проанализирует их в словарях и массивах и затем заполнит эти данные в табличном представлении.

Чтобы этот учебник был простым, он будет охватывать общие задачи, такие как создание и подключение элементов пользовательского интерфейса к коду, работа с несколькими контроллерами, делегатами и протоколами, и покажет, как выполнять асинхронные операции со Swift, в чем язык превосходен.

Перед запуском зарегистрируйтесь и запросите ключ API приложения на сайте themoviedb.org . Зарегистрируйтесь, если у вас еще нет учетной записи, откройте страницу своей учетной записи и создайте новый ключ в разделе API .

Окончательный код приложения находится на GitHub, и я создал ветки для каждого этапа.

Давайте начнем.

Откройте Xcode, создайте новый проект , выберите одно приложение просмотра в разделе iOS и нажмите « Далее» .

Приложение Single View

Я назвал свой проект UpcomingMovies и выбрал Swift в качестве языка.

Новое приложение

Нажмите « Далее» и выберите место для сохранения проекта.

Теперь создайте таблицу для отображения данных приложения, выбрав файл Main.storyboard в XCode и перетащив объект табличного представления из библиотеки объектов.

Вставить таблицу

Чтобы получить доступ к таблице в коде, вам нужно создать делегат, источник данных и выход.

Выберите файл раскадровки, удерживайте элемент управления, щелкните и перетащите из представления таблицы в контроллер представления, выбрав источник данных во всплывающем меню. Повторите процесс и выберите опцию делегата .

Чтобы создать розетку, выберите пункт меню « Просмотр» -> «Помощник редактора» -> «Показать редактор помощника» . Вы увидите новый раздел, в котором отображается код из файла ViewControler.Swift .

Выберите таблицу и на этот раз удерживайте элемент управления , затем щелкните и перетащите из представления таблицы в окно кода, освобождая под объявлением класса.

Дайте розетке имя, я использовал appTableView , и нажмите « Подключиться» .

Создать аутлет

Есть еще одно последнее задание для завершения пользовательского интерфейса. Это необходимо для создания ячейки-прототипа, которая будет содержать текст с подробностями фильма и будет повторно использоваться для каждой ячейки, созданной в таблице.

Для этого выберите «Вид таблицы» и в инспекторе атрибутов измените количество ячеек прототипа на 1. Затем щелкните ячейку, измените стиль на « Субтитры» и присвойте ему идентификатор MovieResultsCell .

Создать прототип

Изменить субтитры

Хорошо, время повеселиться с Swift.

Сначала вы должны настроить источник данных и набор данных, подключенный ранее в раскадровке.

В ViewController.swift измените класс следующим образом:

 class ViewController: UIViewController { 

К этому:

 class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { 

Теперь реализуйте 2 новых протокола, добавленных выше, создав необходимые методы.

Добавьте следующие строки кода в файл ViewController.swift .

 func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1; } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cellIdentifier: String = "MovieResultsCell" let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: cellIdentifier) cell.textLabel?.text = "Test" cell.detailTextLabel?.text = "Test details" return cell } 

Первый метод определяет количество строк в таблице, а второй отображает данные.

Вы можете удалить следующий код, так как он не нужен.

 override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } 

Код ViewController.Swift должен выглядеть следующим образом:

Первый этап обзора кода

Это завершает фазу 1, продолжайте и запустите проект, вы должны увидеть следующий результат.

Пример созданного приложения

Пришло время подключиться к нашему API и получить результаты. Этот код должен быть универсальным и использоваться повторно. Цель состоит в том, чтобы передать URL в качестве параметра, получить результат, проанализировать JSON и вернуть массив с данными.

Затем этот код можно повторно использовать для последующих вызовов API для других URL-адресов.

Создайте новый класс, щелкнув правой кнопкой мыши в папке, содержащей ViewController.swift на панели навигации, и выбрав « Новый файл» .

Создать новый файл

Выберите Cocoa Touch Class , нажмите Next и дайте ему осмысленное имя, я использовал APIController . Оставьте параметры по умолчанию, как показано ниже.

Создать класс API

Откройте файл и введите следующий код под import UIKit .

 protocol APIControllerDelegate { func apiSucceededWithResults(results: NSArray) func apiFailedWithError(error: String) } 

Это определяет протокол, который будет реализован в ViewControler.swift и получит результаты после завершения вызова API.

Давайте добавим функции, которые будут выполнять фактический вызов и обрабатывать результат.

В объявлении класса добавьте следующий код:

 var delegate:APIControllerDelegate? func getAPIResults(urlString:String) { //The Url that will be called. let url = NSURL(string: urlString) //Create a request. let request = NSMutableURLRequest(URL:url!) //Sending Asynchronous request using NSURLSession. NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in do { //Check that we have received data guard let data = data else { self.delegate?.apiFailedWithError("ERROR: no data") return } //Call the JSON serialisation method to generate array of results. self.generateResults(data) } }.resume() } func generateResults(apiData: NSData) { do { //Serialise the api data into a json object let jsonResult = try NSJSONSerialization.JSONObjectWithData(apiData, options: .AllowFragments) //verify we can serialise the json object into a dictionary guard let jsonDictionary: NSDictionary = jsonResult as? NSDictionary else { self.delegate?.apiFailedWithError("ERROR: conversion from JSON failed") return } //Create an array of results let results: NSArray = jsonDictionary["results"] as! NSArray //Use the completion handler to pass the results self.delegate?.apiSucceededWithResults(results) } catch { self.delegate?.apiFailedWithError("ERROR: conversion from JSON failed") } } 

Первая функция берет URL и делает запрос на получение данных от API. Если есть ошибка, он выполнит функцию apiFailedwithError протокола, который передает строку ошибки. В случае успеха он вызовет функцию generateResults для анализа данных API.

Класс APIController теперь должен выглядеть следующим образом.

APIController

Это завершает Фазу 2, если вы соберете и запустите проект, то увидите, что это пока не имеет значения.

Пришло время заполнить данные в таблице. Откройте ViewController.Swift и добавьте делегат APIControler в класс:

 class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, APIControllerDelegate { 

Под выходом appTable добавьте следующие 2 строки:

 var searchResultsData: NSArray = [] var api: APIController = APIController() 

Первая переменная будет содержать данные таблицы. Вторая переменная создает экземпляр контроллера API, который используется для вызова любого из его методов.

Теперь реализуйте протокол контроллера API, добавив следующие функции под существующими tableView . Обязательно замените пустой ключ API своим собственным.

  // MARK: APIControllerDelegate //Make the API call func getUpcomingMovies() { //Construct the API URL that you want to call let APIkey: String = "" //Replace with your Api Key" let APIBaseUrl: String = "https://api.themoviedb.org/3/movie/upcoming?api_key=" let urlString:String = "\(APIBaseUrl)" + "\(APIkey)" //Call the API by using the delegate and passing the API url self.api.delegate = self api.getAPIResults(urlString) } //Handle the Error func apiFailedWithError(error: String) { let alertController = UIAlertController(title: "Error", message: error, preferredStyle: UIAlertControllerStyle.Alert) alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default,handler: nil)) self.presentViewController(alertController, animated: true, completion: nil) } //Handle the returned data func apiSucceededWithResults(results: NSArray) { self.searchResultsData = results self.appTableView.reloadData() } 

ViewController.swift теперь должен выглядеть следующим образом.

VCwithDelegates

Давайте изменим функцию tableView и отобразим данные API на строки и ячейки.

Замените следующий код

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cellIdentifier: String = "MovieResultsCell" let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: cellIdentifier) cell.textLabel?.text = "Test" cell.detailTextLabel?.text = "Test details" return cell } 

с этим:

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cellIdentifier: String = "MovieResultsCell" let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier)! as UITableViewCell //Create a variable that will contain the result data array item for each row let cellData: NSDictionary = self.searchResultsData[indexPath.row] as! NSDictionary //Assign and display the Title field cell.textLabel!.text = cellData["title"] as? String // Construct the posterUrl to get an image URL for the movie thumbnail let imgURL: NSURL = getPoster(cellData["poster_path"] as? String) // Download an NSData representation of the image at the URL let imgData: NSData = NSData(contentsOfURL: imgURL)! cell.imageView!.image = UIImage(data: imgData) // Get the release date string for display in the subtitle let releaseDate: String = cellData["release_date"]as! String cell.detailTextLabel!.text = releaseDate return cell } 

Здесь значения из API присваиваются каждой ячейке с указанием названия фильма, афиши и даты выпуска.

API не всегда возвращает изображение для плаката. Это должно быть обработано с помощью JSON-сериализации в APIController, но этот подход слишком сложен, чтобы описывать его здесь. Так что для целей этого приложения, давайте использовать следующую функцию:

 func getPoster(posterPath: String?) ->NSURL { guard let posterPath = posterPath, let baseUrl: String = "http://image.tmdb.org/t/p/w300", let urlString: String = "\(baseUrl)" + "\(posterPath)", let imgURL: NSURL = NSURL(string: urlString) else { let defaultImageUrl: NSURL = NSURL(string: "https://assets.tmdb.org/images/logos/var_8_0_tmdb-logo-2_Bree.png")! return defaultImageUrl } return imgURL } 

Это проверяет, возвращается ли путь изображения из API и URL, созданный для таблицы. В противном случае отображается логотип tmdb.

Заменить следующую функцию

 func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1; } 

С:

 func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return searchResultsData.count } 

Это создаст столько строк в таблице, сколько результатов из API. Теперь, когда ячейки таблицы готовы к приему данных, пришло время сделать вызов API.

Добавьте следующую строку в метод viewDidLoad

 getUpcomingMovies() 

Полный класс ViewController теперь должен выглядеть следующим образом.

ВК завершен

Перед запуском приложения необходимо включить «Безопасность транспорта приложений для соединений, отличных от HTTPS», поскольку API tmdb не предоставляет зашифрованные данные.

Щелкните правой кнопкой мыши файл info.plist и выберите « Открыть как исходный код» .

введите описание изображения здесь

Добавьте следующий код внизу файла перед закрывающим словарным тегом.

  <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key><true/> </dict> 

Intro.Plist

Вот и все, теперь запустите приложение, которое должно отображать все предстоящие фильмы.

Финальное приложение

Я надеюсь, что вам понравился этот «быстрый» тур по новому языку Apple, и приветствую ваши комментарии и вопросы ниже. Если вы хотите узнать больше, я рекомендую учебное пособие по Hello World на сайте SitePoint и видеоряд серии Swift .