زبان Swift قابلیتهای فراوانی در کتابخانهی استاندارد خود ارائه میدهد، اما میتوانید با وارد کردن کتابخانهها و frameworkهای بیرونی به امکانات بیشتری دسترسی پیدا کنید. این ماژولها ممکن است مستقیماً از پروژهی Swift بیایند (مانند Swift Argument Parser)، از frameworkهای پلتفرم Apple (مانند Foundation و Network Framework)، یا از کتابخانههای متنباز شخص ثالث (مانند SwiftyBeaver).
ماژولهای اصلی مانند Foundation، که یکی از پرکاربردترین کتابخانهها در Swift است، همراه با زنجیرهی ابزار Swift ارائه میشوند. کتابخانههای شخص ثالث باید پیش از آن که بتوان آنها را وارد کرد، به پیکربندی پروژهتان افزوده شوند (برای نمونه، با استفاده از Swift Package Manager).
وارد کردن ماژولها با نوشتن کلیدواژهی import و سپس اسم ماژول انجام میشود.
بنابراین میتوانید با افزودن قطعهی زیر به برنامهتان، Foundation را وارد کنید.
import Foundation
وارد کردن یک ماژول، نوعها، متدها و توابع آن را در اختیار کد شما قرار میدهد.
برای نمونه، وارد کردن Foundation، String را با متدهای سودمند و کاربردی مانند components(separatedBy:) گسترش میدهد.
طبق قرارداد، دستورهای import در بالای فایل Swift نوشته میشوند تا وابستگیها بیدرنگ برای هر کسی که کد را میخواند آشکار باشد.
به کاراکترهای تکتک یک String میتوان با همان روش اندیسگذاری آرایهها دسترسی پیدا کرد.
اما اندیسهایی که برای رشتهها به کار میروند عدد صحیح نیستند و نمیتوان مستقیماً با آنها کار کرد.
در عوض باید آنها را بر پایهی اندیس شناختهشدهی دیگری مانند startIndex محاسبه کرد، که به جایگاه نخستین کاراکتر در یک رشتهی ناتهی اشاره میکند؛ این کار با متدهای موجود در کتابخانههای String و NSString انجام میشود (وقتی ماژول Foundation وارد شده باشد، رشتهها در Swift به همهی ویژگیها و متدهای NSString دسترسی دارند).
برای نمونه، رشتهی زیر را در نظر بگیرید:
let csv = "apple,pear,peach,orange,cherry,lime,goosberry"
نمیتوان برای به دست آوردن «g» در «orange» عبارت csv[21] را نوشت؛ در عوض باید مقداری از نوع String.Index محاسبه کرد و همان اندیس را به کار برد.
توجه کنید که این اندیسها به خودی خود برای مصرف انسان در نظر گرفته نشدهاند.
به آنها اندیسهای مبهم میگویند، چون انسانها نیازی ندارند بدانند درونشان چیست.
let index = csv.index(csv.startIndex, offsetBy: 21)
csv[index]
// "g"
print(index)
// prints Index(_rawBits: 1376513)
اما توجه کنید که اگر مقدار offset اندیس معتبری نباشد، یعنی اگر اندیسی پیش از 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، همراه با framework 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 را پیادهسازی کنید که یک رشته میگیرد و آن را با استفاده از کاراکتر خط جدید به عنوان جداکننده، به آرایهای از رشتهها تقسیم میکند.
تابع باید آرایهای از رشتهها برگرداند که هر رشته یکی از خطوط شعر است.
splitOnNewlines("Hello.\nHow are you?\n\nI'm doing fine.")
// returns ["Hello." ,"How are you?", "", "I'm doing fine"].
_ استفاده کنید.برای نمونه، یکی از نویسندگان محبوبشان Michael Lockwood است که شعر آکروستیک زیر را نوشته است؛ یعنی حرف اول هر جمله یک واژه میسازد:
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!"