Разное

Программирование swift: Основы — SwiftBook

Содержание

Объектно-ориентированное программирование в Swift — SwiftBook

Объектно-ориентированное программирование — это фундаментальная парадигма программирования, которую обязательно нужно освоить,

для использования и знания языка Swift на более высоком и професcиональном уровне. Объектно-ориентированное программирование лежит в основе большинства фреймворков, с которыми в будущем вы будете работать.

Разбираясь в проблеме взаимодействия между объектами с помощью сообщений, которыми объекты обмениваются, может привести сперва к непониманию, но это проверенный способ построения сложных систем, который берет свое начало еще с 1950-х

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

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

— Инкапсуляция

— Наследование

— Переопределение и перегрузка методов

— Типы и экземпляры

— Композиции

— Полиморфизм

— Модификаторы доступа

По содержанию видно, что придется изучить многое, но уверяю, что будет интересно, так что запаситесь временем, кружкой кофе и давайте начнем! :]

Поехали!

Запустите Xcode и перейдите в: File \ New \ Playground. Введите название для проекта: «Instruments», затем выберите платформу «iOS» и нажмите «Далее». Выберите место для хранения вашего проекта и нажмите кнопку «Create». Когда откроется Playground, с вашим новым проектом, очистите его полностью, чтобы лишняя информация вам не мешала

Проектирование объектов объектно-ориентированным способом обычно начинается с самой концепции построения, затем распространяется уже на конкретные типы. Вы хотите создавать музыкальные инструменты, поэтому имеет смысл начинать с типа Instrument (тип Instrument будет общий для всех), а затем определять конкретные (не буквально!) инструменты, такие как пианино и гитары. Подумайте об этом как о генеалогическом дереве инструментов, где все течет от общего типа к конкретному сверху вниз. Пример:

Заметка

Для начала давайте обсудим следующее определения, они будут встречаться в статье, поэтому всегда можно будет вернуться в этот раздел, если вдруг вы забудете значение:
is-a — public наследование.
has-a — агрегирование (создается в классе).
use-a — агрегирование (приходят извне, доступны не только в классе).

Связь между дочерним типом и его родительским типом является отношением is-a. То есть отношением объектов друг к другу, через наследование. Например, мы видим, что «Guitar is-a Instrument». То есть «Instrument» – это родитель, а «Guitar» по отношению к типу «Instrument» является дочерним типом – Гитара является наследником типа Инструмент. Теперь, когда у вас есть визуальное представление объектов, с которыми мы будем работать, можно начать реализацию нашего проекта.

Свойства

Добавьте в Playground  следующий блок кода:

// 1 
class Instrument {   
	// 2   
	let brand: String   
	// 3  
	init(brand: String) {
		//4      
		self.brand = brand   
	}
}

Теперь давайте разберем, что мы написали выше:

  1. Вы создаете базовый класс Instrument с ключевым словом class. Это будет корневой класс по иерархии всех будущих инструментов. Он определяет «Чертеж/План», который будет содержаться в основе любого созданного инструмента (дочерних классов). Поскольку это тип, имя должно начинаться с заглавной буквы (стоит запомнить!), в нашем примере с большой буквы начинается тип Instrument, это является обязательным соглашение в Swift.
  2. Затем объявили свойства (данные) инструмента, которые будут у всех будущих инструментов. В нашем случае это свойство brand, которому мы присвоили тип строки (String).
  3. Теперь нужно создать инициализатор для класса, он обозначается ключевым словом init. Его цель — это создание новых инструментов путем инициализации всех свойств (stored properties).
  4. На этом шаге мы как раз устанавливаем данные в свойство brand из того, что будет приходить в параметрах метода. Поскольку свойство и параметр имеют одинаковое имя, нужно использовать ключевое слово self, чтобы можно было инициализировать именно нашу локальную переменную.

Сейчас вы только что реализовали класс для будущих инструментов, который содержит одно свойство brand, но еще не задали для него поведение. Поведение – означает, что мы можем повлиять на состояние свойства (объекта), через реализацию метода(ов). Давайте добавим какое-нибудь поведение в виде методов для наших свойств.

Методы

Как уже и говорилось, с помощью методов вы можете задать поведение свойствам, например сделать метод настройки (tune() ) или попросить сыграть на инструменте (play() ), при этом независимо от конкретного типа свойств. Добавьте следующий код внутри класса Instrument сразу после инициализатора:

func tune() -> String {   
	fatalError("Implement this method for \(brand)")
 }

Метод tune() — это функция, которая выполнится, только при условии, что мы ее вызовем в наследуемом классе. Классы с подобными методами называются абстрактными, потому что они не предназначены для обычного использования. Чтобы использовать их, вы должны определить подкласс, который переопределит этот метод tune(), после переопределения можно реализовать логику данного метода, а не просто вызвать fatalError(). Подробнее об этом мы поговорим позже.

Функции, определенные внутри класса, называются методами, поскольку они имеют доступ к свойствам, в нашем случае таким свойством является brand, свойство класса Instrument. Организация свойств и связанных с ними операций в классе — это мощный инструмент для упрощения сложных процессов.

Такого рода реализация носит название «Инкапсуляция». Тип класса описывает инкапсулированные данные (например, свойства хранения) и их поведение (например, методы).

Теперь давайте добавим следующий код, но только уже перед нашим классом Instrument:

class Music  {   
	let notes: [String]   
 
	init(notes: [String])  {     
		self.notes = notes   
	}    

	func prepared() -> String  {     
		return notes.joined(separator: " ")   
	} 
}

Это класс Music, который инкапсулирует массив нашего свойства notes с типом String и позволяет задать поведение, в нашем примере мы добавили поведение, которое может соединить все приходящие данные в свойстве, в одну строку, это метод prepared().

Теперь добавьте следующий метод в класс Instrument сразу после метода tune():

func play(_ music: Music) -> String {   
	return music.prepared() 
}

Метод play(_ : ) возвращает строку (String), музыку которую нужно воспроизвести. Возможно у вас возник вопрос, зачем нам создавать специальный тип Music, а не просто передать весь массив строк (String). Дело в том, что это дает ряд преимуществ: создание типа Music помогает создавать словарь, что позволит компилятору проверить корректность работы и создаст место для будущих расширений.

Теперь добавьте следующий метод в класс Instrument сразу после метода play(_ : ):

func perform(_ music: Music) {   
	print(tune())   
	print(play(music)) 
}

Метод perform(_ 🙂 задает поведение настройки инструмента, а затем воспроизводит музыку. Мы создали два метода рядом, чтобы мы могли насладиться настроенной, красиво звучащей симфонией. :]

Это все касалось реализации класса Instrument. Сейчас самое время добавить уже конкретные инструменты.

Наследование

Добавьте следующий класс в нижней части Playground, сразу после класса Instrument:

// 1 
class Piano:  Instrument  {
	let hasPedals: Bool   
	// 2   
	static let whiteKeys = 52   
	static let blackKeys = 36      
	// 3   
	init(brand: String, hasPedals: Bool = false) {             
	       self.hasPedals = hasPedals     
	   // 4     
	   super.init(brand: brand)   
	}      
	// 5   
	override func tune() -> String {     
		return "Piano standard tuning for \(brand)."   
	}      
	override func play(_ music: Music) -> String {     
	// 6      
	let preparedNotes = super.play(music)     
	     return "Piano playing \(preparedNotes)"   
	} 
}

Давайте разберем, шаг за шагом:

  1. Вы создаете класс Piano в качестве подкласса родительского класса Instrument. Все свойства и методы автоматически наследуются дочерним классом Piano и доступны для пользования.
  2. Любое пианино, которое захотите создать, будет иметь одинаковое количество белых и черных клавиш, независимо от их бренда (brand). Динамически эти свойства клавиш с их значениями никогда не изменятся, потому что мы указали свойство как static.
  3. Для параметра hasPedals, инициализатор предоставляет значение по умолчанию false, которое при желание можно будет изменить.
  4. В этом месте мы используем ключевое слово super, чтобы вызвать инициализатор родительского класса, сразу после установки свойства hasPedals  дочернего класса. Инициализатор суперкласса заботится об инициализации унаследованных свойств — в данном случае это свойство brand.
  5. Переопределяем реализацию унаследованного метода tune() с ключевым словом override. Это обеспечивает реализацию метода tune(), которая не вызовет fatalError(), а сделает что-нибудь в классе Piano, например распечатает брэнд настроенного пианино.
  6. Здесь происходит переопределение унаследованного  метода  play(_ : ). С этим методом вы используете ключевое слово super, это делается для того, чтобы вызвать родительский метод Instrument, затем получить подготовленные музыкальные ноты и сразу начать игру на пианино.

Поскольку класс Piano наследуется от класса Instrument, он уже совершенно точно знает о классе Instrument, что: у него есть свойство brand, есть метод для настройки музыки tune(), есть метод проигрывания музыки play() и метод выполняющий воспроизведение музыки с нашими настройками perform().

Заметка

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

Конечно вся музыка при игре на пианино издает какие либо звуки, но ведь звучать оно может по-разному. Поэтому пришло время добавить в вашу музыку педали, чтобы звучание можно было менять по нашему вкусу. :]

Перегрузка методов

Добавьте следующий метод в класс Piano, сразу после переопределенного метода play(_ : ):

func play(_ music: Music, usingPedals: Bool) -> String {   
	let preparedNotes = super.play(music)   
	if hasPedals && usingPedals {     
	    return "Play piano notes \(preparedNotes) with pedals."       
	} else { 
	    return "Play piano notes \(preparedNotes) without pedals."   
	} 
}

