Pobierz bezpłatną kopię
the Missing Manual
for Swift Development

the Guide I Wish I Had When I Started Out

Dołącz do ponad 20 000 programistów uczących się o szybkim rozwoju

Pobierz bezpłatną kopię

jeśli to oglądasz, zakładam, że znasz rozszerzenia Swift. Rozszerzenie Swift pozwala na dodanie funkcjonalności do typu, klasy, struktury, wyliczenia lub protokołu. Ale rozszerzenia są potężniejsze niż to. W tym odcinku chciałbym wam pokazać cztery sprytne zastosowania szybkich rozszerzeń.

Zgodność protokołu

język programowania Swift wspomina, że rozszerzenia mogą być używane do dostosowania istniejącego typu do protokołu. Chociaż nie jest to nowe ani rewolucyjne, może również pomóc w utrzymaniu porządku w kodzie.

weź protokoły UITableViewDataSource i UITableViewDelegate jako przykład. Ten przykład może wyglądać znajomo. Jest to w porządku, ale skutkuje to długą implementacją klas, która z czasem może stać się trudna do nawigacji.

import UIKitclass ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { ...}

możesz uporządkować swój kod, tworząc rozszerzenie dla każdego protokołu zgodnego z typem.

import UIKitclass ViewController: UIViewController { ...}extension ViewController: UITableViewDataSource { ...}extension ViewController: UITableViewDelegate { ...}

nawigacja po plikach źródłowych staje się również łatwiejsza, jeśli nawyk używania paska skoku u góry edytora źródłowego Xcode.

nawigacja po plikach źródłowych staje się również łatwiejsza, jeśli nawyk używania paska skoku u góry edytora źródłowego Xcode.

następnej sztuczki nauczyłem się od Chrisa Eidhofa. W tym przykładzie najpierw musimy zdefiniować strukturę Person. Struktura definiuje dwie stałe właściwości typu String, firsti last.

struct Person { // MARK: - Properties let first: String let last: String}

Swift hojnie tworzy dla nas inicjalizator, init(first:last:), którego możemy użyć do utworzenia instancji struktury Person. To nic nowego.

let john = Person(first: "John", last: "Doe")

niestety, inicjalizator nie jest już dostępny, jeśli zdefiniujemy Niestandardowy inicjalizator w definicji struktury.

struct Person { // MARK: - Properties let first: String let last: String // MARK: - Initialization init(dictionary: ) { self.first = dictionary ?? "John" self.last = dictionary ?? "Doe" }}

inicjalizator nie jest już dostępny, jeśli zdefiniujemy Niestandardowy inicjalizator w definicji struktury.

na szczęście mamy łatwe obejście, aby rozwiązać ten problem. Tworzymy rozszerzenie dla struktury Person, w którym definiujemy Niestandardowy inicjalizator.

struct Person { // MARK: - Properties let first: String let last: String}extension Person { // MARK: - Initialization init(dictionary: ) { self.first = dictionary ?? "John" self.last = dictionary ?? "Doe" }}

rozszerzenie rozwiązuje problem.

separacja kodu

możemy wziąć poprzedni przykład o krok dalej. Kilka lat temu Natasha Murashev zarysowała technikę, która wykorzystuje rozszerzenia do oddzielenia stanu od zachowania. Jeśli zastosujemy tę technikę do poprzedniego przykładu, otrzymamy coś takiego.

struct Person { // MARK: - Properties let first: String let last: String}extension Person { // MARK: - Initialization init(dictionary: ) { self.first = dictionary ?? "John" self.last = dictionary ?? "Doe" } // MARK: - Public API var asDictionary: { return }}

definicja typu definiuje tylko zapisane właściwości. Rozszerzenie jest tworzone dla zachowania typu, czyli metod i właściwości obliczeniowych. Rezultatem jest wyraźne oddzielenie stanu (właściwości przechowywanych) i zachowania (metody i właściwości obliczeniowe).

możemy pójść o krok dalej, tworząc drugie prywatne rozszerzenie dla zachowania prywatnego.

struct Person { // MARK: - Properties let first: String let last: String}extension Person { ...}private extension Person { ...}

separacja i organizacja kodu jest bardzo łatwa do zrobienia przy użyciu rozszerzeń. Używam go cały czas. Jeśli brakuje plików nagłówkowych Objective-C, jest to dobra alternatywa.

typy zagnieżdżone

język programowania Swift wspomina, że rozszerzenia umożliwiają również definiowanie i używanie typów zagnieżdżonych. Ale czuję, że ta funkcja jest niedowartościowana. Używam go w każdym projekcie Swift, na przykład do definiowania stałych.

kilka miesięcy temu opublikowałem tutorial o budowaniu niestandardowej kontroli za pomocą maski bitowej. W tym samouczku przechowujemy surową wartość bitmask w bazie danych domyślnych użytkownika.

// MARK: - [email protected] func scheduleDidChange(_ sender: SchedulePicker) { // Helpers let userDefaults = UserDefaults.standard // Store Value let scheduleRawValue = sender.schedule.rawValue userDefaults.set(scheduleRawValue, forKey: UserDefaults.Keys.schedule)}

zamiast używać dosłownego ciągu znaków, używamy stałej. Tworzymy rozszerzenie dla klasy UserDefaults, w którym definiujemy enum bez przypadków, Keys. Enum definiuje jedną stałą statyczną typu String, schedule.

extension UserDefaults { enum Keys { static let schedule = "schedule" }}

wynik jest całkiem ładny, jeśli O mnie chodzi. Nie tylko możemy grupować stałe, unikając literałów rozproszonych po kodzie, ale także przestrzeń nazw stałych. Innymi słowy, stałe są łatwe do zapamiętania i mają sens.

UserDefaults.Keys.schedule

wraz z wydaniem Swift 3, Apple przyjęło podobną technikę w niektórych swoich frameworkach.

Notification.Name.UIApplicationWillTerminate

co dalej

rozszerzenia są dość potężne w Swifcie, a techniki pokazane w tym samouczku to tylko kilka przykładów tego, co jest możliwe.

Pobierz bezpłatną kopię
brakującego podręcznika
do szybkiego rozwoju

przewodnik, który chciałbym mieć, gdy zaczynałem

Dołącz do ponad 20 000 programistów uczących się o szybkim rozwoju

Pobierz bezpłatną kopię

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.