Najlepsze praktyki i narzędzia do projektowania iOS

Z szablonem projektu Xcode typu open source

Podczas pracy nad zielonymi projektami iOS często musiałem zaczynać nowy projekt od zera. Robiąc to, ja i mój zespół zawsze spędzaliśmy dużo czasu na podstawowej konfiguracji projektu, takiej jak narzędzia integracyjne, konfigurowanie struktury projektu, pisanie klas podstawowych, integrowanie bibliotek zewnętrznych itp.

Uznałem, że czas poświęcony na uruchomienie projektu można zaoszczędzić, a proces ten można w większości zautomatyzować. Zapisałem wszystkie typowe najlepsze praktyki i narzędzia, z których korzystaliśmy, i przygotowałem szablon projektu, który ja i mój zespół moglibyśmy wykorzystać przy rozpoczynaniu nowych projektów. Ten szablon powinien oszczędzić czas konfiguracji projektu, a także stanowić wspólną podstawę, do której przyzwyczai się każdy członek zespołu, dzięki czemu nie będziesz musiał myśleć i badać struktury projektu i fundamentów. Zawsze będą takie same.

Każde narzędzie lub najlepsza praktyka zawarta w szablonie zasługuje na osobny artykuł, ale chciałem spróbować podsumować każdy punkt i krótko wyjaśnić, dlaczego je zawarłem.

Cocoapods

Nie sądzę, że ten wymaga wprowadzenia. Jest to biblioteka do zarządzania zewnętrznymi zależnościami dla projektów iOS. Jest już od dawna i jest solidny i przetestowany w walce w tysiącach (jeśli nie milionach) projektów. Istnieją alternatywni menedżerowie zależności, tacy jak Carthage, ale zdecydowałem się na Cocoapods, ponieważ ma on najszerszy zakres obsługiwanych projektów open source. Korzystanie z Cocoapods jest bardzo łatwe i zawiera indeks wyszukiwania, który pozwala łatwo znaleźć potrzebne pakiety.

Projekt szablonu zawiera prosty plik Podfile, który obejmuje Swiftlint i R.swift. Szablon zawiera także plik Gemfile do zarządzania wersją Cocoapods używaną do rozwiązywania zależności. Jest to często pomijane ulepszenie, które zapobiega problemom pojawiającym się, gdy programiści z twojego zespołu instalują zależności przy użyciu różnych wersji samego Cocoapods. Gemfile wymusza używanie tej samej wersji Cocoapods w całym zespole.

Swiftlint

Swiftlint to bardzo przydatne narzędzie do egzekwowania określonych zasad i stylu kodowania dla każdego programisty w zespole. Możesz myśleć o tym jak o zautomatyzowanym systemie przeglądania kodu, który ostrzega programistę przed niebezpiecznymi rzeczami, takimi jak wymuszanie rozpakowywania, wymuszanie rzutów, wymuszanie prób itp., Ale także egzekwuje wspólny styl kodowania, upewniając się, że wszyscy programiści przestrzegają tych samych reguł związanych z „stylem kodu” takie jak wcięcia lub reguły odstępów. Ma to ogromne zalety polegające nie tylko na oszczędzaniu czasu na przeglądanie kodu przez wykonanie tych podstawowych kontroli, ale także sprawia, że ​​wszystkie pliki w projekcie wyglądają znajomo, co zwiększa ich czytelność, aw rezultacie ich zrozumienie przez wszystkich twórców. Tutaj znajdziesz listę wszystkich zasad. W szablonie Swiftlint jest instalowany za pośrednictwem Cocoapods i jest uwzględniany w kroku Fazy kompilacji, dzięki czemu program ostrzega i ostrzega programistę przy każdej kompilacji projektu.

R.swift

R.swift to narzędzie do uzyskiwania silnie wpisywanych, autouzupełniających zasobów, takich jak obrazy, sekwencje czcionek i lokalizacje. Robi to, skanując projekt i generując szybkie klasy potrzebne do uzyskania zasobów. Największą zaletą tej biblioteki jest to, że podczas korzystania z zasobów czyni twój kod:

  • W pełni wpisany - mniej rzucania i zgadywania, co metoda zwróci
  • Sprawdzono czas kompilacji - nie ma już niepoprawnych ciągów, które powodują awarię aplikacji w czasie wykonywania
  • Autouzupełnianie - nigdy więcej nie musisz zgadywać nazwy obrazu / stalówki / serii ujęć