Добавление этого метода перегружает метод play(_ : ) для задействования педалей, при условии, что usePedals у нас true, и у пианино доступны педали в параметрах. Мы не задействовали ключевое слово override, потому что у нового созданного метода play() отличается список параметров, в отличии от переопределенного метода play(). Swift использует список параметров (сигнатуру), чтобы автоматически определить, требуется ли переиспользование метода. Следует быть осторожными с перегрузкой методов, потому что они могут вас запутать. Например, метод perform(_ 🙂 всегда вызывает play (_ 🙂 и только его, он никогда не вызовет наш второй созданный метод play(_: usingPedals 🙂.

Сделайте в методе play(_ : ), в классе Piano, другую реализацию метода, которая будет вызывать другую педаль, добавьте код ниже:

override func play(_ music: Music) -> String {   
	return play(music, usingPedals: hasPedals) 
}

Теперь пришло время попробовать с созданием экземпляров класса Piano, мы сможем сделать для него необходимые настройки и воспроизвести на нем действительно классную музыку. :]

Экземпляры

Добавьте следующий блок кода в конце Playground  сразу после объявления класса Piano:

// 1 
let piano = Piano(brand: "Yamaha", hasPedals: true) piano.tune() 
// 2 
let music = Music(notes: ["C", "G", "F"]) piano.play(music, usingPedals: false) 
// 3 
piano.play(music) 
// 4 
Piano.whiteKeys 
Piano.blackKeys

Теперь разберемся, что у нас тут происходит:

  1. Объявили переменную piano, как экземпляр класса Piano и инициализировали все необходимые данные. Обратите внимание, что в то время как типы (классы) начинаются с заглавной буквы, экземпляры всегда начинаются с маленькой. Опять же, это является обязательным соглашением Swift.
  2. Тут вы объявляете переменную music, как экземпляр класса Music, заполняете необходимые данные и далее задаете поведение игры на пианино по нотам, с помощью нашего перегруженного метода play(), которая позволит воспроизвести песню уже без использования педалей, так как мы передали в параметр false.
  3. Вызываем из класса Piano, версию метода play(_ : ), которая всегда использует педали, при условии, что этот параметр доступен.
  4. Здесь указаны статические переменные (whiteKeys и blackKeys), которые хранятся внутри класса Piano, для их вызова нам не нужно создавать конкретный экземпляр класса – достаточно будет указать название класса и через точку указать свойство. Такие свойства называются – свойства типа, про это обязательно почитайте в официальной документации.

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

Промежуточный абстрактный базовый класс

Добавьте класс Guitar в самом конце вашего Playground:

class Guitar: Instrument  {   
	let stringGauge: String  
    
	init(brand: String, stringGauge: String = "medium") {    
		self.stringGauge = stringGauge     
		super.init(brand: brand)   
	} 
}

Мы создали новый класс Guitar, который вносит идею струнного датчика в виде текстового параметра строки (String) для базового класса Instrument. Подобно классу Instrument, подкласс Guitar считается абстрактным типом, методы tune () и play (_ : ) должны быть переопределены в подклассе Guitar. Поэтому его иногда называют промежуточным абстрактным базовым классом.

Заметка

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

Теперь для классов, которые будут наследовать тип Guitar, вы сможете добавить действительно крутые гитарные партии! Давай сделаем это! :]

Конкретные гитары

Первый тип гитары, которую мы создадим, — давайте это будет акустическая. Добавьте класс AcousticGuitar в конец Playground сразу после вашего класса Guitar:

class AcousticGuitar: Guitar  {   
	static let numberOfStrings = 6   
	static let fretCount = 20      

	override func tune() -> String {     
		return "Tune \(brand) acoustic with E A D G B E"   
	}      

	override func play(_ music: Music) -> String {     
		let preparedNotes = super.play(music)     
		return "Play folk tune on frets \(preparedNotes)."   
	}
 }

Все акустические гитары имеют 6 струн и 20 ладов, нам потребуется  определить необходимые для этого свойства и определим их как static, поскольку они будут относиться ко всем акустическим гитарам. Static означает, что они являются константами, их значение никогда не изменится, ранее об этом мы уже говорили. В классе отсутствуют свойства, которым потребуется инициализация, поэтому создавать инициализатор нам не потребуется. Класс AcousticGuitar по умолчанию наследует инициализатор от своего родительского класса Guitar.

Итак, время испытать нашу гитару!

Задачка

Нужно определить акустическую гитару Roland. Настроить ее и сыграть на ней.
Решение ниже!

Добавьте следующий код в нижней части Playground сразу после объявления класса AcousticGuitar:

let acousticGuitar = AcousticGuitar(brand: "Roland", stringGauge: "light") 
acousticGuitar.tune() 
acousticGuitar.play(music)

Пришло время немного пошуметь и сыграть какую-нибудь громкую музыку. Теперь уже нам потребуется усилитель, так что создадим его! :]

Уровень доступа Private

Акустические гитары играют превосходно, но с усилителем они будут играть гораздо лучше.  Добавьте класс Amplifier в нижней части Playground, чтобы начать нашу вечеринку:

// 1 
class Amplifier  {   
	// 2   
	private var _volume: Int   
	// 3   
	private(set) var isOn: Bool    

	init() {     
		isOn = false     
		_volume = 0   
	}    
	// 4   
	func plugIn() {     
		isOn = true   
	}    

	func unplug() {     
		isOn = false   
	}    
	// 5   
	var volume: Int {     
		// 6     
		get {       
			return isOn ? _volume : 0     
		}     
		// 7     
		set {      
			_volume = min(max(newValue, 0), 10)     
		}   
	} 
}

Здесь довольно много что у нас происходит, поэтому давайте разберёмся:

  1. Вы определяете класс Amplifier. Это такой же базовый класс, как и Instrument.
  2. Свойство _volume отмечено доступом private, это говорит о том, что его можно получить только внутри класса Amplifier, а также будет скрыто от внешних пользователей. Нижнее подчеркивание в начале имени говорит о том, что свойство имеет скрытую реализацию данных. Еще раз, это все является неким соглашением в Swift, поэтому было бы хорошо, если вы всегда будете придерживаться этим правилам. :]
  3. Свойство isOn может быть доступно внешним пользователям, но только лишь для чтения значения. Данная конструкция разрешает получить значение поля объекта, но без установки в него значения, делается все это с помощью модификатора доступа private(set).
  4. PlugIn() и unplug() влияют на поведение isOn.
  5. Свойство с именем volume делает обертку над нашим приватным свойством _volume, чтобы мы могли задать необходимые для него правила.
  6. Геттер (get{}) понижает громкость до 0, если звук (volume) не подключен.
  7. Внутри сеттера (set{}) звук всегда будет держать ограничение по значениям от 0 до 10. Настройки на усиление громкости до 11 отсутствует.

Ключевым моментом является установка доступа private – это очень правильно для того, чтобы скрыть логику внутреннего кода и защитить ваш класс от нежелательных изменений. Для это есть свое название — «protecting the invariant».

Композиции

Теперь, когда у вас есть удобный компонент усилителя, пришло время использовать его в электрогитаре. Добавьте класс ElectricGuitar в конце Playground сразу после класса Amplifier:

// 1 
class ElectricGuitar: Guitar  {   
	// 2    
	let amplifier: Amplifier      
	// 3   
	init(brand: String, stringGauge: String = "light", amplifier: Amplifier) {     
		self.amplifier = amplifier     
		super.init(brand: brand, stringGauge: stringGauge)   
	}      
	// 4   
	override func tune() -> String {     
		amplifier.plugIn()     
		amplifier.volume = 5     
		return "Tune \(brand) electric with E A D G B E"   
	}      
	// 5   
	override func play(_ music: Music) -> String {     
		let preparedNotes = super.play(music)     
		return "Play solo \(preparedNotes) at volume \(amplifier.volume)."   	
	} 
}

Теперь пояснения:

  1. ElectricGuitar — это тип, который происходит от абстрактного, промежуточного базового класса Guitar.
  2. Электрическая гитара содержит свойство усилитель (amplifier). Это отношение has-a, а не отношения is-a, как в случае с наследованием.
    P.S. Если забыли, что такое has-a  и is-a  вернитесь в начало статьи :]
  3. Пользовательский инициализатор, который инициализирует все свойства хранения, а затем вызывает инициализатор суперкласса.
  4. Метод tune() с определенным поведением.
  5. Метод play() тоже с определенным своим поведением.

Аналогичным образом добавьте класс BassGuitar в нижней части Playground сразу после класса ElectricGuitar:

class BassGuitar: Guitar  {   
	let amplifier: Amplifier 
   
	init(brand: String, stringGauge: String = "heavy", amplifier: Amplifier) {     
		self.amplifier = amplifier     
		super.init(brand: brand, stringGauge: stringGauge)   
	}    

	override func tune() -> String {     
		amplifier.plugIn()     
		return "Tune \(brand) bass with E A D G"   
	}    

	override func play(_ music: Music) -> String {     
			let preparedNotes = super.play(music)     
			return "Play bass line \(preparedNotes) at volume \(amplifier.volume)."   
	} 
}

Мы только что создали бас-гитару, которая также использует has-a  по отношению к усилителю. Все этот класс завершили. Переходим к задаче ниже!

Задачка

Возможно, вы слышали, что классы следуют ссылочной семантике (reference semantics). Это означает, что переменные, содержащие экземпляр класса, фактически содержат ссылку на этот экземпляр. Если у вас есть две переменные с одной и той же ссылкой, изменение данных в одном изменит данные в другом, и на самом деле это одно и то же. Давайте посмотрим на ссылочную семантику в действии, создав экземпляр усилителя и разделив его между электрогитарой “Gibson” и бас-гитарой “Fender”.

Добавьте следующий код в нижней части Playground сразу после объявления класса BassGuitar:

let amplifier = Amplifier() 
let electricGuitar = ElectricGuitar(brand: "Gibson", 
					stringGauge: "medium", 
					    amplifier: amplifier) 
electricGuitar.tune()  

let bassGuitar = BassGuitar(brand: "Fender",  
			    stringGauge: "heavy", 
				 amplifier: amplifier) bassGuitar.tune()  

// Обратите внимание, что из-за семантики ссылки на класс усилитель является общим ресурсом между этими двумя гитарами.

bassGuitar.amplifier.volume
electricGuitar.amplifier.volume
bassGuitar.amplifier.unplug()
bassGuitar.amplifier.volume
electricGuitar.amplifier.volume
bassGuitar.amplifier.plugIn()
bassGuitar.amplifier.volume
electricGuitar.amplifier.volume

Полиморфизм

Одной из сильных сторон объектно-ориентированного программирования является возможность использовать разные объекты через один и тот же интерфейс, в то время когда каждый реализовывает свою логику. Это полиморфизм, означающий «many forms» (много-форменный). Добавьте класс Band в Playground:

class Band  {   
	let instruments: [Instrument]      

	init(instruments: [Instrument]) {     
		self.instruments = instruments   
	}      

	func perform(_ music: Music) {     
		for instrument in instruments {       
		instrument.perform(music)     
		}   
	} 
}

