从NSObject类更改UISwitch的状态

时间:2014-03-26 12:46:16

标签: ios objective-c class allocation

我无法访问我的NSData Class中的UIViewController中的标签,滑块和开关。

到目前为止,这是我的代码:

FirstViewController.h

@interface FirstViewController : UIViewController 
@property (strong) IBOutlet UISwitch * mySwitch;
@property (strong) IBOutlet UISlider *myTransitionSlide;
@property (nonatomic,retain) IBOutlet UILabel *labelTest;

myNSDataClass.h

#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
@class FirstViewController;


@interface myNSDataClass : NSObject <UIApplicationDelegate,CBPeripheralManagerDelegate>
{
    FirstViewController *firstViewController;
}
@property (nonatomic, retain) FirstViewController *firstViewController;

myNSDataClass.m

- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests
{
    self.firstViewController = [[FirstViewController alloc]init];
    [[self.firstViewController labelTest]setText:@"text changed"];                                                  
    [self.firstViewController.myTransitionSlide setValue:1];
    [self.firstViewController.mySwitch setOn:NO animated:YES];
}

我知道问题来自FirstViewController的重新分配,但我不知道该怎么做。

4 个答案:

答案 0 :(得分:3)

您不应该从其他任何地方访问您的商店,而是从拥有它们的视图控制器访问您的商店。此外,你想要做出你的出路weak

要解决您的问题,您可以使用通知:

- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests
{
   [[NSNotificationCenter defaultCenter] postNotificationName:@"MyAppDidReceiveWriteRequestNotification" 
                                                       object:nil 
                                                     userInfo:@{@"text": @"text changed", @"switchOn": @(NO)}];
}

然后,在FirstViewController中,您将自己注册为该通知的观察者,例如在viewDidLoad中:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleDidReceiveWriteRequestNotification:)
                                                 name:@"MyAppDidReceiveWriteRequestNotification"
                                               object:nil];

}

你实现了处理程序:

- (void)handleDidReceiveWriteRequestNotification:(NSNotification *)note
{
  [self.labelTest setText:note.userInfo[@"text"]];
  [self.mySwitch setOn:[note.userInfo[@"switchOn"] boolValue] animated:YES];
}

你清理:

- (void)dealloc
{
   [[NSNotificationCenter defaultCenter] removeObserver:self];
}

就是这样。更干净。

此外,您需要将通知的名称和userInfo字典键的名称转换为常量,这样您的代码中的多个位置就不会有相同的字符串文字。

答案 1 :(得分:1)

您可以通过添加对FirstViewController的引用来使其工作。 在FirstViewController.m中为myNSDataClass对象添加属性或私有变量,例如:

//FirstViewController.m
@implementation FirstViewController {
    myNSDataClass *_myData;
}

稍后在viewDidLoad中添加对FirstViewController的引用:

-(void)viewDidLoad {
    //Your code here...
    _myData = [[myNSDataClass alloc] init];
    _myData.firstViewController = self;
}

下一步是删除内存泄漏,将myNSDataClass.h更改为: @class FirstViewController;

@interface myNSDataClass : NSObject <UIApplicationDelegate,CBPeripheralManagerDelegate>
@property (nonatomic, weak) FirstViewController *firstViewController; //<- use assign if you support OS < 4
//your code ..
@end

如果你不支持少于4的操作系统,你在实现文件中不需要@synthesize。

答案 2 :(得分:1)

当您知道问题来自重新分配时,请不要重新分配。 就这么简单。 :-)

而不是你需要某个地方相应地设置firstViewController的{​​{1}}属性。这可能发生在您的myNSDataClass实际上已经实现的那一刻。这取决于您的应用程序的体系结构。

如果你想要它“整洁”,那么不要让firstViewController(可能作为模型)直接访问myNDataClass等。让它调用mySwitch的某种方法。只有您的视图控制器会“知道”其控件并相应地进行设置。

firstViewController中声明这些方法应该可以解决问题。但是,如果您在firstViewController.h实现(确认)的协议中声明它们,它将更加整洁。不应在firstViewController中包含firstViewConroller.h,而应包括此协议(也是.h文件)。

答案 3 :(得分:1)

[self.firstViewController.mySwitch setOn:NO animated:YES];之前设置一个断点,你应该找到问题。如果您打印self.firstViewController.mySwitch,则元素应为 nil

因此,尝试在此时设置原始或初始化属性

例如

// FirstViewController.h

@interface FirstViewController : UIViewController
{
    BOOL switchState;
    NSString *lblTitle;
    float sliderValue;
}

-(void)setSwitchState:(BOOL)pSwitchState andLabelText:(NSString *)pLblTitle andSliderValue:(float)pSliderValue;

// FirstViewController.m

-(void)setSwitchState:(BOOL)pSwitchState andLabelText:(NSString *)pLblTitle andSliderValue:(float)pSliderValue
{
    switchState = pSwitchState;
    lblTitle = pLblTitle;
    sliderValue = pSliderValue;
}

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.labelTest] setText:pLblTitle];                                     
    [self.myTransitionSlide setValue:pSliderValue];
    [self.mySwitch setOn:pSwitchState animated:YES];
}

并在peripheralManager中

- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests
{
   // I don't know if this re-initialization is realy required, so I let it here.
   // If not, you should think of init it somewhere else use the solution with the NSNotificationCenter ;)
   self.firstViewController = [[FirstViewController alloc]init];
   self.firstViewController setSwitchState:NO andLabelText:@"text changed" andSliderValue:1];
}