Rozważ następujący kod przy użyciu oficjalnego interfejsu API ciągów:

let icon = UIImage (o nazwie: „custom-icon”)

Jeśli źle wpiszesz nazwę obrazu, otrzymasz zero. Jeśli któryś z członków zespołu zmieni nazwę zasobu obrazu, ten kod zwróci zero lub zawiesi się, jeśli wymusisz rozpakowanie obrazu. Podczas używania R.swift staje się to:

let icon = R.image.customIcon ()

Teraz możesz być pewien, że ikona naprawdę istnieje (kompilator ostrzeże Cię, jeśli nie zrobi tego dzięki kontroli czasu kompilacji) i jesteś pewien, że nie zrobisz literówki w nazwie ikony, ponieważ będziesz używać autouzupełniania.

R.swift jest instalowany za pośrednictwem Cocoapods i zintegrowany z szablonem jako Faza kompilacji i będzie generował klasy opakowań Swift dla każdej kompilacji. Oznacza to, że jeśli dodasz plik / obraz / lokalizację / czcionkę / kolor / stalówkę itp., Będzie on dostępny za pomocą R.swift po skompilowaniu projektu.

Oddzielna aplikacjaDeleguj do testów

Często pomijaną dobrą praktyką jest posiadanie osobnej klasy TestAppDelegate podczas uruchamiania testów. Dlaczego to dobry pomysł? Cóż, zazwyczaj klasa AppDelegate wykonuje dużo pracy przy uruchamianiu aplikacji. Może skonfigurować okno, zbudować podstawową strukturę interfejsu użytkownika aplikacji, zarejestrować się w celu otrzymywania powiadomień, skonfigurować bazę danych, a nawet czasami wywoływać API do niektórych usług zaplecza. Testy jednostkowe nie powinny mieć żadnych skutków ubocznych. Czy naprawdę nie chcesz wykonywać losowych wywołań interfejsu API i konfigurować całej struktury interfejsu aplikacji, aby przeprowadzić testy jednostkowe?

TestAppDelegate to także świetne miejsce na kod, który chcesz uruchomić tylko raz podczas wykonywania zestawu testów. Może zawierać kod, który generuje pozorowane, pośredniczące żądania sieciowe itp.

Szablon zawiera plik main.swift, który jest głównym punktem wejścia do aplikacji. W tym pliku są metody sprawdzające, jakie jest środowisko, w którym aktualnie działa aplikacja i jeśli jest to środowisko testowe, wywołuje TestAppDelegate.

Flagi profilowania wydajności kompilatora

Swift to świetny język, łatwiejszy w użyciu i znacznie bezpieczniejszy niż Objective-C (IMO). Ale kiedy został wprowadzony po raz pierwszy, miał jeden duży minus - czasy kompilacji. Wracając do Swift 2 dni, pracowałem nad projektem, który zawierał 40 000 wierszy kodu Swift (projekt średniej wielkości). Kod był bardzo obfity w generyczne i wnioskowanie o typie, a skompilowanie czystej wersji zajęło prawie 5 minut. Po wprowadzeniu nawet niewielkiej zmiany projekt ponownie się skompiluje, a zmiana zajmie około 2 minut. To było jedno z najgorszych doświadczeń deweloperskich, jakie kiedykolwiek miałem i prawie z tego powodu przestałem używać Swift.

Jedynym rozwiązaniem było wówczas sprofilowanie czasów kompilacji projektu i próba zmiany kodu w taki sposób, aby przyspieszyć kompilator. Aby temu zaradzić, Apple wprowadza nieoficjalne flagi kompilatora, które ostrzegałyby Cię podczas kompilowania treści metody lub rozwiązywania typu wyrażenia za długo. Dodałem te flagi do projektu szablonu, więc od samego początku będziesz ostrzegany o długich czasach kompilacji aplikacji.