Класс Band имеет свойство массива instruments, которую мы определили в инициализаторе. Группа (band) выступает вживую на сцене, проходя через массив (array) инструментов (instruments) в цикле for in и вызывает метод perform(_ 🙂 для каждого инструмента в массиве.

Теперь давайте продолжим и подготовим первый свой рок-концерт. Добавьте следующий блок кода в нижней Playground, сразу после класса Band:

let instruments = [piano, acousticGuitar, 
				electricGuitar, bassGuitar] 

let band = Band(instruments: instruments) band.perform(music)

Сначала вы определяете массив instruments (инструментов) из экземпляров класса Instrument, которые ранее мы создали. Затем вы объявляете объект band и настраиваете свойство своих instruments  (инструментов) с помощью инициализации в классе Band. Теперь, вы используете метод perform(_ : ), экземпляра band,

чтобы задавать поведение группе и исполнять живую музыку (в Playground вы должны увидеть результат вашей музыки).

Обратите внимание, что, хотя тип массива instruments[Instrument], каждый инструмент выполняет свое поведение, в зависимости от его типа класса. Вот как полиморфизм работает на практике. Теперь в живую вы выступаете на концертах, как профессионал, поздравляю! :]

Модификаторы доступа

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

 

Private: Доступен только внутри класса.

Fileprivate: Доступен из любого места в пределах одного файла.

internal: Доступен из любого места в том же модуле или приложении.

Public: Доступен вне модуля.

Дополнительно существуют еще два доступа:

Open: Может быть доступен не только вне модуля, но также может быть унаследован и переопределен.

Final: Невозможно переопределить или сделать какие либо изменения

Если вы не укажете модификатор доступа к классу, свойству или методу, по умолчанию будет использован internal доступ. Сегодня мы использовали достаточно простой проект и по большому счету модификаторы доступа тут не важны. Но об этом стоит задуматься всерьез на будущее, когда ваше приложение будет становиться все больше и сложнее, вам обязательно потребуется использование модификаторов доступа, чтобы скрывать часть реализации.

Создание фрэимворка

Предположим, вы захотели создать свой собственный музыкальный и инструментальный фрэимворк. Вы можете сделать это, добавив новый класс в папку «Sources» в скомпилированные проекте вашего Playground. Во-первых, удалите классы Music и Instrument из Playground. Это вызовет множество ошибок, которые вы сейчас исправите ниже.

Убедитесь, что Project Navigator  (Навигатор проектов) доступен в Xcode, перейдя в меню View\Navigators\Show Project Navigator. Затем щелкните правой кнопкой мыши папку «Sources» и выберите «New File» в меню. Переименуйте файл в MusicKit.swift и удалите внутри все лишнее. И вставьте указанный код ниже:

// 1 
final public class Music  {   
	// 2   
	public let notes: [String]    
	public init(notes: [String]) {     
		self.notes = notes   
	}    
	public func prepared() -> String {     
		return notes.joined(separator: " ")   
	} 
}  
// 3 
open class Instrument  {   
	public let brand: String    
	public init(brand: String) {     
		self.brand = brand   
}    
// 4    
open func tune() -> String {     
	fatalError("Implement this method for \(brand)")   
}    

open func play(_ music: Music) -> String {     
	return music.prepared()   
}    
// 5
final public func perform(_ music: Music) {     
	print(tune())     
	print(play(music))   
	} 
}

Сохраните файл и вернитесь на главную страницу Playground. Не беспокойтесь, ваш проект будет работать как и прежде.

Итак, что мы здесь сделали:

  1. final public означает, что будет доступен везде, но только для чтения, вы не сможете его переопределить или внести изменения.
  2. Каждое свойство, инициализатор и метод должны быть с модификатором доступа public, чтобы мы могли увидеть его из любого другого места.
  3. Класс Instrument отмечен как open, поскольку мы хотим дать разрешение на изменения.
  4. Методы также могут быть определены как open, это дает разрешение на их переопределение.
  5. Или методы могут быть отмечены как final, если мы хотим запретить их переопределить. Данный доступ дает полную гарантию за сохранность.

А что дальше?

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

Урок подготовил: Просвиряков Вадим

Источник урока.

7 причин изучить Swift | GeekBrains

И почему вам стоит начать немедленно.

https://d2xzmw6cctk25h.cloudfront.net/post/1401/og_cover_image/fe014dfcd164d1c9c60b8d3a2243ed0c

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

Mac и iOS

Только за 2016 год AppStore собрал около 20 миллиардов долларов для разработчиков с приложений на платформах Mac и iOS. Поскольку Apple берёт с прибыли 30% в AppStore, рынок можно оценить в 28,5 миллиардов долларов.

Огромные деньги! И ты можешь оторвать свою долю от этого пирога.

Язык Swift используется для создания приложений под Mac и iOS, выступая в качестве возможной замены Objective-C. Последний хоть и активно используется, но морально устарел и не имеет будущего  Изучив Swift, вы сможете создавать приложения сразу для обеих платформ и очень хорошо на этом заработать.

Swift отлично подходит для быстрого развития

Когда команда Apple разрабатывала замену Objective-C, у них было два основных требования:

  • Он должен быть прост в изучении.
  • Должен способствовать ускорению цикла разработки приложений.

В итоге, Swift имеет все атрибуты современного языка программирования и определённо превосходит Objective-C по всем фронтам. Основные особенности:

  • Нет неопределенных или неинициализированных переменных.
  • Нет ошибок с размерностями массивов.
  • Нет ошибок переполнения.
  • Явная обработка значений nil (null).
  • Автоматическое управление памятью.

Таким образом, вы тратите больше времени на реализацию идей и меньше — на беспокойство по поводу возможных ошибок, сбоев и конфликтов вашего кода. Кроме того, язык поборол синтаксическую многословность в Objective-C, что упростило запись и чтение. Результат – в разы меньше времени на написание аналогичного кода в Swift.

Swift производителен

Несмотря на то, что Swift язык высокого уровня, ориентированный на скорое изучение, он по-настоящему быстр. По словам Apple, Swift до 2.6 раз быстрее, чем Objective-C и почти в 8,4 раза быстрее, чем Python 2.7. Конечная цель – сделать язык быстрее, чем C++.

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

  • дженерики;
  • замыкания;
  • кортежи;
  • множественные возвраты;
  • итераторы;
  • встроенные шаблоны ФП.

И ещё много другого.

Swift безопасен

Введение многих из перечисленных возможностей, а также усовершенствование синтаксиса делает Swift безопаснее, нежели Objective-C.

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

Swift бесплатный и открытый

Через год после появления Swift Apple сделал его  языком с открытым исходным кодом. Хотя это не уникальное явление для современного мира, для «яблочной» компании подобная щедрость – редкость. Как правило, Apple проталкивает проприетарные технологии, чтобы выделить собственную уникальность. Но шаг со Swift стал оправданным и плодотворным.

Как и в случае с любым другим языком с открытым исходным кодом, Swift – полностью в руках сообщества. Пользователи могут предлагать пути исправления ошибок и улучшать функции, помогают переносить приложения за пределы Mac и iOS. В конце концов, пользователи – главная движущая сила языка

Стремительный рост и высокий спрос

Согласно отчету GitHub Octoverse 2017, Swift является 13-м по популярности среди языков в проектах с открытым исходным кодом.

Ресурс TNW в 2016 году сообщил, что спрос на сотрудников Swift вырос на 600 процентов. К концу года Upwork сообщила, что Swift стал вторым самым быстрорастущим навыком на внештатном рынке труда. И в опросе Stack Overflow 2017 Swift стал четвертым самым любимым языком среди активных разработчиков.

Glassdoor сообщает о среднем базовом окладе для iOS Developer в размере 107 тыс. долларов.

Разработка приложений сегодня – одна из самых «горячих» профессий на бирже. Выбрав Swift в качестве фундамента карьеры, вы точно не пожалеете.

Swift – будущее Apple

У Apple нет причин в ближайшее десятилетие заменять Swift другим языком. Добавьте сюда 4-летний прогресс, как с точки зрения развития, так и популярности, неизменно растущие продажи «яблочных» устройств и расширение линейки. Основываясь на этих фактах, можно с уверенностью говорить, что потребность в Swift-разработчиках будет расти.

Если вы хотите работать с Apple, хотите быть частью их сумасшедших финансовых отчётов – вам нужен Swift. Самое время начать обучение. Вы знаете с чего начать.

Знакомьтесь, Swift! / Хабр

2 июня на конференции WWDC 2014 Apple представила новый объектно-ориентированный язык программирования — Swift. Я думаю, многие уже успели посмотреть, что из себя представляет этот язык (Swift — нововведения), поэтому я не буду останавливаться на нововведениях. Я предлагаю создать простенький проект на языке Swift, чтобы понять на деле основные отличия от привычного Obj-C.

Подготовка

Для начала необходимо установить Xcode 6 Beta. Скачать его можно отсюда:
https://developer.apple.com/devcenter/ios/index.action
Скачиваем, устанавливаем и открываем (проблем с установкой не должно возникнуть, beta версия ставится как отдельное приложение и на основной Xcode никак не влияет).
Создаем новый проект (Single View Application) -> вводим название проекта и не забываем выбрать язык Swift!

Структура

Обратите внимание на структуру, количество файлов теперь в 2 раза меньше, теперь нет необходимости в заголовочных файлах. Код, написанный в глобальной области используется в качестве точки входа для программы, так что больше не нужна функция main.

Вот как выглядит теперь AppDelegate:

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
                            
    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    func applicationWillResignActive(application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(application: UIApplication) {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
}
Hello World

Изучение любого языка начинается с Hello World. Не станем нарушать традицию. Откройте AppDelegate.swift и добавьте в func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool строку:

println("Hello World") //Выводит в консоль

Запустите программу и вы увидите в консоли заветный Hello World. Вот так все просто.

Усложним

Немного усложним проект. Добавим любимый TableView.
Открываем Main.storyboard. Кстати, обратите внимание что для универсального приложения теперь по умолчанию создается не два storyboard, как было раньше, а всего лишь один. Количество симуляторов тоже увеличилось:

Находим в Object Library заветный Table View и переносим его на экран приложения. Растягиваем таблицу, чтобы она была на весь экран (необходимо, чтобы она совпадала с краями).

Дальше все делается как и раньше, нам нужно задать для таблицы dataSource и delegate. Для этого открываем Connection Inspector, от delegate тянем к объекту ViewController и аналогично для dataSource.

Во ViewController.swift нужно указать протоколы, которые нам понадобятся: UITableViewDataSource и UITableViewDelegate

Теперь это можно сделать так:

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

Компилятор сразу ругнется:
Type ‘ViewController’ does not conform to protocol ‘UITableViewDataSource’
Компилятор сообщает нам, что мы не определили функции протокола 'UITableViewDataSource'. Чтобы посмотреть какие функции нужно определить, зажмите command + кликните по протоколу.

protocol UITableViewDataSource : NSObjectProtocol {
    
    func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
    func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!

Вот эти две функции и необходимо добавить в наш ViewController.swift
Первая функция должна возвращать количество строк в таблице (Int):

func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
 {
        return 20
  }

А вторая функция возвращает ячейку таблицы:

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
    {
        let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestSwiftCell")
        
        cell.text = "Habrapost \(indexPath.row)"
        cell.detailTextLabel.text = "Hi, \(indexPath.row)"
        
        return cell
    }

В первой строчке создаем ячейку. Разберем запись подробней:
let означает, что мы создаем константу, а не переменную.
let cell: UITableViewCell сообщаем, что тип этой константы будет UITableViewCell. По идее, необязательно сообщать какой тип будет у константы или переменной. Программа будет прекрасно работать и так:

let cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestSwiftCell")

Но как мне кажется, лучше все-таки сообщать, Apple дает хороший пример почему:

let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70

Напомню, как мы создавали ячейку в Obj-C:

UITableCell *cell =[[UITableCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyTestSwiftCell"]

Не нужен больше alloc, Swift все делает самостоятельно. Все методы, которые начинались с init были убраны, и теперь инициализация происходит в стиле Swift (т.е MyClass()). Причем инициализаторы с with тоже были преобразованы, то что шло после with — стало первым аргументом в инициализаторе Swift.

Вот эта запись мне особенно сильно понравилась:

cell.text = "Habrapost \(indexPath.row)"

В Obj-C, чтобы сделать простую операцию конкатенацию строк, нужно было изгаляться следующим образом:

cell.text = [NSString stringWithFormat:@"Habrapost %@", indexPath.row];

По мне, так это приятное изменение.
Скажем теперь мы захотели изменить цвет текста на стандартный фиолетовый. Сделать это можно аналогично тому как было в Obj-C, обратимся к методу класса

cell.detailTextLabel.textColor = UIColor.purpleColor()

В итоге, получаем

Немного о playground

Playground — это площадка, где можно поэкспериментировать, и если понравиться перенести в основной проект.
Для того, чтобы создать playgroung выберете File->New->File:

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


Подробней почитать можно здесь https://developer.apple.com/…

Заключение

На первый взгляд, мне язык понравился. Довольно легко будет перейти от Obj-C на Swift, к тому же Swift прекрасно уживается с Obj-C. Количество кода уменьшилось в разы, читаемость при этом увеличилась. С памятью теперь вообще возиться не надо, все это делает Swift.

Подробнее про Swift: The Swift Programming Language

Функциональное программирование в Swift — SwiftBook

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

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

Функциональное программирование может показаться в теории сложным, именно поэтому в этом туториале мы будем разбирать его на наглядных примерах. Сначала вы будете проходить задачи известными и знакомыми вам способами, а затем попробовать свои силы в решении этих же задач с использованием функциональных методов.

Пришло время повеселиться… в функциональном программировании!

Простая фильтрация массива

Вы начнете с очень простого: с математики. Ваша первая задача состоит в том, чтобы создать простой Swift скрипт, находящий все четные числа от 1 до 10 (включительно). Довольно простая задача и отличное введение в функциональное программирование!

Фильтрация старым способом

Создайте новый файл в плейграунде Swift и сохранить его. Замените содержимое созданного файла следующим:


var evens = [Int]()
for i in 1...10 {
  if i % 2 == 0 {
    evens.append(i)
  }
}
print(evens)

Это приведет к желаемому результату:


[2, 4, 6, 8, 10]

(Если вы не видите консоль, то вам нужно, чтобы показался Assistant Editor, вы можете его вызвать через View/Assistant Editor/Show Assistant Editor.)

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

  1. Вы создаете пустой (и изменяемый) массив.
  2. Цикл for перебирает числа от 1 до 10 (помните, «» включительно!).
  3. Если условие (о том, что число должно быть четным) удовлетворяется, то вы добавляете его в массив.

Приведенный выше код является императивным по своей сути. Инструкции указывают компьютеру, как располагать четные числа через четкие инструкции, использующие основные структуры контроля, в данном случае if и for-in.

Код работает просто отлично, но есть важное «но» — тестирование на то, является ли число четным, закопано внутри цикла. Существует также глубокая связь: желаемое действие добавления числа в массив находится внутри условия. Если вы хотите напечатать каждое четное число где-то еще в вашем приложении, то кроме копи-пейста лучшего варианта у вас и не будет.

Функциональная фильтрация

Добавьте следующее в конец вашего плейграунда:


func isEven(number: Int) -> Bool {
  return number % 2 == 0
}
evens = Array(1...10).filter(isEven)
print(evens)

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


[2, 4, 6, 8, 10]

Давайте рассмотрим подробнее функциональную версию. Она состоит из двух частей:

  1. Раздел Array(1…10) представляет собой простой и удобный способ создания массива и содержит числа от 1 до 10. Оператор диапазона 1…10 создает диапазон, который вы передаете инициализатору массива.
  2. Выражение filter — это то место, где происходит магия функционального программирования. Этот метод, раскрытый через Array, создает и возвращает новый массив, содержащий только элементы, для которых данная функция возвращает значение true. В этом примере isEven подается на filter.

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


evens = Array(1...10).filter { (number) in number % 2 == 0 }
print(evens)

Убедитесь, что результаты всех трех вариантов одинаковые. Приведенный выше пример показывает, что компилятор выводит тип параметра числа и возвращает типы замыкания из контекста использования.

Если вы хотите, чтобы ваш код был еще более кратким, то попробуйте следующее:


evens = Array(1...10).filter { $0 % 2 == 0 }
print(evens)

Код выше использует сокращенное обозначение аргумента, неявные возвращения …, вывод типа … И это работает!

Заметка

Использование сокращенного обозначения аргумента является вопросом предпочтений. Лично я считаю, что для простых примеров, таких как приведен выше, сокращенное обозначение — это то, что нужно. Тем не менее, я бы выбрал явные имена аргументов для чего-то более сложного. Компиляторы не связаны с именами переменных, но с их помощью мир станет гораздо разнообразнее!

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

  1. Higher-order functions (Функции высшего порядка): Это функции, которые вы передаете в качестве аргументов другим функциям. В этом простом примере, фильтр требует передачи функции высшего порядка.
  2. First-class functions (Функции первого класса): Вы можете рассматривать функции, как любую другую переменную. Вы можете присвоить их переменным и передать их в качестве аргументов другим функциям.
  3. Closures (Замыкания): Это фактические анонимные функции, которые вы создаете на месте.

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

Магия фильтров

Массивы в Swift имеют ряд функциональных методов, таких как map, join и reduce. Что, собственно, происходит за кулисами этих методов?

Пришло время прикоснуться к магии фильтров и добавить собственную реализацию.

В этом же плейграунде, добавьте следующую функцию:


func myFilter<T>(source: [T], predicate:(T) -> Bool) -> [T] {
  var result = [T]()
  for i in source {
    if predicate(i) {
      result.append(i)
    }
  }
  return result
}

Выше вы видите общую (generic) функцию, которая принимает в качестве своих входных параметров исходный массив типа  T, и предекат, или функцию, которая принимает экземпляр типа T и возвращает Bool.

Реализация MyFilter выглядит практически также, как императивная версия, которую вы добавили в начале. Основное отличие заключается в том, что у вас есть условие, которое проверяется как функция, а не просто жестко hard-code (определять в коде конкретные значения переменных вместо того, чтобы получать их из внешних источников).

Поработаем с добавленной реализацией фильтра, добавив следующий код:


evens = myFilter(Array(1...10)) { $0 % 2 == 0 }
print(evens)

Опять результат такой же!

Задачка!

Вышеуказанная функция фильтра является глобальной, а вы сможете сделать ее методом массива?

Подсказка №1

Вы можете добавить myFilter в массив с помощью расширения класса.

Подсказка №2

Вы можете расширить Array, но не Array<T>. Это означает, что, когда вы перебираете элементы массива через себя, вы должны выполнить приведение.

Функция Reduce

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

Создайте новый плейграунд и ждите новое задание!

Своя функция Reduce

Ваша задача в этом разделе лишь немного сложнее. Возьмите четные числа от 1 до 10, и вычислите их сумму. Для этого вам понадобится функция reduce, которая принимает несколько входных значений и генерирует одно на выходе.

Я уверен, что вы с успехом справитесь и сами, но в любом случае ответ ниже! Добавьте следующую строку в ваш плейграунд:


var evens = [Int]()
for i in 1...10 {
  if i % 2 == 0 {
    evens.append(i)
  }
}
 
var evenSum = 0
for i in evens {
  evenSum += i
}
 
print(evenSum)

В Assistant Editor будет следующий результат:


30

Императивный код, указанный выше, написан в том же ключе, что и код в предыдущем примере, с добавлением дополнительного цикла for-in.

Давайте посмотрим, как выглядит функциональный эквивалент!

Функциональная Reduce

Добавьте следующую строку в ваш плейграунд:


evenSum = Array(1...10)
    .filter { (number) in number % 2 == 0 }
    .reduce(0) { (total, number) in total + number }
 
print(evenSum)

Вы увидите точно такой же результат:


30

Предыдущий раздел охватывал создание массива и использование filter. Конечным результатом этих двух операций является массив с пятью числами [2, 4, 6, 8, 10]. Новым шагом в коде выше стало использование reduce.

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

Для того чтобы понять, как работает метод reduce, нужно посмотреть на его описание:


func reduce<U>(initial: U, combine: (U, T) -> U) -> U

Первый параметр — это начальное значение типа U. В вашем текущем коде, начальное значение равно 0, и имеет тип Int (следовательно, U это в данном случае Int). Второй аргумент — это функция combine, и она выполняется один раз для каждого элемента массива.

combine принимает два аргумента: первый, типа U, является результатом предыдущего вызова combine, второй — значением элемента массива, с которым он объединен. Результат, возвращаемый reduce,  это значение, возвращаемое последним вызовом combine.

Давайте разберем все шаг за шагом.

В вашем коде, первая итерация reduce приводит к следующему:

Сначала total имеет значение 0, а первый элемент входного массива равен 2. Если мы просуммируем эти значения, то на выходе (result) получится 2.

Вторая итерация показана ниже:

Во второй итерации, входное значение равно значению предыдущей итерации и следующего элемента из входного массива. Объединение их приводит к 2 + 4 = 6.

Продолжаем проделывать тоже самое для всех элементов массива, что приводит к следующим вводам и выводам:

Обозначенное звездочкой число в правом нижнем углу — общий результат.

Это довольно простой пример, на практике же вы можете выполнять любые виды интересных и сильных преобразований с reduce. Ниже приведены несколько простых примеров.

Добавьте следующую строку в ваш плейграунд:


let maxNumber = Array(1...10)
            .reduce(0) { (total, number) in max(total, number) }
print(maxNumber)

Этот код использует reduce, чтобы найти максимальное значение в массиве целых чисел. В этом случае результат весьма очевиден! Помните, что здесь total на самом деле просто максимальный результат max последней итерации reduce.

Если вы пытаетесь изо всех сил понять, как это работает, почему бы не создать еще одну таблицу, где вы вычислите вводы и выводы combine (т.е. замыкания) для каждой итерации?

Примеры, которые вы видели, все уменьшают массивы целых чисел до одиночных целочисленных значений. Конечно, у reduce есть два типа параметров, U и T и они могут быть разными, и, конечно, не должны быть интеджерами. Это означает, что вы можете уменьшить массив одного типа до совершенно другого типа.

Добавьте следующую строку в ваш плейграунд:


let numbers = Array(1...10)
  	.reduce("numbers: ") {(total, number) in total + "\(number) "}
print(numbers)

Это приводит к следующему выводу:


numbers: 1 2 3 4 5 6 7 8 9 10

Этот пример понижает массив целых чисел до строки, указанной выше.

Немного практики и вы будете использовать reduce по-всякому! 

Задача

Можете ли вы использовать reduce для того, чтобы преобразовать массив digits в целое число, если массив ввода такой:


let digits = ["3", "1", "4", "1"]

Ваш понижающий метод должен возвращать Int со значением 3141.

Магия Reduce

В предыдущем разделе, вы разработали свою собственную реализацию filter, что оказалось удивительно просто. Теперь вы увидите, что то же самое можно сделать и для reduce.

Добавьте следующий код в ваш плейграунд:


extension Array {
  func myReduce<T, U>(seed:U, combiner:(U, T) -> U) -> U {
    var current = seed
    for item in self {
      current = combiner(current, item as! T)
    }
    return current
  }
}

Код выше добавляет метод myReduce в Array, который имитирует встроенную функцию Array. Этот метод просто перебирает каждый элемента массива, вызывая на каждом этапе combiner.

Чтобы это проверить, замените один из методов reduce в вашем плейграунде на myReduce.

Вы, наверное, на этом этапе думаете о том, почему вам должно хотеться реализовать filter или reduce? Ответ: “А и не должно хотеться!”

Но тем не менее, вы можете захотеть расширить использование функциональной парадигмы в Swift и реализовать собственные функциональные методы. Видеть и понимать, насколько это легко реализовывать такие действенные методы, как reduce, очень важно и нужно.

Построение индекса

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

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

В новом плейграунде добавьте:


import Foundation
 
let words = ["Cat", "Chicken", "fish", "Dog",
                      "Mouse", "Guinea Pig", "monkey"]

Для выполнения задачи этого раздела, вам нужно сгруппировать эти слова по их первым буквам (без учета регистра!).

Добавьте следующее:


typealias Entry = (Character, [String])
 
func buildIndex(words: [String]) -> [Entry] {
  return [Entry]()
}
print(buildIndex(words))

typealias Entry определяет тип кортежа для каждой записи индекса. Использование typealias в этом примере делает код более удобным для чтения, устраняя необходимость повторно указать тип кортежа в полном объеме. Вам нужно добавить код, создающий индекс, в buildIndex.

Строим индекс императивно

Начнем с императивного подхода; обновите buildIndex следующим:


func buildIndex(words: [String]) -> [Entry] {
  var result = [Entry]()
  
  var letters = [Character]()
  for word in words {
    let firstLetter = Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString)
    
    if !letters.contains(firstLetter) {
      letters.append(firstLetter)
    }
  }
  
  for letter in letters {
    var wordsForLetter = [String]()
    for word in words {
      let firstLetter = Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString)
      
      if firstLetter == letter {
        wordsForLetter.append(word)
      }
    }
    result.append((letter, wordsForLetter))
  }
  return result
}

У этой функции две части, у каждой части свой собственный цикл for. Первая половина перебирает слова, чтобы построить массив букв; вторая перебирает эти буквы, находя слова, которые начинаются с нужной буквы, чтобы построить обратный массив.

После реализации, вы увидите желаемый результат:


[("C", ["Cat", "Chicken"]), 
 ("F", ["fish"]), 
 ("D", ["Dog"]), 
 ("M", ["Mouse", "monkey"]), 
 ("G", ["Guinea Pig"])]

(Текст выше немного отформатирован для ясности.)

У этой императивной реализации довольно много шагов и вложенных циклов, от этого возникают сложности понимания. Давайте посмотрим, как выглядит функциональный эквивалент.

Создание индекса функциональным путем

Создайте новый файл в плейграунде и добавьте ту же первоначальную структуру:


import Foundation

let words = ["Cat", "Chicken", "fish", "Dog",
             "Mouse", "Guinea Pig", "monkey"]

typealias Entry = (Character, [String])

func buildIndex(words: [String]) -> [Entry] {
  return [Entry]()
}

print(buildIndex(words))

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


[]

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


func buildIndex(words: [String]) -> [Entry] {
  let letters = words.map {
    (word) -> Character in
    Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString)
    
  }
  print(letters)
  
  return [Entry]()
}

Плейграунд в настоящее время выводит массив букв верхнего регистра, каждой букве соответствует слово в вводном массиве.


[C, C, F, D, M, G, M]

В предыдущих разделах, вы столкнулись с filter и reduce. Приведенный выше код представляет map, другой функциональный метод, являющийся частью API массива.

map создает новый массив с результатами вызовов прилагаемого замыкания для каждого элемента в каждом массиве. Вы можете использовать map для выполнения преобразований. В этом случае map преобразует массив типа [String] в массив типа [Character].

Сейчас массив букв содержит дубликаты, а у нужного вам индекса должно быть только одно вхождение каждой буквы. К сожалению, у типа массива в Swift нет метода дедупликации. Это то, что вам нужно написать самим!

В предыдущих разделах мы видели, что повторно реализовать reduce и filter легко. Добавление метода дедупликации также не должно вызвать сложности.

Добавьте следующую функцию в вашем плейграунде перед buildIndex:


func distinct<T: Equatable>(source: [T]) -> [T] {
  var unique = [T]()
  for item in source {
    if !unique.contains(item) {
      unique.append(item)
    }
  }
  return unique
}

При построении нового массива, содержащего только уникальные элементы, distinct перебирает все элементы массива.

Обновите buildIndex, чтобы привести в работу distinct:


func buildIndex(words: [String]) -> [Entry] {
  let letters = words.map {
    (word) -> Character in
    Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString)
    
  }
  let distinctLetters = distinct(letters)
  print(distinctLetters)
  
  return [Entry]()
}

Ваша плейграунд теперь будет выводить уникальные буквы:


[C, F, D, M, G]

Теперь, когда у вас есть массив различных букв, следующей задачей в создании индекса, будет преобразование каждой буквы в экземпляр Entry. Не звучит как преобразование? Еще одна работа для map!

Обновите buildIndex следующим образом:


func buildIndex(words: [String]) -> [Entry] {
  let letters = words.map {
    (word) -> Character in
    Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString)
    
  }
  let distinctLetters = distinct(letters)
  return distinctLetters.map {
    (letter) -> Entry in
    return (letter, [])
  }
}

Второй вызов map принимает массив символов и выводит массив экземпляров Entry:


[(C, []), 

 (F, []), 

 (D, []), 

 (M, []), 

 (G, [])]

(Опять же, текст выше для ясности отформатирован.)

Вы на финишной прямой. Заключительная задача состоит в том, чтобы заполнить каждый экземпляр ввода словами, которые начинаются с данной буквы. Обновите функцию для добавления вложенного filter, следующим образом:


func buildIndex(words: [String]) -> [Entry] {
  let letters = words.map {
    (word) -> Character in
    Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString)
    
  }
  
  let distinctLetters = distinct(letters)
  return distinctLetters.map {
    (letter) -> Entry in
    
    return (letter, words.filter {
        (word) -> Bool in
      Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString) == letter
  
      })
  }
}

Это даст вам желаемый результат:


[(C, [Cat, Chicken]),

 (F, [fish]),

 (D, [Dog]),

 (M, [Mouse, monkey]),

 (G, [Guinea Pig])]

Во второй половине функции теперь есть вложенный вызов для filter внутри map. Он отфильтрует список слов для каждой отдельной буквы, и, таким образом, опередит те слова, которые начинаются с нужной буквы.

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

Если бы это был код на Objective-C, у вас было бы несколько вариантов: Вы могли бы создать метод, который бы выполнял эту функцию  или, возможно, вы могли бы добавить этот метод непосредственно к NSString через категорию класса. Тем не менее, если вам нужно выполнить эту задачу в рамках buildIndex, то в служебном методе не достаточно смысловой ясности и использование категории класса будет излишним.

К счастью, Swift предлагает отличный вариант!

Обновите buildIndex следующим:


func buildIndex(words: [String]) -> [Entry] {
  func firstLetter(str: String) -> Character {
    return Character(str.substringToIndex(str.startIndex.advancedBy(1)).uppercaseString)
  }
  
  let letters = words.map {
    (word) -> Character in
    Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString)
    
  }
  
  
  return distinct(words.map(firstLetter))
    .map {
      (letter) -> Entry in
      
      return (letter, words.filter {
        (word) -> Bool in
        Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString) == letter
        })
  }
}

Вы увидите точно такой же результат, как видели и раньше.

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

Новый код удаляет дублирование, но вы можете сделать еще больше, чтобы очистить buildIndex.

Первый шаг map, направленный на построение массива букв, принимает замыкание, тип которого (String) -> Character. Вы можете заметить, что этот тип точно такой же, как у функции firstLetter, которую вы только что добавили, что означает, что вы можете передать ее непосредственно на map.

Используя эти знания, вы можете переписать функцию следующим образом:


