I think this is a very simple thing to do, but since I'm new to iOS development and objective C, I can't figure it out.
#define RESTFUL_PATH_PREFIX #"https://gogch.com/gch-restful";
#define LOGIN RESTFUL_PATH_PREFIX #"/login;
I want the result "https://gogch.com/gch-restful/login"
but I'm getting the result as "https://gogch.com/gch-restful"
other topics in stackoverflow mention only about adding a new string to the beginning of a string like,
#define DOMAIN "example.com"
#define SUBDOMAIN "test." DOMAIN
Remove the trailing semi-colon:
#define RESTFUL_PATH_PREFIX #"https://gogch.com/gch-restful";
^
and then string constants can be concatenated by the compiler:
#"first" #"second"
instead of:
#"first"; #"second"
It is much better practice to use constants instead of define macros.
static NSString *const YourPath = #"https://...";
And then you can concatenate your strings with NSString stringWithFormat: method.
Since I made this answer to a question marked as a dupe, I'll also answer it here
Sure, you can use defines OR you can use NSString constants. It's really a matter of preference ... I have however seen both a #define and an NSString const * const being used before. Defines are easier, and you're probably not going to save that much memory by having constants instead of individual immutable instances of NSString all over the place.
Some advice is to think about how you export the NSString constants. You'll probably want EXTERN_PRIVATE instead of EXTERN, but my sample code will allow all clients of your header to read the string constants you've declared therein.
What you can do:
Create a new .m/.c file with a header in Xcode
In the .m/.c file, declare and initialise your constants
Export the constant as necessary so other compilation units can access it
constants.h
#ifndef constants_h
#define constants_h
// Export the symbol to clients of the static object (library)
#define EXTERN extern __attribute__((visibility("default")))
// Export the symbol, but make it available only within the static object
#define EXTERN_PRIVATE extern __attribute__((visibility("hidden")))
// Make the class symbol available to clients
#define EXTERN_CLASS __attribute__((visibility("default")))
// Hide the class symbol from clients
#define EXTERN_CLASS_PRIVATE __attribute__((visibility("hidden")))
#define INLINE static inline
#import <Foundation/Foundation.h>
EXTERN NSString const * _Nonnull const devBaseUrl;
#endif /* constants_h */
constants.m
#include "constants.h"
NSString const * _Nonnull const devBaseUrl = #"http://127.0.0.1:8000/";
main.m
#import <Foundation/Foundation.h>
#import "constants.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSLog(#"Constant value: %#", devBaseUrl);
// Prints: Constant value: http://127.0.0.1:8000/
}
return 0;
}
I would like to get the int value of my extern const by its name.
For example in my .h file:
extern const int MY_INT_CONST;
In my .m file:
const int MY_INT_CONST = 0;
What I want:
- (void) method {
int i = [getMyConstantFromString:#"MY_INT_CONST"];
}
How can I do that?
I searched in RunTime api and I did not find anything.
There's no simple way to do this. Neither the language nor the runtime provide a facility for this.
It can be done using the API of the dynamic loader to look up a symbol's address by its name.
// Near top of file
#include <dlfcn.h>
// elsewhere
int* pointer = dlsym(RTLD_SELF, "MY_INT_CONST");
if (pointer)
{
int value = *pointer;
// use value...
}
Note, that's a C-style string that's passed to dlsym(). If you have an NSString, you can use -UTF8String to get a C-style string.
No need for [getMyConstantFromString:#"MY_INT_CONST"];
directly use as follows
- (void) method {
int i = MY_INT_CONST;
}
I have a static library which contains some constants such as:
// constants.h
NSString* const KDefaultProtocol;
// constants.m
NSString* const kDefaultProtocol = #"https";
// OtherCode.m
NSString *s = kDefaultProtocol;
When I run an app which links to the library the value of kDefaultProtocol is nil. Why is that?
(constants.m is included in the library compile sources section).
// constants.h
NSString* const KDefaultProtocol;
This one is incorrect. You meant:
// constants.h
extern NSString* const KDefaultProtocol;
The reason you're not getting the warning you should is because you've used mismatched the case of the leading K (which raises the question of how OtherCode.m even compiles; I suspect this is not exactly the code in question).
Try it->
// constants.h
static NSString * const KDefaultProtocol = #"https";
I am currently having issues converting NSString to a const void *
Here is my code:
DoSomethingFunction:(const void *)parameter
[class DoSomeThingFunction:(const void *)passswordField.text]
Password field is a UITextfield. The value becomes null when I try and cast it.
I want passwordField.text to be a const void * so it can be used in the function.
It depends on function implementation. It can be like this:
NSString *string = #"text";
const void *parameter = CFBridgingRetain(string);
DoSomethingFunction(parameter);
If function has similar parameter handling
void DoSomethingFunction(const void *parameter) {
NSString *string = CFBridgingRelease(parameter);
NSLog(#"%#", string);
}
Try casting the result of one of the NSString's methods that return a C string:
– cStringUsingEncoding:
– getCString:maxLength:encoding:
– UTF8String
NSString Class Reference
Im digging for ways to enum objc object such as NSString, I remember there a new feature in a version of Xcode4+ which offering a new way to enum , but not clearly. Anyone know that?
OK, I answered myself. Guess I make a mistake.
This is the new feature I mentioned above:
typedef enum Language : NSUInteger{
ObjectiveC,
Java,
Ruby,
Python,
Erlang
}Language;
It's just a new syntax for enum in Xcode 4.4, but I'm so foolish to think we can exchange "NSUInteger" to "NSString".
So here is the way I found that works:
http://longweekendmobile.com/2010/12/01/not-so-nasty-enums-in-objective-c/
// Place this in your .h file, outside the #interface block
typedef enum {
JPG,
PNG,
GIF,
PVR
} kImageType;
#define kImageTypeArray #"JPEG", #"PNG", #"GIF", #"PowerVR", nil
...
// Place this in the .m file, inside the #implementation block
// A method to convert an enum to string
-(NSString*) imageTypeEnumToString:(kImageType)enumVal
{
NSArray *imageTypeArray = [[NSArray alloc] initWithObjects:kImageTypeArray];
return [imageTypeArray objectAtIndex:enumVal];
}
// A method to retrieve the int value from the NSArray of NSStrings
-(kImageType) imageTypeStringToEnum:(NSString*)strVal
{
NSArray *imageTypeArray = [[NSArray alloc] initWithObjects:kImageTypeArray];
NSUInteger n = [imageTypeArray indexOfObject:strVal];
if(n < 1) n = JPG;
return (kImageType) n;
}
FYI. The original author of the second example code created a category for enum handling. Just the thing for adding to your very own NSArray class definition.
#interface NSArray (EnumExtensions)
- (NSString*) stringWithEnum: (NSUInteger) enumVal;
- (NSUInteger) enumFromString: (NSString*) strVal default: (NSUInteger) def;
- (NSUInteger) enumFromString: (NSString*) strVal;
#end
#implementation NSArray (EnumExtensions)
- (NSString*) stringWithEnum: (NSUInteger) enumVal
{
return [self objectAtIndex:enumVal];
}
- (NSUInteger) enumFromString: (NSString*) strVal default: (NSUInteger) def
{
NSUInteger n = [self indexOfObject:strVal];
if(n == NSNotFound) n = def;
return n;
}
- (NSUInteger) enumFromString: (NSString*) strVal
{
return [self enumFromString:strVal default:0];
}
#end
Alternative way to use struct:
extern const struct AMPlayerStateReadable
{
__unsafe_unretained NSString *ready;
__unsafe_unretained NSString *completed;
__unsafe_unretained NSString *playing;
__unsafe_unretained NSString *paused;
__unsafe_unretained NSString *broken;
} AMPlayerState;
const struct AMPlayerStateReadable AMPlayerState =
{
.ready = #"READY",
.completed = #"COMPLETE",
.playing = #"PLAYING",
.paused = #"PAUSED",
.broken = #"BROKEN"
};
Then you can use like this:
NSString *status = AMPlayerState.ready;
Easy to use, readable.
Would be nice if someone update/edit answer with advantages/disadvantages of this approach.
Recommended way from apple docs:
You use the NS_TYPED_ENUM to group constants with a raw value type that you specify. Use NS_TYPED_ENUM for sets of constants that can't logically have values added in a Swift extension, and use NS_TYPED_EXTENSIBLE_ENUM for sets of constants that can be expanded in an extension.
Apple docs
typedef NSString *MyEnum NS_TYPED_ENUM;
extern MyEnum const MyEnumFirstValue;
extern MyEnum const MyEnumSecondValue;
extern MyEnum const MyEnumThirdValue;
in the .h file. Define your strings in the .m file
MyEnum const MyEnumFirstValue = #"MyEnumFirstValue"
MyEnum const MyEnumSecondValue = #"MyEnumSecondValue";
MyEnum const MyEnumThirdValue = #"MyEnumThirdValue";
Works as expected in both Objective-C
- (void)methodWithMyEnum:(MyEnum)myEnum { }
and Swift
func method(_ myEnum: MyEnum) { }
This will be validated by compiler, so you won't mix up indices accidentally.
NSDictionary *stateStrings =
#{
#(MCSessionStateNotConnected) : #"MCSessionStateNotConnected",
#(MCSessionStateConnecting) : #"MCSessionStateConnecting",
#(MCSessionStateConnected) : #"MCSessionStateConnected",
};
NSString *stateString = [stateStrings objectForKey:#(state)];
<nbsp;>
var stateStrings: [MCSessionState: String] = [
MCSessionState.NotConnected : "MCSessionState.NotConnected",
MCSessionState.Connecting : "MCSessionState.Connecting",
MCSessionState.Connected : "MCSessionState.Connected"
]
var stateString = stateStrings[MCSessionState.Connected]
UPDATE: A more Swifty way is to extend the enum with CustomStringConvertible conformance. Also, this way the compiler will safeguard to implement every new addition to the underlying enum (whereas using arrays does not), as switch statements must be exhaustive.
extension MCSessionState: CustomStringConvertible {
public var description: String {
switch self {
case .notConnected:
return "MCSessionState.notConnected"
case .connecting:
return "MCSessionState.connecting"
case .connected:
return "MCSessionState.connected"
#unknown default:
return "Unknown"
}
}
}
// You can use it like this.
var stateString = MCSessionState.connected.description
// Or this.
var stateString = "\(MCSessionState.connected)"
Update in 2017
Recent down votes drew my attention, and I'd like to add that enum is really easy to work with String now:
enum HTTPMethod: String {
case GET, POST, PUT
}
HTTPMethod.GET.rawValue == "GET" // it's true
Original Answer
Unfortunately I ended up using:
#define HLCSRestMethodGet #"GET"
#define HLCSRestMethodPost #"POST"
#define HLCSRestMethodPut #"PUT"
#define HLCSRestMethodDelete #"DELETE"
typedef NSString* HLCSRestMethod;
I know this is not what OP asked, but writing actual code to implement enum seems to be an overkill to me. I would consider enum as a language feature (from C) and if I have to write code, I would come up with some better classes that does more than enum does.
Update
Swift version seems to be prettier, although the performance can never be as good.
struct LRest {
enum HTTPMethod: String {
case Get = "GET"
case Put = "PUT"
case Post = "POST"
case Delete = "DELETE"
}
struct method {
static let get = HTTPMethod.Get
static let put = HTTPMethod.Put
static let post = HTTPMethod.Post
static let delete = HTTPMethod.Delete
}
}
I think you are looking for the inline array function. eg
#[#"stringone",#"stringtwo",#"stringthree"];
if not, i'm not sure you can enum objects.
you could however have a static array of strings and have the enum reference object at index.
This is how I do it, although it's not perfect. I feel the switch mechanism could be improved... also not positive about hash-collision resistance, don't know what apple uses under the hood.
#define ElementProperty NSString *
#define __ElementPropertiesList #[#"backgroundColor", #"scale", #"alpha"]
#define epBackgroundColor __ElementPropertiesList[0]
#define epScale __ElementPropertiesList[1]
#define epAlpha __ElementPropertiesList[2]
#define switchElementProperty(__ep) switch(__ep.hash)
#define caseElementProperty(__ep) case(__ep.hash)
-(void)setValue:(id)value forElementProperty:(ElementProperty)ep;
[self setValue:#(1.5) forElementProperty:epScale];
//Compiler unfortunately won't warn you if you are missing a case
switchElementProperty(myProperty) {
caseElementProperty(epBackgroundColor):
NSLog(#"bg");
break;
caseElementProperty(epScale):
NSLog(#"s");
break;
caseElementProperty(epAlpha):
NSLog(#"a");
break;
}