Większość modeli w mojej aplikacji na iOS odpytuje serwer WWW. Chciałbym mieć plik konfiguracyjny przechowujący podstawowy adres URL serwera. Będzie wyglądać mniej więcej tak:
// production
// static NSString* const baseUrl = "http://website.com/"
// testing
static NSString* const baseUrl = "http://192.168.0.123/"
Komentując jedną lub drugą linię, mogę natychmiast zmienić serwer, na który wskazują moje modele. Moje pytanie brzmi: jaka jest najlepsza praktyka przechowywania globalnych stałych w iOS? W programowaniu na Androida mamy ten wbudowany plik zasobów ciągów . W dowolnym działaniu (odpowiedniku UIViewController ) możemy pobrać te stałe łańcuchowe za pomocą:
String string = this.getString(R.string.someConstant);
Zastanawiałem się, czy iOS SDK ma analogiczne miejsce do przechowywania stałych. Jeśli nie, jaka jest najlepsza praktyka w Objective-C, aby to zrobić?
"constants.h"
podejście, deklarującstatic
zmienne na podstawie#ifdef VIEW_CONSTANTS ... #endif
. Mam więc jeden plik stałych dla całej aplikacji, ale każdy z moich pozostałych plików z kodem#define
to różne zestawy stałych, które mają zostać#include
dołączone przed plikiem stałych (zatrzymuje wszystkie te „zdefiniowane, ale nie używane” ostrzeżenia kompilatora).#decalare
, otrzymałem błąd kompilacji z informacją „ Nieprawidłowa deklaracja dyrektywy preprocessingu ”. Więc zmieniłem to na#define
. Innym problemem jest użycie stałej. Chciałem stworzyć inną stałą zstatic NSString* const fullUrl = [NSString stringWithFormat:@"%@%@", kbaseUrl, @"script.php"]
, ale najwyraźniej tworzenie stałych z wyrażeniem jest nielegalne. Pojawia się błąd „ Element inicjujący nie jest stały ”.#define kBaseURL @"http://192.168.0.123/";
Cóż, chcesz, aby deklaracja była lokalna dla interfejsów, do których się odnosi - plik stałych całej aplikacji nie jest dobrą rzeczą.
Poza tym lepiej jest po prostu zadeklarować
extern NSString* const
symbol, zamiast używać#define
:SomeFile.h
SomeFile.m
Oprócz pominięcia deklaracji Extern zgodnej z C ++, to jest to, co zwykle jest używane w frameworkach Obj-C firmy Apple.
Jeśli stała ma być widoczna tylko dla jednego pliku lub funkcji, to
static NSString* const baseUrl
w twoim*.m
jest dobra.źródło
@"foo"
to nie to samo co[[NSString alloc] initWithCString:"foo"]
.#define
jest używana (tj. Równość wskaźnika może się nie udać) - nie znaczy to, że dosłowne wyrażenie NSString tworzy tymczasowe wyrażenie za każdym razem, gdy jest wykonywane.Sposób definiowania stałych globalnych:
AppConstants.h
AppConstants.m
Następnie w pliku {$ APP} -Prefix.pch:
Jeśli wystąpią jakiekolwiek problemy, najpierw upewnij się, że opcja Precompile Prefix Header jest ustawiona na NO.
źródło
Możesz również łączyć stałe łańcuchowe w następujący sposób:
źródło
Myślę, że inny sposób jest znacznie prostszy i po prostu umieścisz go w plikach, w których są potrzebne, a nie WSZYSTKICH plikach, jak w przypadku pliku z prefiksem .pch:
Następnie umieść ten plik nagłówkowy w żądanym pliku nagłówkowym. Umieszczasz go w pliku nagłówkowym dla określonej klasy, w której ma być uwzględniony:
źródło
"error: use of undeclared identifier .."
#define BASEURl @"http://myWebService.appspot.com/xyz/xx"
następnie w dowolnym miejscu projektu, aby używać BASEURL:
Zaktualizowano: W Xcode 6 nie znajdziesz domyślnego pliku .pch utworzonego w Twoim projekcie. Dlatego użyj pliku PCH w Xcode 6, aby wstawić plik .pch do projektu.
Aktualizacje: dla SWIFT
& Od razu zadeklaruj / zdefiniuj członka
Przykład:
źródło
Deklaracje globalne są interesujące, ale dla mnie to, co głęboko się zmieniło w moim sposobie kodowania, to posiadanie globalnych instancji klas. Zajęło mi kilka dni, zanim naprawdę zrozumiałem, jak z nim pracować, więc szybko podsumowałem to tutaj
Używam globalnych instancji klas (1 lub 2 na projekt, jeśli to konieczne), aby przegrupować dostęp do podstawowych danych lub logikę niektórych transakcji.
Na przykład, jeśli chcesz mieć centralny obiekt obsługujący wszystkie stoły restauracyjne, tworzysz obiekt podczas uruchamiania i to wszystko. Ten obiekt może obsługiwać dostęp do bazy danych LUB obsłużyć go w pamięci, jeśli nie musisz go zapisywać. Jest scentralizowany, pokazujesz tylko przydatne interfejsy ...!
To świetna pomoc, zorientowana obiektowo i dobry sposób na zebranie wszystkich rzeczy w tym samym miejscu
Kilka linijek kodu:
i realizacja obiektów:
za korzystanie z niego jest to naprawdę proste:
źródło
Przyjęta odpowiedź ma 2 słabości. Po pierwsze, jak wskazali inni, użycie
#define
którego jest trudniejsze do debugowania, użyj zamiast tegoextern NSString* const kBaseUrl
struktury. Po drugie, definiuje pojedynczy plik dla stałych. IMO, to jest złe, ponieważ większość klas nie potrzebuje dostępu do tych stałych lub aby uzyskać dostęp do wszystkich z nich, a także plik może zostać rozdęty, jeśli wszystkie stałe są tam zadeklarowane. Lepszym rozwiązaniem byłoby modularyzacja stałych w 3 różnych warstwach:Warstwa systemowa:
SystemConstants.h
lubAppConstants.h
która opisuje stałe o zasięgu globalnym, do których dostęp może uzyskać każda klasa w systemie. Zadeklaruj tutaj tylko te stałe, do których należy uzyskać dostęp z różnych klas, które nie są powiązane.Warstwa modułu / podsystemu:
ModuleNameConstants.h
opisuje zestaw stałych, które są typowe dla zestawu powiązanych klas, wewnątrz modułu / podsystemu.Warstwa klasy: Stałe znajdują się w klasie i są używane tylko przez nią.
Tylko 1,2 odnosi się do pytania.
źródło
Podejście, którego używałem wcześniej, polega na utworzeniu pliku
Settings.plist
i załadowaniu goNSUserDefaults
po uruchomieniu za pomocąregisterDefaults:
. Następnie możesz uzyskać dostęp do jego zawartości za pomocą:Chociaż nie robiłem żadnego programu na Androida, wydaje się, że jest to analogiczne do opisanego przez ciebie pliku zasobów ciągów. Jedynym minusem jest to, że nie można używać preprocesora do przełączania się między ustawieniami (np. W
DEBUG
trybie). Przypuszczam jednak, że możesz załadować inny plik.NSUserDefaults
dokumentacja.źródło
NSString
,NSNumber
, itd.). Jasne, możesz owinąć swoje#define
pliki, aby zrobić to samo, ale wtedy nie są tak łatwe do edycji.plist
Interfejs edycji jest ładne, zbyt. :) Chociaż zgadzam się, że nie powinieneś umieszczać tam super tajnych rzeczy, takich jak klucze szyfrujące, nie martwię się zbytnio o użytkowników, którzy szperają w miejscach, w których nie powinni być - jeśli zepsują aplikację, to ich wina .#define
aby zwrócić właściwy typ, ale jestem przyzwyczajony do edytowania takich plików stałych, ponieważ zawsze nauczyłem się umieszczać globalne stałe w oddzielnym pliku stałych, z czasów, gdy uczyłem się Pascala na starym 286 :) A co do użytkownika, który wszędzie grzebuje, to też się zgadzam, to jego wina. Tak naprawdę to tylko kwestia gustu.Dla numeru możesz go używać jak
źródło
Użyłbym obiektu konfiguracji, który inicjuje się z pliku
plist
. Po co zawracać innym klasom nieistotne zewnętrzne rzeczy?Stworzyłem
eppz!settigns
Soley z tego powodu. Zobacz artykuł Zaawansowany, ale prosty sposób zapisywania w NSUserDefaults w celu włączenia wartości domyślnych z plikuplist
.źródło