我无法访问我的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的重新分配,但我不知道该怎么做。
答案 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];
}