在Objective-C中使用类似C的静态变量是不好的做法吗?

时间:2013-05-28 20:55:24

标签: ios objective-c static singleton class-variables

我想要做的就是为我的(流捕获)应用程序创建一个实用程序类,从我的网站获取设置。我想从其他文件中将其称为简单的[RemoteConfig updateSettings];

我的目标是使用此远程配置实用程序,而不会为我抓取远程设置的每种情况都设置对象。

目标C中的静态/类变量和方法的信息是模糊的,非常自以为是,所以经过大量的实验,我得到了这个。但它看起来很有趣,这让我觉得有些不对劲。

RemoteConfig.h 只是声明 +(void)updateSettings 方法。

这是我的 RemoteConfig.m

#import "RemoteConfig.h"

static NSMutableData* _configData;
static NSString* url = @"http://local.namehidden.com:90/json.html";
static int try;

@implementation RemoteConfig

+(void) updateSettings
{
    NSString *identifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];

    //Create URL request
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
                                                           cachePolicy: NSURLRequestReloadIgnoringCacheData
                                                       timeoutInterval: 10];

    [request setHTTPMethod: @"POST"];
    NSString *post = [NSString stringWithFormat:@"id=%@", identifier];
    NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding];
    [request setHTTPBody:postData];

    NSURLConnection* connection = [NSURLConnection connectionWithRequest:request
                                                                delegate:self];
    [connection start];
}

///////////////////////////// DELEGATE METHODS ///////////////////////////////////

+(void)connection:(NSConnection*)conn didReceiveResponse:(NSURLResponse*)response
{
       if (_configData == NULL) {
        _configData = [[NSMutableData alloc] init];
    }
    [_configData setLength:0];
    NSLog(@"didReceiveResponse: responseData length:(%d)", _configData.length);
}

/// and so on...

看起来很时髦,将C风格的变量放在@interface / @实现之上。很多人说尝试使用属性,有人说做静态方法单例技巧,我看过一个处理单例的小库,但这是我找到的最简单的解决方案。

我的问题 -

  • 这听起来很糟糕吗?
  • 这有什么限制?
  • 有哪些替代品,什么是最好的?

2 个答案:

答案 0 :(得分:4)

  

这听起来很糟糕吗?这有什么限制?

全局变量往往会施加一系列限制:

  • 他们经常无法正确清理资源
  • 不是线程安全的(例如,可以从一个线程使用或者可以为每个线程引入状态)
  • 他们未必可以安全地筑巢
  • 他们可以通过序列化请求来解决其中的一些问题 - 引入过度暂停和锁定。
  • 它们变得非常难以“安全地”延伸(即添加全局变量使其更加脆弱)
  • 它们很难测试,并且可能导致很难再现的错误
  

有哪些替代品,什么是最好的?

只需将这些变量移动到ivars,并创建该类的实例,而不是依赖于全局状态。然后,您可以以不会显着影响客户的方式进行扩展和抽象。

请注意static NSString* const url = @"http://local.namehidden.com:90/json.html";不是可变变量(添加const)。因此,只有_configDatatry需要为ivars。

答案 1 :(得分:0)

使用像这样的静态变量并不比使用Singleton安全。您仍然会遇到与线程安全相同的问题,例如Singleton当然更容易Mock,因此Singleton's可能会带来好处。

在这两种情况下,您都会引入全局可变状态(全局不可变状态是没有问题的)。这有多大问题取决于这些变量存在于调用层次结构中的哪个位置。如果您的大多数代码都是基于一些基于某些全局可变状态更改其输出的函数构建的,那么这将使您难以测试和分析代码。

因此,如果您确实引入了全局可变状态,请尝试:

  1. 在分层中尽可能放置它。意思是尽可能少的其他代码应该依赖于这个代码。

  2. 确保状态更改不会更改使用它的函数输出。例如。全局可变状态只是缓存可能有效。

  3. 如果您的程序的总代码很小,您可以使用全局状态,因为500行程序中的全局变量与500行类中的成员变量之间几乎没有差异。