2014-03-26 45 views
0

我無法從我的NSData類訪問我的標籤,滑塊和開關,它們都位於UIViewController中。從NSObject類更改UISwitch的狀態

這是到目前爲止我的代碼:

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的重新分配,但我不知道該怎麼辦。

回答

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 

你並不需要在實現文件@synthesize,如果你不支持OS小於4

+0

這隻需要將某些東西分配給myNSDataClass對象的非必要和錯誤的新分配問題 –

+0

但是,iOS 4.3之前沒有官方支持iOS 4.3的安裝,佔所有iOS的2-3%設備。當提到OS少於4的支持時,你在說什麼? –

+0

@SergiusGee我在說的是支持ARC的iOS 4.3 - 操作系統低於4.3,你不能使用弱關鍵字。 – Greg

1

當你知道這個問題來自於重新分配,那麼不重新分配它。 就是這麼簡單。 :-)

取而代之的是,您需要在某處設置myNSDataClassfirstViewController相應的屬性。當你的firstViewController實際存在時,可能會發生這種情況。那取決於你的應用程序的體系結構。

如果你想要它'整潔',那麼不要讓myNDataClass(可能作爲模型)直接訪問mySwitch等。讓它調用一些方法firstViewController。只有你的視圖控制器可以「知道」它的控制並相應地設置它們。

聲明這些方法在firstViewController.h應該做的伎倆。然而,如果你在firstViewController執行(確認)的協議中聲明它們,它會更加整潔。您應該包含此協議(也是.h文件),而不是將firstViewConroller.h包含在myNSDataClass.h中。

1

[self.firstViewController.mySwitch setOn:NO animated:YES];之前設置一個斷點,您應該可以找到問題。如果您打印出self.firstViewController.mySwitch,則該元素應爲

所以儘量在這一點上

例如設置原始或初始化屬性

// 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]; 
} 
+0

每次調用'peripheralManager:didReceiveWriteRequests:'方法時,您仍然在創建'FirstViewController'的新實例。 –

+0

我不知道他的代碼的其餘部分,所以我放棄了這部分希望,它需要這樣做,他知道他在那裏做什麼;)否則我也會重新編寫一個代理解決方案 – geo