【问题标题】:Singleton UIViewController单例 UIViewController
【发布时间】:2014-11-06 10:29:27
【问题描述】:

我正在尝试将随机类中的一些数据添加到我的 viewController,

所以为了始终保持相同的数据,我在我的 UIViewController 上做了一个单例,但它不起作用我从来没有在我的 tableview 上获得数据。

这是我添加到 UIViewController 中的内容:

+(id)sharedMBVC {
   static MBViewController *sharedMBVC ;
    @synchronized(self) {
        if (!sharedMBVC)
            sharedMBVC = [[MBViewController alloc] init];
        return sharedMBVC;
    }
}

在我的课堂上,我通过这样做来称呼它:

  MBViewController *vc = [MBViewController sharedMBVC];

我是否必须在某处设置我的 NSArrays 的内容,它们在 viewcontroller 的 viewDidLoad 中声明?或者还有其他事情要做。

PS:我在vc = (MBViewController *)[[[[UIApplication sharedApplication] delegate] window] rootViewController]; 之前在课堂上做,但现在我的 uiviewcontroller 不再是 rootview,这就是为什么我试图找到其他方法来访问它,我想最好的解决方案是做一个单例

你们能帮帮我吗

【问题讨论】:

  • 不要这样做。这是不好的。是什么让你想使用单例? 一种更好的方法。
  • @Fogmeister 主要的 pb 是现在我使用 AMSlideMenu,他的 MainVC 变成了 rootview,所以现在我没有如何访问我的 MBViewController 方法:s 我希望始终拥有当前的 MBViewController 和他的NSArrays 更新
  • 为什么需要从任何地方访问 MBViewController?只是为了获取数组吗?
  • @fourthnovember,好吧,我认为,从架构的角度来看,这些数组不属于 VMBiewController。我会将它们分离到一个数据层(例如某种 DataSource 类),并在您需要的任何地方保留对 DataSource 的引用。看看 Apple 的Second iOS App tutorial。它包含一个简单的数据层实现示例。
  • viewController + singleton = 这将破坏与视图控制器工作方式有关的一切。首先默认回到单例是一个坏主意。使 viewController 成为单例,我什至不知道会因此而中断。

标签: ios objective-c iphone uitableview uiviewcontroller


【解决方案1】:

好的,所以您遇到的问题是显示数组的 viewController 也“拥有”数组。这意味着(使用您当前的设置)能够更改数组,您需要获取 viewController 才能访问数组。

您需要通过从该 viewController 中删除数组来更改此设置。

您仍然可以使用单例来执行此操作(如果您愿意的话),但要创建一个名为 ArrayManager 之类的全新类。

这将包含数组和更新数组的所有方法。

例如,如果您的 viewController 有一个名为 - (void)addObjectToArray:(id)object; 的方法,则将该方法移至 ArrayManager 单例类。

现在在你显示的 viewController 中你可以做...

[[ArrayManager sharedInstance] getSomeDataFromTheArray];

在必须更新数组的地方你可以做...

[[ArrayManager sharedInstance] addObjectToArray:someObject];

现在你完全不用担心传递 viewController 了。

这可以通过各种方式来改善。例如,您可能根本不需要单例,只需将这个 ArrayManager 类并注入通过设置属性等将其插入需要它的地方......

此外,您还可以使用 CoreData 来存储信息。

另外,您的单例方法不正确。苹果推荐的方式是使用...

+ (ArrayManager *)sharedInstance
{
    static dispatch_once_t once;
    static ArrayManager *arrayManager;
    dispatch_once(&once, ^{
        arrayManager = [[ArrayManager alloc] init];
    });
    return arrayManager;
}

重写你的单例...

.h 文件

@interface PTVData : NSObject

+ (PTVData *)sharedInstance;

- (void)addSensor:(NSString *)sensorName;
- (NSInteger)numberOfSensors;
- (NSString *)sensorAtIndex:(NSUInteger)index;

@end

.m 文件

@interface PTVData ()

@property (nonatomic, strong) NSMutableArray *sensors;

@end

@implementation PTVData

+ (PTVData)sharedInstance
{
    static PTVData *sharedPTVData;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedPTVData  = [[PTVData alloc] init];
    });
    return sharedPTVData;
}

- (id)init
{
    if (self = [super init]) {
        _sensors = [[NSMutableArray alloc] initWithObject:@"None"];
    }
    return self;
}

