[英]Change UISwitch's state from an NSObject class
我無法從NSData類訪問所有位於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的重新分配,但我不知道該怎么辦。
您不應從其他任何地方訪問出口,而應從擁有出口的視圖控制器中訪問。 另外,您想使網點變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字典鍵的名稱轉換為常量,以便在代碼的多個位置沒有相同的字符串文字。
您可以通過添加對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。
當您知道問題來自重新分配時,請不要重新分配它。 就這么簡單。 :-)
相反的,你需要的地方設置firstViewController
你的財產myNSDataClass
相應。 當您的firstViewController
實際上被實例化的那一刻可能會發生這種情況。 那在哪里取決於您的應用程序的體系結構。
如果您希望它“整潔”,則不要讓myNDataClass
(可能用作模型)直接訪問mySwitch
等。 讓它調用firstViewController
某些方法。 只有您的視圖控制器才會“知道”其控件並進行相應的設置。
在firstViewController.h
聲明這些方法應該可以解決問題。 但是,如果您在firstViewController
實現(確認)的協議中聲明它們,那將更加整潔。 不應在myNSDataClass.h
中包含firstViewConroller.h
, myNSDataClass.h
應包含此協議(也應包含.h文件)。
在[self.firstViewController.mySwitch setOn:NO animated:YES];
之前設置一個斷點[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];
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.