Die meisten Modelle in meiner iOS-App fragen einen Webserver ab. Ich hätte gerne eine Konfigurationsdatei, in der die Basis-URL des Servers gespeichert ist. Es wird ungefähr so aussehen:
// production
// static NSString* const baseUrl = "http://website.com/"
// testing
static NSString* const baseUrl = "http://192.168.0.123/"
Durch Auskommentieren der einen oder anderen Zeile kann ich sofort ändern, auf welchen Server meine Modelle verweisen. Meine Frage ist, was ist die beste Vorgehensweise zum Speichern globaler Konstanten in iOS? In der Android-Programmierung haben wir diese integrierte String-Ressourcendatei . In jeder Aktivität (das Äquivalent eines UIViewControllers ) können wir diese Zeichenfolgenkonstanten abrufen mit:
String string = this.getString(R.string.someConstant);
Ich habe mich gefragt, ob das iOS SDK einen analogen Speicherort für Konstanten hat. Wenn nicht, was ist die beste Vorgehensweise in Objective-C, um dies zu tun?
"constants.h"
Ansatz und deklarierestatic
Variablen basierend auf#ifdef VIEW_CONSTANTS ... #endif
. Ich habe also eine anwendungsweite Konstantendatei, aber jede meiner anderen Codedateien muss#define
unterschiedliche Konstantensätze enthalten, bevor#include
die Konstantendatei erstellt wird (stoppt alle "definierten, aber nicht verwendeten" Compiler-Warnungen).#decalare
, bekam ich zuerst einen Kompilierungsfehler mit der Aufschrift " Ungültige Vorverarbeitungsrichtlinie deklarieren ". Also habe ich es#define
stattdessen geändert . Das andere Problem ist die Verwendung der Konstante. Ich wollte eine andere Konstante mit erstellenstatic NSString* const fullUrl = [NSString stringWithFormat:@"%@%@", kbaseUrl, @"script.php"]
, aber anscheinend ist es illegal, Konstanten mit einem Ausdruck zu erstellen. Ich erhalte die Fehlermeldung " Initialisierungselement ist nicht konstant ".#define kBaseURL @"http://192.168.0.123/";
Nun, Sie möchten die Deklaration lokal für die Schnittstellen, auf die sie sich bezieht - die app-weite Konstantendatei ist keine gute Sache.
Außerdem ist es vorzuziehen, einfach ein
extern NSString* const
Symbol zu deklarieren , anstatt ein#define
:SomeFile.h
SomeFile.m
Abgesehen vom Weglassen der C ++ - kompatiblen externen Deklaration wird dies im Allgemeinen in den Obj-C-Frameworks von Apple verwendet.
Wenn die Konstante nur für eine Datei oder Funktion sichtbar sein muss, ist
static NSString* const baseUrl
in Ihrer*.m
gut.quelle
@"foo"
ist nicht dasselbe wie[[NSString alloc] initWithCString:"foo"]
.#define
verwendet werden (dh Zeigergleichheit könnte fehlschlagen) - nicht, dass ein NSString-Literalausdruck bei jeder Ausführung eine temporäre erzeugt.So definiere ich globale Konstanten:
AppConstants.h
AppConstants.m
Dann in Ihrer {$ APP} -Prefix.pch-Datei:
Wenn Probleme auftreten, stellen Sie zunächst sicher, dass die Option Precompile Prefix Header auf NO gesetzt ist.
quelle
Sie können auch Zeichenfolgenkonstanten wie folgt verketten:
quelle
Ich denke, dass ein anderer Weg, dies zu tun, viel einfacher ist und Sie ihn einfach in Dateien einfügen, in denen Sie ihn benötigen, nicht in ALLE Dateien, wie bei der .pch-Präfixdatei:
Danach fügen Sie diese Header-Datei in die gewünschte Header-Datei ein. Sie fügen es in die Header-Datei für die bestimmte Klasse ein, in die es aufgenommen werden soll:
quelle
"error: use of undeclared identifier .."
#define BASEURl @"http://myWebService.appspot.com/xyz/xx"
dann irgendwo im Projekt, um BASEURL zu verwenden:
Aktualisiert: In Xcode 6 finden Sie keine in Ihrem Projekt erstellte Standard-PCH-Datei. Verwenden Sie daher bitte die PCH-Datei in Xcode 6 , um die PCH-Datei in Ihr Projekt einzufügen.
Updates: Für SWIFT
& Sofort Mitglied deklarieren / definieren
Beispiel:
quelle
Globale Deklarationen sind interessant, aber für mich hat sich meine Art zu codieren grundlegend geändert, globale Instanzen von Klassen zu haben. Ich habe ein paar Tage gebraucht, um wirklich zu verstehen, wie man damit arbeitet, also habe ich es hier schnell zusammengefasst
Ich verwende globale Instanzen von Klassen (1 oder 2 pro Projekt, falls erforderlich), um den Kerndatenzugriff oder einige Handelslogiken neu zu gruppieren.
Wenn Sie beispielsweise ein zentrales Objekt haben möchten, das alle Restauranttabellen verwaltet, erstellen Sie Ihr Objekt beim Start, und das ist es. Dieses Objekt kann Datenbankzugriffe verarbeiten ODER im Speicher verarbeiten, wenn Sie es nicht speichern müssen. Es ist zentralisiert, Sie zeigen nur nützliche Schnittstellen ...!
Es ist eine große Hilfe, objektorientiert und eine gute Möglichkeit, alles, was Sie haben, an den gleichen Ort zu bringen
Ein paar Codezeilen:
und Objektimplementierung:
für die Verwendung ist es wirklich einfach:
quelle
Die akzeptierte Antwort hat 2 Schwächen. Erstens, wie andere betonten, ist die Verwendung,
#define
deren Debugging schwieriger ist, stattdessen dieextern NSString* const kBaseUrl
Struktur. Zweitens definiert es eine einzelne Datei für Konstanten. IMO, das ist falsch, weil die meisten Klassen keinen Zugriff auf diese Konstanten benötigen oder auf alle zugreifen können. Außerdem kann die Datei aufgebläht werden, wenn alle Konstanten dort deklariert sind. Eine bessere Lösung wäre, Konstanten in 3 verschiedenen Schichten zu modularisieren:Systemschicht :
SystemConstants.h
oderAppConstants.h
beschreibt Konstanten im globalen Bereich, auf die jede Klasse im System zugreifen kann. Deklarieren Sie hier nur die Konstanten, auf die von verschiedenen Klassen zugegriffen werden muss, die nicht miteinander verbunden sind.ModuleNameConstants.h
Modul- / Subsystemschicht : , beschreibt eine Reihe von Konstanten, die für eine Reihe verwandter Klassen innerhalb eines Moduls / Subsystems typisch sind.Klassenebene: Konstanten befinden sich in der Klasse und werden nur von dieser verwendet.
Nur 1,2 beziehen sich auf die Frage.
quelle
Ein Ansatz, den ich zuvor verwendet habe, besteht darin, eine Datei zu erstellen
Settings.plist
und sieNSUserDefaults
beim Start mit zu ladenregisterDefaults:
. Sie können dann wie folgt auf den Inhalt zugreifen:Obwohl ich noch keine Android-Entwicklung durchgeführt habe, klingt es so, als ob dies analog zu der von Ihnen beschriebenen String-Ressourcendatei ist. Der einzige Nachteil ist, dass Sie den Präprozessor nicht zum Wechseln zwischen Einstellungen verwenden können (z
DEBUG
. B. im Modus). Ich nehme an, Sie könnten jedoch eine andere Datei laden.NSUserDefaults
Dokumentation.quelle
NSString
,NSNumber
usw.). Sicher, Sie könnten Ihre#define
s einpacken , um dasselbe zu tun, aber dann sind sie nicht so einfach zu bearbeiten. Dieplist
Bearbeitungsoberfläche ist auch schön. :) Obwohl ich damit einverstanden bin, dass Sie keine supergeheimen Dinge wie Verschlüsselungsschlüssel hineinstecken sollten, mache ich mir keine allzu großen Sorgen um Benutzer, die an Orten herumstochern, an denen sie nicht sein sollten - wenn sie die App kaputt machen, ist es ihre eigene Schuld .#define
s, um den richtigen Typ zurückzugeben, aber ich bin es gewohnt, solche Konstantendateien zu bearbeiten, da ich immer gelernt habe, globale Konstanten wie diese in eine separate Konstantendatei zu schreiben, seit ich Pascal gelernt habe auf einem alten 286 :) Und was den Benutzer betrifft, der überall herumstochert, stimme ich auch zu, es ist ihre Schuld. Es ist wirklich nur eine Frage des Geschmacks.Für eine Nummer können Sie es wie verwenden
quelle
Ich würde ein Konfigurationsobjekt verwenden , das von a initialisiert wird
plist
. Warum andere Klassen mit irrelevanten externen Dingen belästigen?Ich habe
eppz!settigns
allein aus diesem Grund erstellt. Siehe Artikel Erweiterte und dennoch einfache Methode zum Speichern in NSUserDefaults zum Einbeziehen von Standardwerten aus aplist
.quelle