- (void)addSensor:(NSString *)sensorName
{
    if (sensorName
        && ![self.sensors containsObject:sensorName]) {
        [self.sensors addObject:sensorName];
    }
}

- (NSInteger)numberOfSensors
{
    return self.sensors.count;
}

- (NSString *)sensorAtIndex:(NSUInteger)index
{
    return self.sensors[index];
}

@end

通过这样做,您可以隐藏实际的传感器阵列。它只能通过PTVData 类直接访问。

现在在你的 tableview 方法中你可以做...

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [[PTVData sharedInstance] numberOfSensors];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = ...

    cell.textLabel.text = [[PTVData sharedInstance] sensorAtIndex:indexPath.row];

    return cell;
}

【讨论】:

  • 我做到了,我得到了相同的 pb 数据没有显示,在 viewDidLoad 我调用我的单例类 MyClass *myclass= [MyClass sharedInstance];然后 _array1 = myclass.array1;
  • 当我在 viewcontroller 中调用 adddata 时,该方法调用 Myclass 的 adddata,我把断点放在那里,但是当我回到我的 viewcontroller 之后,我做了 array1=myclass.array1;一次又一次 [self.tableview reloadData];但他从不重新加载我的意思是他不调用任何 tableview 方法:s,你知道我为什么这样做吗?
  • @fourthnovember 你能把一些代码粘贴到 gist 上吗?如果没有看到代码,几乎不可能提供帮助。
  • @fourthnovember 不要添加答案。只需编辑您的问题。
  • opss 我没有看到你的评论:请检查一下并告诉我你的想法
【解决方案2】:

嗯,我认为,从架构的角度来看,这些数组不属于MBViewController。我会将它们分离到一个数据层(例如某种 DataSource 类),并在您需要的任何地方保留对 DataSource 的引用。看看 Apple 的Second iOS App tutorial。它包含一个简单的数据层实现示例。 更新: 另外,请查看 Fogmeister 的答案。他很好地解释了这种对象的可能实现:)

至于为什么单例在这种情况下没有按您的预期工作,我相信原因可能如下: 如果您通过 segue(我认为您是)到达 MBViewController,那么每次都会创建一个新的 MBViewController 实例。如果您使用 self.myArray 从 MBViewController 访问您的数组,那么您将访问这个新的MBViewControllermyArray。虽然 sharedMBVC 保留了对共享实例的引用,但它只是被 segue 忽略了。

【讨论】:

    【解决方案3】:

    在我的 ViewController.h 中

    @property PTVData *ptvdata; 
    

    ViewController.m 查看Didload

       ptvdata = [PTVData sharedPTVData];
        _sensorsCollection = ptvdata.sensorsCollection; 
    

    然后我的 ViewController.m 中有一个方法

    - (void) addSensorToCollection:( NSString *)sensorName{
    
      [[PTVData sharedPTVData] addSensorToCollection:sensorName];
        _sensorsCollection = ptvdata.sensorsCollection;
    
           [ self.tableView reloadData];
    
    
        }
    }
    

    我的 PTVData.h

    @property (nonatomic,retain) NSMutableArray *sensorsCollection;
    +(id)sharedPTVData;
    -(id) init;
    - (void) addSensorToCollection:( NSString *)sensorName;
    @end
    

    我的 PTVData.m

    @synthesize sensorsCollection = _sensorsCollection;
    
    + (id)sharedPTVData {
        static PTVData *sharedPTVData  = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedPTVData  = [[self alloc] init];
        });
        return sharedPTVData;
    }
    
    - (id)init {
        if (self = [super init]) {
               _sensorsCollection   = [[NSMutableArray alloc]initWithObjects:@"None", nil];
        }
        return self;
    }
    - (void) addSensorToCollection:( NSString *)sensorName{
    
        if (![_sensorsCollection containsObject:sensorName]&& sensorName!= nil) {
            [_sensorsCollection addObject:sensorName];
    
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      不要在 viewDidLoad 中初始化您的数组,而是在 sharedMBVC 函数中进行。这将确保每次视图加载时都不会重新初始化数组。

      【讨论】:

      • 这是合理的,但它并不能以任何方式回答 OP 的问题。它应该是一个评论。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-03
      • 2014-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-27
      相关资源
      最近更新 更多