簡體   English   中英

從NSObject類更改UISwitch的狀態

[英]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.hmyNSDataClass.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM