Хоча Swift надає багато функціональності у своїй стандартній бібліотеці, багато додаткових можливостей можна отримати, імпортуючи зовнішні бібліотеки та фреймворки. Ці модулі можуть походити безпосередньо від проєкту Swift (як-от Swift Argument Parser), від фреймворків платформи Apple (як-от Foundation і Network Framework) або від сторонніх бібліотек з відкритим кодом (як-от SwiftyBeaver).
Основні модулі, як-от Foundation, одна з найуживаніших бібліотек у Swift, входять до складу інструментарію Swift. Сторонні бібліотеки потрібно додати до конфігурації проєкту (наприклад, скориставшись Swift Package Manager), перш ніж їх можна буде імпортувати.
Імпортування модулів відбувається так: пишемо ключове слово import, а потім назву модуля.
Тож щоб імпортувати Foundation, достатньо додати до своєї програми таке.
import Foundation
Імпортування модуля робить його типи, методи й функції доступними для нашого коду.
Наприклад, імпорт Foundation розширює String корисними допоміжними методами, як-от components(separatedBy:).
За домовленістю інструкції import ставлять на початку файлу Swift, щоб залежності було відразу видно кожному, хто читає код.
Окремі символи в String можна отримати тим самим способом індексування, який використовують для масивів.
Однак індекси, які використовують для рядків тексту (англ. string), не є цілими числами, і працювати з ними безпосередньо не можна.
Замість цього їх потрібно обчислити на основі якогось іншого відомого індексу, наприклад startIndex, який указує на позицію першого символу в непорожньому рядку тексту, скориставшись методами, доступними в бібліотеках String та NSString (коли модуль Foundation імпортовано, рядки тексту у Swift мають доступ до всіх властивостей і методів NSString).
Наприклад, маємо такий рядок тексту:
let csv = "apple,pear,peach,orange,cherry,lime,goosberry"
Не можна написати csv[21], щоб отримати "g" в "orange": замість цього потрібно обчислити значення типу String.Index і передати саме його.
Зауважмо, що ці індекси не призначені для безпосереднього сприйняття людиною.
Їх називають непрозорими індексами, бо людині не потрібно знати, що всередині них.
let index = csv.index(csv.startIndex, offsetBy: 21)
csv[index]
// "g"
print(index)
// prints Index(_rawBits: 1376513)
Проте зауважмо: якщо зсув не відповідає дійсному індексу, тобто якщо він указує на позицію перед startIndex або після endIndex, операція спричинить помилку й аварійно завершить програму.
Щоб запобігти цій проблемі, можна вказати обмежувальний індекс.
Тоді операція повертає необовʼязковий індекс і поверне nil для індексів, які інакше були б недійсними.
let tooFar = csv.index(csv.startIndex, offsetBy: 200)
// error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
let tooFarButSafe = csv.index(csv.startIndex, offsetBy: 200, limitedBy: csv.endIndex)
// nil
Крім того, індекси не можна використовувати для різних рядків тексту.
Наприклад, якщо скористатися обчисленим вище index для "g" в "orange", щоб проіндексувати рядок fam = "This is my family: 👨👩👦👦, this is our dog: 🐶, this is our cat: 🐱!", тобто fam[index], програма аварійно завершиться.
Для всього цього є багато причин, але всі вони зводяться до того, що «з Unicode усе непросто».
Загалом, якщо потрібен довільний доступ до окремих символів, імовірно, варто використати якусь іншу структуру даних, як-от Array<Character>.
У Swift є методи first і last, щоб отримати перший і останній символ рядка тексту.
Ці методи повертають необовʼязковий символ, тож якщо рядок тексту порожній, вони повернуть nil.
let str = "Hello, world!"
print(str.first) // Prints Optional("H")
print(str.last) // Prints Optional("!")
Також можна скористатися методами prefix і suffix, щоб отримати підрядок рядка тексту.
Ці методи приймають ціле число як аргумент і повертають підрядок, що містить перші або останні n символів рядка тексту.
let str = "Hello, world!"
print(str.prefix(5)) // Prints "Hello"
print(str.suffix(6)) // Prints "world!"
Робота з текстом трапляється в програмуванні часто. Swift разом із фреймворком Foundation надає багато зручних методів і властивостей для перегляду, перетворення й опрацювання рядків тексту.
components(separatedBy:)
Щоб розбити рядок тексту на масив підрядків за розділювачем, можна скористатися методом components(separatedBy:) (потрібен імпорт Foundation):
import Foundation
let sentence = "Hello, world!"
let words = sentence.components(separatedBy: " ")
print(words) // Prints ["Hello,", "world!"]
hasPrefix(_:) і hasSuffix(_:)
Щоб перевірити, чи рядок тексту починається або закінчується певною послідовністю символів, можна скористатися методами hasPrefix(_:) і hasSuffix(_:):
let greeting = "Hello, world!"
print(greeting.hasPrefix("Hello")) // Prints true
print(greeting.hasSuffix("world!")) // Prints true
Змінити регістр рядка тексту можна за допомогою цих стандартних методів і властивостей:
lowercased(): повертає копію рядка тексту в нижньому регістрі.uppercased(): повертає копію рядка тексту у верхньому регістрі.capitalized: повертає копію, у якій першу літеру кожного слова записано з великої літери (з Foundation).let greeting = "hello, world!"
print(greeting.lowercased()) // Prints "hello, world!"
print(greeting.uppercased()) // Prints "HELLO, WORLD!"
print(greeting.capitalized) // Prints "Hello, World!"
replacingOccurrences(of:with:)
Щоб замінити всі входження цільового підрядка на інший рядок тексту, можна скористатися методом replacingOccurrences(of:with:) (з Foundation):
let greeting = "Hello, world!"
let updated = greeting.replacingOccurrences(of: "world", with: "Swift")
print(updated) // Prints "Hello, Swift!"
joined(separator:)
Метод joined(separator:) належить колекціям рядків тексту, як-от [String].
Він поєднує елементи в один рядок тексту за допомогою розділювача:
let words = ["Hello", "world"]
let sentence = words.joined(separator: ", ")
print(sentence) // Prints "Hello, world"
У місті відкрився новий поетичний клуб, і ми думаємо, чи не завітати туди. Оскільки в минулому траплялися інциденти, у клубу дуже специфічні правила входу, які потрібно опанувати, перш ніж намагатися зайти.
У поетичному клубі є двоє дверей, і обидві охороняються. Щоб потрапити всередину, потрібно розгадати пароль на цей день:
Перше, що потрібно зробити, - розбити вірш на окремі рядки. Охоронець прочитає вірш, а нам потрібно буде розбити його на рядки.
Реалізуйте функцію splitOnNewlines, яка приймає рядок тексту (англ. string) і розбиває його на масив рядків тексту, використовуючи символ нового рядка як розділювач.
Функція повинна повернути масив рядків тексту, де кожен елемент - це один рядок вірша.
splitOnNewlines("Hello.\nHow are you?\n\nI'm doing fine.")
// returns ["Hello." ,"How are you?", "", "I'm doing fine"].
_.Наприклад, один з їхніх улюблених письменників - Майкл Локвуд, який написав такий акровірш, а це означає, що перша літера кожного речення утворює слово:
Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave
Коли охоронець прочитає вірш, ми розбиваємо його на окремі рядки та відповідаємо першими літерами кожного рядка, тобто ["S", "H", "I", "R", "E"].
Тоді охоронець назве слово, утворене з масиву літер, якими ми відповіли, і це слово потрібно буде записати з великої літери.
Зрештою пароль, який ми повертаємо, - це "SHIRE", і ми потрапляємо всередину.
Реалізуйте функцію frontDoorPassword, яка приймає рядок тексту, що представляє вірш.
Функція повинна повернути пароль, який ми назвемо охоронцеві.
frontDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "SHIRE"
У глибині клубу збираються найвідоміші поети, щось на кшталт VIP-зони. Оскільки це не для всіх, вхід через чорний хід трохи заплутаніший.
", please" у кінець слова, утвореного з цих літер.Наприклад, згаданий вище вірш - це також телестих, а це означає, що остання літера кожного речення утворює слово:
Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave
Коли охоронець прочитає вірш, ми розбиваємо його на окремі рядки, прибираємо пробіли в кінці та відповідаємо останніми літерами кожного рядка, тобто ["h", "o", "r", "s", "e"].
Тоді охоронець назве слово, утворене з масиву літер, якими ми відповіли, і це слово потрібно буде записати з великої літери та додати ", please".
Зрештою пароль, який ми повертаємо, - це "horse, please", і ми потрапляємо всередину.
Реалізуйте функцію backDoorPassword, яка приймає рядок тексту, що представляє вірш.
Функція повинна повернути пароль, який ми назвемо охоронцеві.
backDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "horse, please"
У глибині клубу є ще одні двері, які ведуть до таємної кімнати, куди можуть зайти лише найкращі поети.
"!" у кінець слова, утвореного з цих літер.Наприклад, змінений варіант згаданого вище вірша відповідає цій схемі:
Stands so high
Huge hooves too
Impatiently waits for
Rider with harness
Eager to leave
Коли охоронець прочитає вірш, ми розбиваємо його на окремі рядки, прибираємо пробіли в кінці та відповідаємо i-ми літерами кожного рядка, тобто ["S", "u", "p", "e", "r"].
Тоді охоронець назве слово, утворене з масиву літер, якими ми відповіли, і це слово потрібно буде записати великими літерами та додати "!".
Зрештою пароль, який ми повертаємо, - це SUPER!, і ми потрапляємо всередину.
Реалізуйте функцію secretRoomPassword, яка приймає рядок тексту, що представляє вірш.
Функція повинна повернути пароль, який ми назвемо охоронцеві.
secretRoomPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nRider with harness\nEager to leave")
// returns "SUPER!"
Зареєструйтеся на Exercism, щоб вивчати й опановувати Swift, а також 35 концепцій116 вправ та справжнє наставництво від людей, і все це безкоштовно.