[英]Usage of global variables in Objective-C
在Objective-C中使用全局变量的最佳实践是什么?
现在,我有一个.h / .m类,其中包含所有全局变量,并且在其中声明通用函数的方式如下:
。H
BOOL bOne;
NSInteger iOne;
BOOL bTwo;
BOOL nThreee;
id NilOrValue(id aValue);
BOOL NSStringIsValidEmail(NSString *email);
BOOL NSStringIsValidName(NSString *name);
BOOL NSStringIsVaildUrl ( NSString * candidate );
BOOL NSStringIsValidPhoneNumber( NSString *phoneNumber );
NSString *displayErrorCode( NSError *anError );
NSString *MacAdress ();
NSString* md5( NSString *str );
#define IS_IPHONE ( [[[UIDevice currentDevice] model] isEqualToString:@"iPhone"] )
#define IS_WIDESCREEN (fabs((double)[[UIScreen mainScreen] bounds].size.height - (double) 568) < DBL_EPSILON)
#define IS_IPHONE_5 ( IS_WIDESCREEN )
#define kSettings [NSUserDefaults standardUserDefaults];
#define EMPTYIFNIL(foo) ((foo == nil) ? @"" : foo)
.m
BOOL bOne = NO;
NSInteger iOne = 0;
BOOL bTwo = NO;
BOOL nThreee = NO;
id NilOrValue(id aValue) {
if ((NSNull *)aValue == [NSNull null]) {
return nil;
}
else {
return aValue;
}
}
NSString* md5( NSString *str )
{
// Create pointer to the string as UTF8
const char *ptr = [str UTF8String];
// Create byte array of unsigned chars
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
// Create 16 byte MD5 hash value, store in buffer
CC_MD5(ptr, (CC_LONG)strlen(ptr), md5Buffer);
// Convert MD5 value in the buffer to NSString of hex values
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x",md5Buffer[i]];
return output;
}
BOOL NSStringIsVaildUrl (NSString * candidate) {
NSString *urlRegEx =
@"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+";
NSPredicate *urlTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", urlRegEx];
return [urlTest evaluateWithObject:candidate];
}
BOOL NSStringIsValidEmail(NSString *email) {
NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
if (email.length == 0) {
return YES;
}else {
if (![emailTest evaluateWithObject:email]) {
return NO;
}else {
return YES;
}
}
}
BOOL NSStringIsValidName(NSString *name) {
NSString *nameRegex = @"^([a-zA-Z'-]+)$";
NSPredicate *nameTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", nameRegex];
if (name.length == 0) {
return YES;
}else {
if (![nameTest evaluateWithObject:name]) {
return NO;
} else {
return YES;
}
}
}
BOOL NSStringIsValidPhoneNumber(NSString *phoneNumber) {
NSError *error = NULL;
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber error:&error];
NSRange inputRange = NSMakeRange(0, [phoneNumber length]);
NSArray *matches = [detector matchesInString:phoneNumber options:0 range:inputRange];
// no match at all
if ([matches count] == 0) {
return NO;
}
// found match but we need to check if it matched the whole string
NSTextCheckingResult *result = (NSTextCheckingResult *)[matches objectAtIndex:0];
if ([result resultType] == NSTextCheckingTypePhoneNumber && result.range.location == inputRange.location && result.range.length == inputRange.length) {
// it matched the whole string
return YES;
}
else {
// it only matched partial string
return NO;
}
}
NSString *MacAdress () {
int mgmtInfoBase[6];
char *msgBuffer = NULL;
size_t length;
unsigned char macAddress[6];
struct if_msghdr *interfaceMsgStruct;
struct sockaddr_dl *socketStruct;
NSString *errorFlag = NULL;
// Setup the management Information Base (mib)
mgmtInfoBase[0] = CTL_NET; // Request network subsystem
mgmtInfoBase[1] = AF_ROUTE; // Routing table info
mgmtInfoBase[2] = 0;
mgmtInfoBase[3] = AF_LINK; // Request link layer information
mgmtInfoBase[4] = NET_RT_IFLIST; // Request all configured interfaces
// With all configured interfaces requested, get handle index
if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0)
errorFlag = @"if_nametoindex failure";
else
{
// Get the size of the data available (store in len)
if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0)
errorFlag = @"sysctl mgmtInfoBase failure";
else
{
// Alloc memory based on above call
if ((msgBuffer = malloc(length)) == NULL)
errorFlag = @"buffer allocation failure";
else
{
// Get system information, store in buffer
if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
errorFlag = @"sysctl msgBuffer failure";
}
}
}
// Befor going any further...
if (errorFlag != NULL)
{
NSLog(@"Error: %@", errorFlag);
free(msgBuffer);
return errorFlag;
}
// Map msgbuffer to interface message structure
interfaceMsgStruct = (struct if_msghdr *) msgBuffer;
// Map to link-level socket structure
socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);
// Copy link layer address data in socket structure to an array
memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);
// Read from char array into a string object, into traditional Mac address format
NSString *macAddressString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
macAddress[0], macAddress[1], macAddress[2],
macAddress[3], macAddress[4], macAddress[5]];
NSLog(@"Mac Address: %@", macAddressString);
// Release the buffer memory
free(msgBuffer);
return macAddressString;
}
这是一个不好的解决方案吗? 如果是,我将如何以最佳方式使用全局变量?
全局变量总是会引起问题,但是在某些情况下它很有用,我们需要两种类型的全局变量,一种是常量,第二种是可以改变值的变量...
建议创建不可变的全局变量,而不是行内字符串常量(难以重构且不进行编译时检查)或#defines(不进行编译时检查)。 您可以按照以下方式进行操作...
在MyConstants.h中:
extern NSString * const MyStringConstant;
在MyConstants.m中:
NSString * const MyStringConstant = @"MyString";
然后在任何其他.m文件中:
#import "MyConstants.h"
...
[someObject someMethodTakingAString:MyStringConstant];
...这样,您便获得了编译时检查,以确保您没有误拼写一个字符串常量,可以在比较常量时检查指针相等性而不是字符串相等性[1],并且由于常量,调试更容易具有运行时字符串值。
对于可变变量,安全的方法是采用singalton模式
@interface VariableStore : NSObject
{
// Place any "global" variables here
}
// message from which our instance is obtained
+ (VariableStore *)sharedInstance;
@end
@implementation VariableStore
+ (VariableStore *)sharedInstance
{
// the instance of this class is stored here
static VariableStore *myInstance = nil;
// check to see if an instance already exists
if (nil == myInstance) {
myInstance = [[[self class] alloc] init];
// initialize variables here
}
// return the instance of this class
return myInstance;
}
@end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.