W dzisiejszych czasach czasy kompilacji zostały znacznie poprawione i bardzo rzadko trzeba modyfikować kod, aby poprawić czasy kompilacji. Ale nadal lepiej jest wiedzieć z góry, niż spróbować rozwiązać problem, gdy projekt staje się zbyt duży.

Konfiguracje Dev / Staging / Production

Inną dobrą praktyką (lub mogę powiedzieć, że jest to konieczność) jest posiadanie oddzielnych konfiguracji i zmiennych środowiskowych dla środowisk programistycznych, testowych i produkcyjnych. Prawie każda aplikacja musi obecnie łączyć się z pewnego rodzaju usługą zaplecza i zwykle usługi te są wdrażane w wielu środowiskach. Środowisko programistyczne jest używane do codziennych wdrożeń oraz do testowania kodu przez programistów. Środowisko przemieszczania służy do stabilnych wydań testerów i klientów do testowania. Wszyscy wiemy, do czego służy środowisko produkcyjne.

Jednym ze sposobów obsługi wielu środowisk w projekcie iOS jest dodanie konfiguracji na poziomie projektu.

Konfiguracje na poziomie projektu

Po zdefiniowaniu konfiguracji możesz utworzyć plik Configuration.plist zawierający zmienne dla każdego środowiska.

Configuration.plist

Podczas uruchamiania projektu możesz określić, której konfiguracji należy użyć. Możesz to zrobić w schemacie kompilacji.

Następnie musisz dodać jedną dodatkową właściwość do pliku Info.plist projektu. Wartość tej właściwości zostanie dynamicznie ustalona w czasie wykonywania na nazwę bieżącej konfiguracji.

Wszystko to jest wstępnie skonfigurowane w szablonie.

Pozostaje tylko napisać klasę, która może pobierać te zmienne w czasie wykonywania, w zależności od konfiguracji wybranej w schemacie kompilacji. Szablon zawiera klasę ConfigurationManager, która może pobierać zmienne dla bieżącego środowiska. Możesz sprawdzić implementację tej klasy na Github, aby zobaczyć, jak to działa.

Readme

Każdy projekt powinien mieć podstawowy plik Readme, który przynajmniej zawiera instrukcje dotyczące instalowania zależności i uruchamiania projektu. Powinien także zawierać opisy architektury i modułów projektu. Niestety programiści nie lubią pisać dokumentacji (plik Readme jest tego częścią) i widziałem projekt, który był rozwijany od miesięcy i mieli nawet podstawowy plik Readme. Aby usunąć ciężar pisania tego podstawowego pliku Readme, szablon zawiera standardowy plik Readme obejmujący instalację i strukturę projektu. Po skonfigurowaniu nowego projektu za pomocą szablonu, plik Readme zostanie dołączony automatycznie.

Gitignore

Obecnie większość projektów używa GIT jako systemu kontroli wersji. Korzystając z GIT, zwykle nie ignorujesz niektórych plików lub folderów w projekcie, takich jak folder kompilacji lub folder danych pochodnych. Aby uniknąć kłopotów ze znalezieniem pliku gitignore, który pasowałby do twojego projektu iOS, szablon zawiera standardowy gitignore dostarczony przez współpracowników Github.

Klasy podstawowe do obsługi precyzyjnych linków i powiadomień

Prawie każda aplikacja musi obecnie obsługiwać precyzyjne linki i powiadomienia. Aby to zrobić, programista musi napisać pewną ilość kodu typu „plateplate” w klasie AppDelegate. Szablon ma to pokryte, a także zapewnia klasy podstawowe, które ułatwiają pracę z precyzyjnymi linkami i powiadomieniami.

Podsumowanie

Podsumowując, szablon stara się zawierać najlepsze praktyki i integruje przydatne narzędzia innych firm. Powinno to zaoszczędzić Ciebie i nasz zespół czasu poświęconego na konfigurację nowego projektu, a także zapewnić wspólny i mocny fundament dla reszty projektu. Niech ci dobrze służy!

PS: Jeśli masz jakieś problemy lub prośbę o funkcję szablonu, zostaw problem w Github. Spróbuję rozwiązać to w wolnym czasie.