func buildIndex(words: [String]) -> [Entry] {
  func firstLetter(str: String) -> Character {
    return Character(str.substringToIndex(str.startIndex.advancedBy(1)).uppercaseString)
  }
  
  
  return distinct(words.map(firstLetter))
    .map {
      (letter) -> Entry in
      
      return (letter, words.filter {
        (word) -> Bool in
        Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString) == letter
        })
  }
}

Конечный результат краткий, но весьма выразительный.

Возможно, вы заметили интересный побочный эффект функциональных методов, которые вы до сих пор использовали. В то время как ваши императивные решения полагались на переменные (с использованием ключевого слова var), то все функциональные эквиваленты вы определяли как константы (через let).

Вы должны стремиться к неизменности. Неизменные типы легче тестировать и использовать параллелизм. Функциональное программирование и неизменные типы, как правило, идут рука об руку. В результате, ваш код будет более кратким, а также менее подвержен ошибкам. Он будет круто выглядеть и произведет впечатление на ваших друзей!

Заметка

Сейчас buildIndex возвращает неотсортированный индекс; порядок экземпляров Entry зависит от порядка слов в вводном массиве. Ваша задача состоит в том, чтобы отсортировать индекс в алфавитном порядке. Для примера массив строк, то это дало бы следующий вывод:


[(C, [Cat, Chicken]),
 (D, [Dog]),
 (F, [fish]),
 (G, [Guinea Pig]),
 (M, [Mouse, monkey])]
Подсказка:

Тип массива в Swift имеет метод sort, но этот метод изменяет массив, а не возвращает новый, отсортированный экземпляр. Для работы он требует изменяемый массив. В общем, безопаснее иметь дело с неизменяемыми данными, поэтому я бы не советовал этот метод! В качестве альтернативы, использовать метод сортировки, который возвращает второй отсортированный массив.

Что дальше?

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

Урок подготовил: Акулов Иван

Источник урока: Источник

12 книг для изучения языка программирования Swift

Темой этой статьи стал язык Swift. На нем написаны приложения для iOS и macOS. Язык достаточно молод и литературу на него не так просто найти, — пишет KV.BY. Причиной малого количества книг стало и то, что официальная электронная литература от разработчиков очень подробная и доступная для понимания. Часть книг из перечня только на английском языке. Русской литературы, к сожалению, очень немного. Поэтому, исходя из этого, статья будет поделена на русские и английские издания.

Swift. Основы разработки приложений под iOS и macOS

Отличная книга для старта освоения языка Swift. Её написал русский программист, пошагово разжевывая все нюансы работы с языком. Постепенно автор подведёт вас к непосредственному созданию приложений для яблочной продукции. Книга описывает работу Swift 3.0, что очень хорошо, так как про эту версию русскоязычных изданий немного.

Отзывы о книге хорошие. Придраться можно лишь к тому, что использовать её как базовый справочник неудобно, и некоторые аспекты рассмотрены поверхностно.

Язык Swift. Самоучитель

Здесь рассмотрена теория. Разбор качественный, глубокий. Первая часть книги рассказывает о синтаксисе, типах данных, операторах и прочих тонкостях, а вторая бегло проносится по остальным моментам (классы, структуры, протоколы), частично захватывая ООП. А вот практических заданий и примеров совсем мало.

Хороший вариант настольного справочника под рукой. Но есть несколько минусов: описана работа Swift 2.0,а значит, часть приемов не работают в версии 3.0.

Swift 3

Разработка приложений в среде Xcode для iPhone и iPad с использованием iOS SDK

Книга внушает уважение с первого взгляда: 900 страниц – это серьёзное заявление. Исходя из этого, диапазон тем очень широкий. Авторы грамотно сочетают теорию с практикой, чтобы эффективно усваивать новые знания. Перевод местами не очень понятен, но это сильно не влияет на усвояемость материала.

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

Swift для детей

Издание для начинающих программистов. Автор труда максимально подробно и последовательно описывает процесс создания приложений для iOS. Обратная сторона медали – много лишнего текста. Но для того, чтобы постигнуть азы языка – то, что надо. 

Swift. Карманный справочник. Программирование в среде iOS и ОS X

А вот книга от O’Reilly. Компания очень известная и серьёзная. Всё примеры рабочие, серьёзных огрехов нет, все скриншоты на местах. Единственный недостаток – в качестве основы использовалась версия языка 2.1.

Swift. Основы разработки приложений под iOS и OS X

Название говорит за себя: она введёт вас в основы программирования для продукции компании Apple. Причём для любой платформы: iOS, OS X, tvOS, watchOS. Опытным программистам ждать от этого пособия нечего, а вот новичкам оно должно понравится. Автор грамотно комбинирует практику с теорией, что отлично работает.

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

Professional Swift

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

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

Learning Swift: Building Apps for macOS, iOS, and Beyond

Перед вами практическое руководство от опытных программистов, которое научит кодить на последней версии Swift, даже если вы совсем не знакомы с этим языком. Книга пройдёт по всем этапам создания своего приложения. Вы узнаете основы языка, как работать с Xcode и Interface Builder.

Авторы книги предлагают вам создать свою программу для работы с селфи. Кроме написания самого кода вы протестируете приложение на производительность, произведёте его настройку и будете управлять им в App Store. Также вы узнаете об автоматизации рутинных операций с Fastlane и пользовательском тестировании приложения с TestFlight.

Swift For Dummies

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

Swift Programming: The Big Nerd Ranch Guide (2nd Edition) (Big Nerd Ranch Guides)

Авторы этого справочника тщательно объясняют на примерах грамматику и эффективное написание кода на Swift. В книге рассмотрены версия 3.0, работа с Xcode, объяснены некоторые моменты официальной документации от Apple по Swift. Создатели этого труда делятся с читателем своим опытом, показывая области применения этого языка.

Mastering Swift 5: Deep dive into the latest edition of the Swift programming language, 5th Edition

Книга про пятую версию языка. Здесь рассмотрены самые актуальные и новые возможности Swift, новые методы проектирования. Всё это описано не только теоретически, но и подкреплено наглядными примерами. Здесь раскрыты темы расширения протокола, обработка ошибок и замыкание. Объяснения авторов продемонстрируют, как использовать и применять их в ваших собственных проектах.

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

Swift: The Complete Guide for Beginners,Intermediate and Advanced Detailed Strategies To Master Swift Programming

Это целая серия книг, которая охватывает любой уровень подготовки программиста. Независимо от навыков, авторы проведут вас через все этапы создания приложения для техники компании Apple. Книга познакомит вас с языком, вы найдёте здесь пошаговую инструкцию для написания ПО, примеры проектов из XCode, узнаете о дизайне и прочие полезные вещи.

О языке Swift — SwiftBook

Заметка

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

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

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

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

  • Переменные всегда инициализированы до того, как будут использованы.
  • Индексы массивов всегда проверяются на out-of-bounds ошибки.
  • Целые числа проверяются на переполнение.
  • Опционалы гарантируют, что значения nil будут явно обработаны.
  • Автоматическое управление памятью
  • Обработка ошибок позволяет осуществлять контролируемое восстановление от непредвиденных ошибок.

Код на Swift скомпилирован и оптимизирован, чтобы получать максимальную отдачу от современного оборудования. Синтаксис стандартной библиотеки спроектирован основываясь на руководстве, что самый очевидный и простой способ написания кода является лучшим вариантом. Комбинация безопасности и скорости делает Swift лучшим кандидатом для написания программ от уровня «Hello, World!» и до целой операционной системы.

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

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

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Swift | Введение

Язык Swift и платформы iOS и Mac OS

Последнее обновление: 25.12.2017

Устройства компании Apple являются признанным лидером в сфере информационных технологий. По последним данным доля iOS среди других мобильных операционных систем
колеблется в районе 15-20%, а доля Mac OSX среди настольных систем составляет по разным данным 15-20%. Подобное широкое распространение устройств от компании Apple рождает потребность в программном обеспечении для этих устройств.

Традиционно основным языком программирования под iOS и MacOS был Objective-C, однако 2 июня 2014 года на конференции разработчиков Apple WWDC 2014 был представлен новый и более удобный язык программирования — Swift. По сравнению с Objective-C Swift обладает следующими особенностями:

  • Swift является чистым объектно-ориентированным языком программирования

  • Простота, ясный и четкий синтаксис

  • Строгая типизированность. Каждая переменная имеет определенный тип

  • Автоматическое управление памятью

Однако при этом Swift полностью совместим с ранее написанными прикладными интерфейсами Cocoa API, для которых использовались C и Objective-C.

При этом Swift продолжает развиваться. 19 сентября 2017 года вышла версия 4.0, которая добавила новые возможности для разработки под iOS и Mac OS. В принципе каждый год выходят новые версии.

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

Что нужно для разработки для iOS?

В первую очередь необходима соответствующая операционная система Mac OS 10.12 Yosemite или выше. Без Mac OS практически невозможно скомпилировать программу. Данное обстоятельство сильно ограничивает возможности разработки, учитывая тот факт, что Mac OS может гарантированно работать лишь на компьютерах
самой компании Apple (iMac, MacBook, MacBook Air, MacBook Pro), а также учитывая высокую стоимость этих самых компьютеров. Однако на обычном PC под управлением ОС Windows или ОС на базе
Linux создавать приложения под iOS и Mac OS практически невозможно.

Существуют также варианты с виртуальными машинами, на которые установлена Mac OS, либо использование Хакинтош, однако работоспособность подобных вариантов не гарантирована.

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

Непосредственно для самой разработки нам потребуются инструменты языка Swift, текстовый редактор для написания кода, симуляторы iPhone и iPad для отладки приложения.
Для всех этих и многих других функций разработки Apple предоставляет бесплатную среду разработки XCode.

Нужны ли реальные устройства iPhone или iPad для тестирования разрабатываемых приложений? По большому счету нет, так как XCode предоставляет симуляторы для тестирования,
однако в некоторых отдельных случаях предпочтительнее тестировать на реальном смартфоне.

Регистрация разработчика

И также непосредственно перед тем, как приступить к созданию приложений, необходимо зарегистрироваться в центре Apple для разработчиков. Для этого надо пройти
по ссылке https://developer.apple.com/register/:

Для регистрации надо будет войти на сайт с помощью своего идентификатора Apple ID и пароля. Если вдруг такого идентификатора у вас нет, то можно создать новую учетную запись,
перейдя по ссылке Create Apple ID. После регистрации сайт перенаправит на страницу https://developer.apple.com/resources/,
где можно найти различные материалы по разработке для самых разных аспектов.

