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],并且调试更容易,因为常量具有运行时字符串值。

对于可变变量,安全的方法是采用信号模式

@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

最新更新