2

我有一个实例变量 apiEndpoint ,我不想从除 init 之外的任何地方设置它,我只希望它对类是私有的。如果我使用实例变量而不是属性可以吗?

ApiWrapper.h

#import <Foundation/Foundation.h>

@interface ApiWrapper : NSObject
{
    NSString *apiEndpoint;
}

- (void) initWithApiEndpoint:(NSString *) newApiEndpoint;


+ (NSString *)getApiEndpoint:(NSString *) storeUrl;
+ (NSString *)getApiEndpointWithoutIndexDotPHP:(NSString *) storeUrl;
@end

ApiWrapper.m

#import "ApiWrapper.h"


@implementation ApiWrapper
- (void) initWithApiEndpoint:(NSString *) newApiEndpoint;
{
    apiEndpoint = newApiEndpoint;
}
+ (NSString *)getApiEndpoint:(NSString *) storeUrl
{
    if (![storeUrl hasPrefix:@"http://"] && ![storeUrl hasPrefix:@"https://"])
    {
        NSLog(@"%@ missing http", storeUrl);
    }

    return nil;
}

+ (NSString *)getApiEndpointWithoutIndexDotPHP:(NSString *) storeUrl
{

}

@end
4

3 回答 3

4

是的,可以使用 ivars。但是,属性的​​优点在于它们为您创建了 getter 和 setter,它们不仅仅是读取或写入变量值,还可以包括对象保留管理、线程安全读取和写入等内容。

有一种方法可以通过在类的 .m 文件中的匿名类扩展中声明它来创建“私有属性”。请注意,您仍然必须在 init 和 dealloc 方法中使用支持该属性的 ivar。您的代码将如下所示:

#import "ApiWrapper.h"

@interface ApiWrapper ()
@property (strong,nonatomic) NSString* apiEndpoint;

@end

@implementation ApiWrapper

- (id) initWithApiEndpoint:(NSString *) newApiEndpoint;
{
    self = [super init]
    if ( self ) {
        _apiEndpoint = newApiEndpoint;
    }

    return self;
}
于 2013-01-28T03:19:43.737 回答
2

在这里查看我的答案:
我应该在接口中声明变量还是在 Objective-C 弧中使用属性?

总结版:

  • 尽可能声明属性
  • 不要单独声明 iVar
  • 不要@synthesize
  • 在您的 .h 文件中找到尽可能少的属性
  • 在 .m 文件的类扩展中找到尽可能多的属性

我要补充的唯一一点 - 如果出于任何原因您使用 iVars,使用像 _leading _underscores 这样的明确约定,以便我们在阅读您的代码时知道您在做什么。

于 2013-01-28T03:48:50.160 回答
2

我同意 claireware 的建议,即在您的私有类扩展中使用私有属性。另一种方法,如果您希望其他类能够看到它,但不能改变它,则将其定义为只读属性:

在 ApiWrapper.h 中:

#import <Foundation/Foundation.h>

@interface ApiWrapper : NSObject

@property (nonatomic, strong, readonly) NSString *apiEndpoint;

- (id) initWithApiEndpoint:(NSString *) newApiEndpoint;

+ (NSString *)getApiEndpoint:(NSString *) storeUrl;
+ (NSString *)getApiEndpointWithoutIndexDotPHP:(NSString *) storeUrl;

@end

在 ApiWrapper.m 中:

#import "ApiWrapper.h"

@interface ApiWrapper ()

@property (nonatomic, strong) NSString *apiEndpoint;

@end

@implementation ApiWrapper

- (id) initWithApiEndpoint:(NSString *) newApiEndpoint;
{
    self = [super alloc];
    if (self)
    {
        _apiEndpoint = newApiEndpoint;
    }

    return self;
}

@end

两个注意事项:

  1. init...方法不应有void返回类型。init方法应该总是返回一个初始化的对象。

  2. 如果您使用属性,请记住不要在 Initializer Methods 和 dealloc 中使用访问器方法。


显然,如果您真的想使用 ivar(我同意其他人的观点,您可以通过属性实现您想要的),它只是:

ApiWrapper.h:

#import <Foundation/Foundation.h>

@interface ApiWrapper : NSObject

- (id) initWithApiEndpoint:(NSString *) newApiEndpoint;

+ (NSString *)getApiEndpoint:(NSString *) storeUrl;
+ (NSString *)getApiEndpointWithoutIndexDotPHP:(NSString *) storeUrl;

@end

在 ApiWrapper.m 中:

#import "ApiWrapper.h"

@interface ApiWrapper ()
{
    NSString *apiEndpoint;
}
@end

@implementation ApiWrapper

- (id) initWithApiEndpoint:(NSString *) newApiEndpoint;
{
    self = [super alloc];
    if (self)
    {
        apiEndpoint = newApiEndpoint;
    }

    return self;
}

@end
于 2013-01-28T03:32:48.300 回答