3

我目前正在为 iOS 创建一个客观的 c 框架,以帮助促进 API 和开发人员之间的交互。作为其中的一部分,我返回了各种只读对象数组,开发人员可以使用这些数组向用户显示信息。但是,我想确保向用户显示的对象仅来自框架,并且不能由使用框架的开发人员实例化。

我当前的实现使用了一个自定义构造函数初始化程序,它从 api 获取 JSON 来实例化自己。我知道访问自定义构造函数初始化程序的唯一方法是将其定义放在头文件中,这样不仅我自己可以访问它,开发人员也可以访问它。我知道当用户尝试使用默认构造函数初始化程序时,我可能会引发不一致异常-(id)init;,但我无法阻止他们创建自己的 JSON 字符串并调用我的自定义构造函数初始化程序。

我是否采取了正确的方法来保护我的私有框架免受使用它的开发人员的干扰?我还能如何解决这个问题以确保这些对象中数据的有效性?

资料来源:是否可以在 Objective-C 中将 -init 方法设为私有?

4

2 回答 2

3

您是正确的,由于其动态调度系统,Objective-C 本质上不允许真正的私有方法。但是,假设您的问题不是关于真正的安全性,而只是让您难以以不正确的方式使用该框架,那么您有几个选择。

一个简单、常见的解决方案是将您不想公开公开的方法的声明放在单独的头文件中的类别中。您仍然可以将这些方法的实现放在类的主实现文件中。所以,一个像这样的标题:

// MyClass+Private.h
@interface MyClass (Private)
- (void)aPrivateMethod;
@end

然后,在您需要访问这些私有方法的您自己的源文件中,您只需导入 MyClass+Private.h。

对于框架,您可以将每个头文件设置为 Public 或 Private。私有标头不会被复制到框架包中,因此对框架的用户不可见。您可以通过在 Xcode 中打开 Utilities 窗格(右侧滑出窗格),选择有问题的标题,然后在“Target Membership”下相关行的第二列中选择 Private。

于 2013-03-14T16:53:35.410 回答
0

基于 Andrew Madsen 的解决方案,我最终使用的是为每个对象设置两个不同的头文件;一种是公开的,一种是私人的。公共标头仅包含开发人员访问只读属性所需的信息。然后我的私有标头导入公共标头,还包含一个类别,其中包含我需要在 SDK 中使用的所有方法调用(包括初始化程序)。然后我将私有标头导入到我的实现中。结构如下所示:

公共头文件 MyObject.h

#import <Foundation/Foundation.h>

@interface MyObject : NSObject
    @property (nonatomic, retain, readonly) NSString *myValue;
@end

私有头文件 MyObject+Private.h

#import "MyObject.h"
@interface MyObject (Private)
    +(MyObject*)MyObjectFromJSONString:(NSString*)JSONString;
    -(id)initWithJSON:JSONString:(NSString*)JSONString
@end

私有实现 MyObject.m

#import "MyObject+Private.h"
@implementation MyObject

@synthesize myValue = _myValue; //_myValue allows local access to readonly variable

- (id)init {
    @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"-init is not a valid initializer for the class MyObject" userInfo:nil];
    return nil;
}


+(MyObject*)MyObjectFromJSONString:(NSString*)JSONString;
{
    return [[MyObject alloc]initWithJSON:JSONString];
}


-(id)initWithJSON:JSONString:(NSString*)JSONString
{
    self = [super init];
    if(self){
        //parse JSON
        _myValue = JSONString;
    }
    return self;
}
于 2013-03-14T20:02:19.620 回答