Swift.org — Документация

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

Язык быстрого программирования

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

Вы также можете загрузить последнюю версию в формате ePub по лицензии Creative Commons Attribution 4.0 International (CC BY 4.0).

Переводы

Мы призываем вас принять участие в переводе The Swift Programming Language на другие языки.
Примите участие в существующем переводческом проекте или начните новый, если в этом возникнет необходимость.
Отличный пример — язык программирования Swift (перевод на китайский язык, проект GitHub).

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

Менеджер пакетов Swift

Swift Package Manager — это инструмент для управления распространением кода Swift.
Он интегрирован с системой сборки Swift для автоматизации процесса
загрузка, компиляция и связывание зависимостей. Манифест диспетчера пакетов
Документация по API доступна здесь.

Руководство по проектированию API

Цель Swift состоит в том, чтобы код разделял единый стандарт для программистов.
пользовательский опыт, большая часть которого определяется именами и идиомами, которые появляются
в API. Эти рекомендации по дизайну объясняют, как
убедитесь, что ваш код ощущается как часть более крупной экосистемы Swift.

Руководства по миграции

Xcode включает инструмент Swift Migrator, который поможет вам перенести ваш проект на последнюю версию Swift,
или обновите его для работы с последними SDK.

.

Swift.org — Начало работы

Здесь вы найдете информацию о том, как использовать язык программирования Swift.

Если вы новичок в Swift, ознакомьтесь с A Swift Tour в
The Swift Programming Language , для быстрого знакомства с
наиболее важные понятия и особенности языка.

Установка Swift

Первым шагом к использованию Swift является загрузка и установка
компилятор и другие необходимые компоненты.
Перейти на страницу загрузки
и следуйте инструкциям для вашей целевой платформы.

Чтобы следовать приведенным ниже примерам,
не забудьте добавить Swift в свой $ PATH .

В macOS

Расположение по умолчанию для загружаемой цепочки инструментов в macOS:
/ Библиотека / Разработчик / Toolchains .
Вы можете сделать последнюю установленную цепочку инструментов доступной для использования из терминала с помощью следующей команды:

  $ экспорт TOOLCHAINS = swift
  

Чтобы выбрать любой другой установленный набор инструментов, используйте его идентификатор в TOOLCHAINS .
переменная.Идентификатор можно найти в файле Info.plist toolchain.

  $ / usr / libexec / PlistBuddy -c "Распечатать CFBundleIdentifier:" /Library/Developer/Toolchains/swift-4.0-RELEASE.xctoolchain/Info.plist
org.swift.4020170919

$ export TOOLCHAINS = org.swift.4020170919
  

в Linux

  1. Установить необходимые зависимости:
Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04 CentOS 7 CentOS 8 Amazon Linux 2
  $ apt-get install \
          binutils \
          мерзавец \
          libc6-dev \
          libcurl3 \
          libedit2 \
          libgcc-5-dev \
          libpython2.7 \
          libsqlite3-0 \
          libstdc ++ - 5-разработчик \
          libxml2 \
          pkg-config \
          tzdata \
          zlib1g-dev  
  $ apt-get install \
          binutils \
          мерзавец \
          libc6-dev \
          libcurl4 \
          libedit2 \
          libgcc-5-dev \
          libpython2.7 \
          libsqlite3-0 \
          libstdc ++ - 5-разработчик \
          libxml2 \
          pkg-config \
          tzdata \
          zlib1g-dev  
  $ apt-get install \
          binutils \
          мерзавец \
          gnupg2 \
          libc6-dev \
          libcurl4 \
          libedit2 \
          libgcc-9-dev \
          libpython2.7 \
          libsqlite3-0 \
          libstdc ++ - 9-разработчик \
          libxml2 \
          libz3-dev \
          pkg-config \
          tzdata \
          zlib1g-dev  
  $ yum install \
      binutils \
      gcc \
      мерзавец \
      glibc-static \
      libbsd-devel \
      libedit \
      libedit-devel \
      libicu-devel \
      libstdc ++ - статический \
      pkg-config \
      python2 \
      sqlite

      # __block конфликтует с квалификатором __block clang
      sed -i -e 's / \ * __ блок / \ * __ libc_block / g' / usr / include / unistd.в  
  $ yum install \
      binutils \
      gcc \
      мерзавец \
      glibc-static \
      libbsd-devel \
      libedit \
      libedit-devel \
      libicu-devel \
      libstdc ++ - статический \
      pkg-config \
      python2 \
      sqlite  
  $ yum install \
      binutils \
      gcc \
      мерзавец \
      glibc-static \
      gzip \
      libbsd \
      libcurl \
      libedit \
      libicu \
      libsqlite \
      libstdc ++ - статический \
      libuuid \
      libxml2 \
      смола \
      tzdata  

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

  $ export PATH = / путь / к / Swift / usr / bin: "$ {PATH}"
  

в Windows

Visual Studio и Swift

Вам нужно будет установить оба установщика инструментальной цепочки из
Страница загрузки и Visual Studio 2019.

Требуются следующие компоненты Visual Studio :

Компонент Visual Studio ID
MSVC v142 — VS 2019 C ++ x64 / x86 инструменты сборки (v14.25) 1 Microsoft.VisualStudio.Component.VC.Tools.x86.x64
Универсальная среда выполнения Windows C Microsoft.VisualStudio.Component.Windows10SDK
Windows 10 SDK (10.0,17763,0) 2 Microsoft.VisualStudio.Component.Windows10SDK.17763

1 Вы можете установить более новый набор инструментов сборки.
2 Вместо этого вы можете установить более новый SDK.

Следующие дополнительные компоненты Visual Studio рекомендуются :

Компонент Visual Studio ID
Инструменты C ++ CMake для Windows Microsoft.VisualStudio.Component.VC.CMake.Project
Git для Windows Microsoft.VisualStudio.Component.Git
Python 3 64-разрядная (3.7.8) Component.CPython.x64

Расположение по умолчанию для установки набора инструментов в Windows:
% SystemDrive% \ Library \ Developer \ Toolchains .

Файлы поддержки

Обратите внимание, что для запуска необходимо использовать собственные инструменты x64 для командной строки VS2019
набор инструментов.Собственные инструменты x64 для командной строки VS2019 запускает
DevEnv скрипт из Visual Studio, который настраивает необходимую среду
переменные, чтобы найти системные заголовки.

Чтобы сделать Windows SDK доступным для Swift, необходимо развернуть
несколько файлов в Windows SDK. Следующее изменит вашу Visual Studio
Установка, и, как таковая, потребуется запускать из (повышенного)
«Администратор» Родные инструменты x86 для командной строки VS2019 .

  копировать% SDKROOT% \ usr \ share \ ucrt.modulemap "% UniversalCRTSdkDir% \ Include \% UCRTVersion% \ ucrt \ module.modulemap"
скопируйте% SDKROOT% \ usr \ share \ visualc.modulemap "% VCToolsInstallDir% \ include \ module.modulemap"
скопируйте% SDKROOT% \ usr \ share \ visualc.apinotes "% VCToolsInstallDir% \ include \ visualc.apinotes"
скопируйте% SDKROOT% \ usr \ share \ winsdk.modulemap "% UniversalCRTSdkDir% \ Include \% UCRTVersion% \ um \ module.modulemap"
  

Поскольку файлы устанавливаются в образ Visual Studio, файлы будут
необходимо копировать каждый раз при обновлении Visual Studio.


Версия Swift

Вы можете убедиться, что используете ожидаемую версию Swift.
введя команду swift и передав флаг --version :

  $ swift - версия
Apple Swift версии 2.2-dev (LLVM ..., Clang ..., Swift ...)
  

Суффикс -dev в номере версии
используется, чтобы указать, что это сборка development ,
не выпущенная версия.

Использование REPL

Если вы запустите команду swift без других аргументов,
вы запустите REPL, интерактивную оболочку
который прочитает, оценит и распечатает результаты
любого введенного кода Swift.

  $ swift
Добро пожаловать в Apple Swift версии 2.2. Тип: help для получения помощи.
  1>
  

Взаимодействие с REPL — отличный способ поэкспериментировать со Swift.
Например, если вы введете выражение 1 + 2 ,
результат выражения 3 печатается в следующей строке:

Вы можете присвоить значения константам и переменным,
и используйте их в последующих строках.
Например, String value Hello, world!
можно присвоить константе приветствие ,
а затем передается в качестве аргумента функции print (_ :) :

  2> let приветствие = "Привет!"
приветствие: String = "Привет!"
  3> печать (приветствие)
Здравствуйте!
  

Если вы введете неверное выражение,
REPL выведет сообщение об ошибке, указав, где возникла проблема:

  let answer = "сорок" - "два"
ошибка: двоичный оператор '-' нельзя применить к двум операндам типа String
let answer = "сорок" - "два"
             ~~~~~~~ ^ ~~~~~
  

Вы можете использовать клавиши со стрелками вверх и вниз ( и )
для циклического просмотра предыдущих строк, введенных в REPL.Это позволяет вам немного изменить предыдущее выражение
без повторного набора всей строки,
и особенно удобен для исправления ошибок, подобных предыдущей:

  let answer = "сорок два"
ответ: String = "сорок два"
  

Еще одна полезная функция REPL
в том, что он может автоматически предлагать функции и методы
которые можно использовать в конкретном контексте.
Например, если вы введете вместо
после оператора точки в значении String
а затем нажмите клавишу табуляции (),
REPL выдаст список доступных доработок
например remove (at :) и replaceSubrange (bounds: with :) :

  5> «Привет!».re⇥
Доступные доработки:
удалить (в: Индекс) -> Символ
removeAll () -> Пустота
removeAll (keepCapacity: Bool) -> Пустота
removeSubrange (границы: ClosedRange ) -> Пустота
removeSubrange (bounds: Range ) -> Пустота
replaceSubrange (границы: ClosedRange , с: C) -> Void
replaceSubrange (границы: ClosedRange , с: String) -> Void
replaceSubrange (bounds: Range , with: C) -> Void
replaceSubrange (bounds: Range , with: String) -> Void
ReserveCapacity (n: Int) -> Void
  

Если вы запускаете блок кода,
например, при итерации по массиву с циклом for-in ,
REPL автоматически сделает отступ для следующей строки,
и измените символ приглашения с > на .
чтобы указать, что код введен в эту строку
будет оцениваться только тогда, когда оценивается весь блок кода.

  6> пусть числа = [1,2,3]
числа: [Int] = 3 значения {
  [0] = 1
  [1] = 2
  [2] = 3
}
  7> для n в числах.reversed () {
  8. print (n)
  9.}
3
2
1
  

Вся функциональность Swift доступна вам из REPL,
от написания операторов потока управления
для объявления и создания экземпляров структур и классов.

Вы также можете импортировать любые доступные системные модули,
например Darwin в macOS и Glibc в Linux:

В macOS

  1> импорт Дарвин
2> arc4random_uniform (10)
$ R0: UInt32 = 4
  

в Linux

  1> импорт Glibc
2> случайный ()% 10
$ R0: Int32 = 4
  

в Windows

REPL зависит от привязок Python.Вы должны убедиться, что Python доступен
в пути. Следующая команда добавляет Python в PATH, чтобы его можно было
используемый:

  путь% ProgramFiles (x86)% \ Microsoft Visual Studio \ Shared \ Python37_64;% PATH%
  

Поскольку установка Windows отделяет SDK от инструментальной цепочки, несколько
в REPL должны быть переданы дополнительные параметры. Это позволяет использовать несколько
разные SDK с одним и тем же набором инструментов.

  установить SWIFTFLAGS = -sdk% SDKROOT% -I% SDKROOT% / usr / lib / swift -L SDKROOT% / usr / lib / swift / windows
swift repl -target x86_64-unknown-windows-msvc% SWIFTFLAGS%
  

Использование диспетчера пакетов

Менеджер пакетов Swift предоставляет систему на основе соглашений для
создание библиотек и исполняемых файлов, а также совместное использование кода в разных пакетах.

В этих примерах предполагается, что вы сделали swift доступным на своем пути;
см. Установка для получения дополнительной информации.
Когда они станут доступны, вы можете вызвать инструменты диспетчера пакетов: swift package , swift run , swift build и swift test .

  $ быстрый пакет - справка
ОБЗОР: выполнение операций с пакетами Swift
...
  

Создание пакета

Чтобы создать новый пакет Swift, сначала создайте и войдите в каталог с именем Hello :

Каждый пакет должен иметь файл манифеста с именем Package.swift в корневом каталоге.
Вы можете создать минимальный пакет с именем Hello , используя:

По умолчанию команда init создает структуру каталогов пакета библиотеки:

  ├── Package.swift
├── README.md
├── Источники
│ └── Привет
│ └── Привет. Swift
└── Тесты
    ├── HelloTests
    │ └── HelloTests.swift
    └── LinuxMain.swift
  

Для сборки пакета можно использовать swift build . Это загрузит, разрешит и скомпилирует упомянутые зависимости.
в файле манифеста Package.Сибирский .

  $ быстрая сборка
Скомпилируйте модуль Swift 'Hello' (1 исходный код)
  

Чтобы запустить тесты для пакета, используйте: swift test

  $ быстрый тест
Скомпилируйте модуль Swift 'HelloTests' (1 источник)
Связывание ./.build/x86_64-apple-macosx10.10/debug/HelloPackageTests.xctest/Contents/MacOS/HelloPackageTests
Набор тестов «Все тесты» начат в 2016-08-29 08: 00: 31.453
Набор тестов HelloPackageTests.xctest начат в 2016-08-29 08: 00: 31.454
Тестовый пакет HelloTests запущен в 2016-08-29 08:00:31.454
Тестовый пример '- [HelloTests.HelloTests testExample]' запущен.
Тестовый пример «- [HelloTests.HelloTests testExample]» пройден (0,001 секунды).
Набор тестов HelloTests пройден в 2016-08-29 08: 00: 31.455.
Выполнен 1 тест с 0 сбоями (0 непредвиденных) в 0,001  

.

Swift.org — О Swift

Swift — это язык программирования общего назначения, созданный с использованием современного подхода к безопасности, производительности и шаблонам проектирования программного обеспечения.

Целью проекта Swift является создание наилучшего доступного языка для использования в самых разных областях — от системного программирования до мобильных и настольных приложений и масштабирования до облачных сервисов. Самое главное, Swift разработан, чтобы упростить для разработчика написание и поддержку правильных программ . Мы считаем, что для достижения этой цели наиболее очевидным способом написания кода Swift также должен быть:

Сейф. Самый очевидный способ написания кода также должен вести себя безопасным образом. Неопределенное поведение — враг безопасности, и ошибки разработчика должны быть обнаружены до того, как программное обеспечение будет запущено в производство. Выбор безопасности иногда означает, что Swift будет чувствовать себя строгим, но мы считаем, что ясность экономит время в долгосрочной перспективе.

Быстро. Swift предназначен для замены языков на основе C (C, C ++ и Objective-C). Таким образом, Swift должен быть сопоставим с этими языками по производительности для большинства задач.Производительность также должна быть предсказуемой и стабильной, а не только быстрой короткими сериями, которые позже требуют очистки. Есть много языков с новыми функциями — быстрота — редкость.

Выразительный. Swift извлекает выгоду из десятилетий развития информатики, предлагая синтаксис, который приятно использовать, с современными функциями, ожидаемыми разработчиками. Но Swift никогда не заканчивается. Мы будем следить за развитием языка и принимать то, что работает, постоянно совершенствуясь, чтобы сделать Swift еще лучше.

Инструменты являются важной частью экосистемы Swift. Мы стремимся хорошо интегрироваться в набор инструментов разработчика, быстро создавать, предоставлять отличную диагностику и обеспечивать интерактивные возможности разработки. Инструменты могут сделать программирование намного более мощным, как игровые площадки на основе Swift в Xcode или веб-REPL при работе с серверным кодом Linux.

Характеристики

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

Функции Swift разработаны для совместной работы, чтобы создать мощный, но увлекательный в использовании язык.Некоторые дополнительные функции Swift включают:

  • Замыкания унифицированы с указателями функций
  • Кортежи и несколько возвращаемых значений
  • Универсальные
  • Быстрая и лаконичная итерация по диапазону или коллекции
  • Структуры, поддерживающие методы, расширения и протоколы
  • Шаблоны функционального программирования, например, карта и фильтр
  • Встроенная мощная обработка ошибок
  • Расширенный поток управления с до , охранник , отложить и повторять ключевых слов

Безопасность

Swift с самого начала разрабатывался как более безопасный, чем языки на основе C, и исключает целые классы небезопасного кода.Переменные всегда инициализируются перед использованием, массивы и целые числа проверяются на переполнение, а память управляется автоматически. Синтаксис настроен так, чтобы упростить определение вашего намерения — например, простые трехсимвольные ключевые слова определяют переменную ( var ) или константу ( let ).

Другая функция безопасности заключается в том, что по умолчанию объекты Swift никогда не могут быть nil , и попытка создать или использовать объект nil приведет к ошибке во время компиляции. Это делает написание кода намного чище и безопаснее, а также предотвращает частую причину сбоев во время выполнения.Однако бывают случаи, когда подходит nil , и для этих ситуаций Swift имеет инновационную функцию, известную как optionals . Необязательный параметр может содержать nil , но синтаксис Swift заставляет вас безопасно работать с ним, используя ? , чтобы указать компилятору, что вы понимаете поведение и будете обрабатывать его безопасно.

Swift.org и открытый исходный код

3 декабря 2015 г. язык Swift, вспомогательные библиотеки, отладчик и диспетчер пакетов были опубликованы под Apache 2.0 с исключением библиотеки времени выполнения, и Swift.org был создан для размещения проекта. Исходный код размещен на GitHub, где любой может легко получить код, собрать его самостоятельно и даже создать запросы на вытягивание, чтобы вернуть код обратно в проект. Приглашаются все желающие, даже если они просто отправят отчет об ошибке. Здесь, на сайте, также есть отличные руководства по началу работы.

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

Проектов

Язык Swift управляется как набор проектов, каждый со своими собственными репозиториями. Текущий список проектов включает:

Поддержка платформы

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

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

Проект основных библиотек Swift направлен на
расширить кроссплатформенные возможности Swift, предоставив портативные
реализации фундаментальных фреймворков Apple (таких как Foundation)
без зависимости от среды выполнения Objective-C.Хотя ядро
библиотеки находятся на ранней стадии разработки, со временем они будут
обеспечить улучшенную совместимость исходного кода для кода Swift во всех
платформы.

Платформы Apple

Swift с открытым исходным кодом можно использовать на Mac для работы со всеми Apple
платформы: iOS, macOS, watchOS и tvOS. Более того, бинарные сборки
Swift с открытым исходным кодом интегрируется с инструментами разработчика Xcode, включая
полная поддержка системы сборки Xcode, автозавершение кода в
редактор и интегрированная отладка, позволяющая любому экспериментировать с
последние разработки Swift в знакомом нам какао и какао Touch
среда разработки.

Linux

Swift с открытым исходным кодом можно использовать в Linux для создания библиотек Swift и
Приложения. Бинарные сборки с открытым исходным кодом предоставляют компилятор Swift и стандартную библиотеку, Swift REPL и отладчик (LLDB), а также основные библиотеки, поэтому можно сразу перейти к разработке Swift.

Новые платформы

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

.

О Swift — язык программирования Swift (Swift 5.3)

Swift — отличный способ писать программное обеспечение, будь то для телефонов, настольных компьютеров, серверов или чего-либо еще, что запускает код. Это безопасный, быстрый и интерактивный язык программирования, который сочетает в себе лучшее из современного языкового мышления с мудростью более широкой инженерной культуры Apple и разнообразным вкладом сообщества разработчиков ПО с открытым исходным кодом. Компилятор оптимизирован для производительности, а язык оптимизирован для разработки без ущерба для производительности.

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

Swift определяет большие классы распространенных ошибок программирования, принимая современные шаблоны программирования:

  • Переменные всегда инициализируются перед использованием.
  • Индексы массива проверяются на наличие ошибок, выходящих за границы.
  • Целые числа проверяются на переполнение.
  • Опции обеспечивают явную обработку значений nil .
  • Память управляется автоматически.
  • Обработка ошибок позволяет контролировать восстановление после неожиданных сбоев.

Код Swift скомпилирован и оптимизирован для получения максимальной отдачи от современного оборудования. Синтаксис и стандартная библиотека были разработаны на основе руководящего принципа, согласно которому очевидный способ написания кода также должен работать наилучшим образом.Сочетание безопасности и скорости делает Swift отличным выбором для всего, начиная с «Hello, world!» ко всей операционной системе.

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

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

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *