I'm having an issue with a label not updating correctly in my UI. I have an Mac OS X app which uses a outline view to switch views. I want to simply have the date displayed to the user in a label on the view which is switched to (FirstViewController). When implemented alone in a new project I have no issue. But when implemented where the view changes, the value of the label does not update, in fact the console output indicates that _dateLabel is (null) even after being set prior. Any suggestions? I must be missing something quite fundamental!
Console output:
2014-08-30 19:54:22.719 OutlineView[10420:1613022] StringedText is 30 August 2014
2014-08-30 19:54:22.720 OutlineView[10420:1613022] label value is (null)
I include the following code:
//
// FirstViewContorller.h
// OutlineView
#import <Cocoa/Cocoa.h>
#interface FirstViewContorller : NSViewController
#property (weak) IBOutlet NSTextField *dateLabel;
-(void)updateDateScreen;
#end
//
// FirstViewContorller.m
// OutlineView
#import "FirstViewContorller.h"
#implementation FirstViewContorller
#synthesize dateLabel = _dateLabel;
-(void)updateDateScreen{
//date calculation for main window
NSDate *now = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterLongStyle];
NSString *stringedText = [formatter stringFromDate:now];
_dateLabel.stringValue = stringedText;
NSLog(#"StringedText is %#", stringedText);
NSLog(#"label value is %#", _dateLabel.value);
}
#end
//
// AppDelegate.m
// OutlineView
#import "AppDelegate.h"
#import "Book.h"
#import "FirstViewContorller.h"
#interface AppDelegate()
#property (weak) IBOutlet NSOutlineView *outlineView;
#property (weak) IBOutlet NSTreeController *booksController;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
//other code here
//Call the update method in FirstViewController to load date label
FirstViewContorller *instance = [[FirstViewContorller alloc]init];
[instance updateDateScreen];
}
//further unrelated code
#end
You have:
NSLog(#"label value is %#", _dateLabel.value);
And because it is outputting "null" you think that your value is "null" when in all likelihood it is _dateLabel that is null.
You are creating the instance object, but then calling a method that updates a UI object, which may not have been unarchived from the xib file by the time you are calling it. So although your date formatter is correctly creating a string, it is trying to set it on a nil object.
You can see this for yourself by examining the output of of:
NSLog(#"label is %#", _dateLabel);
which will probably return a "null" as well.
Related
This is my first post so apologies for any errors I make, but this has been frustrating me for hours now and I cannot find a solution.
I have an app that uses a UITabBarViewController that has 3 tabs: FirstViewController, SecondViewController and ThirdViewController.
I have an NSObject class (Manager) where I reach out to from my view controllers to pull information from the calendar. Which works perfectly fine when I use the FirstViewController, however, when I go to use the other view controllers it simply returns "null" but I know the instance method is being called because I put an NSLog in the instance method it returns a value, but this value isn't being passed onto view controllers two and three.
The code I am using is below.
AppDelegate.m
#import <UIKit/UIKit.h>
#import "EventManager.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>{
}
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, strong) EventManager *eventManager;
#end
AppDelegate.m
- (void)applicationDidBecomeActive:(UIApplication *)application {
self.eventManager = [[EventManager alloc] init];
}
EventManager.h
#import <Foundation/Foundation.h>
#import <EventKit/EKEventStore.h>
#interface EventManager : NSObject
#property (nonatomic, strong) EKEventStore *eventStore;
-(NSMutableArray *) fetchCalendars;
#end
EventManager.m
-(NSMutableArray *) fetchCalendars {
NSArray *EKCalendars = [self.eventStore calendarsForEntityType:EKEntityTypeEvent];
NSMutableArray *mutableCalendars = [[NSMutableArray alloc] initWithArray:EKCalendars];
NSLog(#"EKCalendars %#",EKCalendars);
return mutableCalendars;
}
FirstViewController.m
-(void)loadCalendars{
NSMutableArray *mutableCalendars = [self.appDelegate.eventManager fetchCalendars];
}
This works absolutely fine for loading the calendars.
SecondViewController.m
-(void)loadCalendars{
NSMutableArray *mutableCalendars = [self.appDelegate.eventManager fetchCalendars];
}
This returns null, however, the output from the NSLog[ NSLog(#"EKCalendars %#",EKCalendars)] gives the exact same output as when it code is ran for the First View Controller.
I can get the calendars from the altering the SecondViewController.m to read
-(void)loadCalendars{
EventManager *per= [[EventManager alloc]init];
calendarsArray = [per fetchCalendars];
}
But I just don't understand why I need to reinitialize the event manager as it is initialized in the applicationDidBecomeActive.
Thanks for any help you guy can give.
You can access the Application's AppDelegate using [UIApplication sharedApplication].delegate:
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSMutableArray *mutableCalendars = [appDelegate.eventManager fetchCalendars];
Need real help here!!!
I am trying to use data created in 1st class within the 2nd class. I have been searching Youtube and StackOverflow for over 1 week. Every time I think I am close, there is some element missing that I can not grasp. My latest attempt came from this site published in 2011 (Passing Data between classes objective-c) and while the application compiles, I can not see the data in the 2nd class.
More specific. I am using 2 classes because the data is gathered in groups (1st class) selected by the user and will be displayed on-screen in a table within the 2nd class. There are 6 NSMutable Arrays from the source passing to 6 different in the 2nd class. I will continue to try to solve, but I could use help.
Here is what I have devised from the 2011 article:
1st class .h code(partial):
#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>
#import "ReportsOutput.h"
//#class AppDelegate;
#class ReportsOutput;
#interface ReportsClass : NSWindowController<NSApplicationDelegate,NSMenuDelegate,NSWindowDelegate>{
ReportsOutput *ro;
//Shared Data arrays
NSMutableArray *tblYrScott;
NSMutableArray *tblYrExt;
NSMutableArray *tblYrYear;
NSMutableArray *tblYrType;
NSMutableArray *tblYrPrice;
NSMutableArray *tblYrDescription;
...... added code
#property(nonatomic,retain)NSMutableArray *tblYrScott;
#property(nonatomic,retain)NSMutableArray *tblYrExt;
#property(nonatomic,retain)NSMutableArray *tblYrType;
#property(nonatomic,retain)NSMutableArray *tblYrYear;
#property(nonatomic,retain)NSMutableArray *tblYrPrice;
#property(nonatomic,retain)NSMutableArray *tblYrDescription;
1st class .m code:
- (IBAction)btnShowDataOutput:(id)sender {
//pass data from Reports Class to Report Output Class
ReportsOutput *objReportsOutput = [[ReportsOutput alloc]init];
[objReportsOutput.tblScott setArray: tblYrScott];
[objReportsOutput.tblExt setArray:tblYrDescription];
[objReportsOutput.tblYear setArray:tblYrYear];
[objReportsOutput.tblType setArray:tblYrType];
[objReportsOutput.tblDescription setArray:tblYrDescription];
// open Reports Output Window
if (ro == nil){
ro = [[ReportsOutput alloc] initWithWindowNibName:#"ReportsOutput"];
}
[ro showWindow:nil];
}
2nd class .h code:
#import <Cocoa/Cocoa.h>
#import "ReportsClass.h"
#interface ReportsOutput : NSWindowController{
//shared data arrays
NSMutableArray *tblScott;
NSMutableArray *tblExt;
NSMutableArray *tblYear;
NSMutableArray *tblType;
NSMutableArray *tblPrice;
NSMutableArray *tblDescription;
}
#property(nonatomic,strong) NSMutableArray *tblScott;
#property(nonatomic,strong) NSMutableArray *tblExt;
#property(nonatomic,strong) NSMutableArray *tblYear;
#property(nonatomic,strong) NSMutableArray *tblType;
#property(nonatomic,strong) NSMutableArray *tblPrice;
#property(nonatomic,strong) NSMutableArray *tblDescription;
#end
2nd class .m code:
#import "ReportsOutput.h"
//#import "ReportsClass.h"
#interface ReportsOutput ()
#end
#implementation ReportsOutput
#synthesize tblScott;
#synthesize tblExt;
#synthesize tblType;
#synthesize tblPrice;
#synthesize tblYear;
#synthesize tblDescription;
- (void)windowDidLoad {
[super windowDidLoad];
}
-(void)awakeFromNib{
[self dataCheck];
}
-(void)dataCheck{
int a;
for (a=0; a<[self.tblScott count]; a++){
NSLog(#"#i,%d :%#: %#: %#: %#: %#: %#",a,[tblScott objectAtIndex:a],[tblExt objectAtIndex:a],[tblYear objectAtIndex:a],[tblType objectAtIndex:a],[tblPrice objectAtIndex:a],[tblDescription objectAtIndex:a]);
}
}
In btnShowDataOutput, you create objReportsOutput, but that object goes away as soon as the method ends. You don't need to create objReportsOutput. Instead, set the properties directly on the ReportsOutput window controller:
if (ro == nil){
ro = [[ReportsOutput alloc] initWithWindowNibName:#"ReportsOutput"];
}
ro.tblScott = self.tblYrScott
ro.tblExt = self.tblYrExt
ro.tblYear = self.tblYrYear
ro.tblType = self.tblYrType
ro.tblDescription = self.tblYrDescription
[ro showWindow:nil];
I have two different methods of trying to grab a variable from another class. The first one, which I would prefer using doesn't work - The second one, which I don't prefer does. Could someone please explain why?
AppDelegate.h
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate> {
NSString *someString;
}
#property (assign) IBOutlet NSWindow *window;
#property (retain, nonatomic) NSString *someString;
- (void)manualSetVariable;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "GrabFromAppDelegate.h"
#implementation AppDelegate
#synthesize someString;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
someString = #"The Variable";
NSLog(#"In AppDelegate (1): %#",someString);
GrabFromAppDelegate *getThis = [[GrabFromAppDelegate alloc] init];
getThis.varSet = someString;
}
- (void)manualSetVariable { // THIS METHOD WORKS (2)
someString = #"The Variable";
NSLog(#"In AppDelegate(2): %#",someString);
}
#end
GrabFromAppDelegate.h
#import <Foundation/Foundation.h>
#interface GrabFromAppDelegate : NSObject {
NSString *varSet;
IBOutlet NSTextField *variable;
}
#property(retain, nonatomic) NSString *varSet;
- (IBAction)showVariable:(id)sender;
- (IBAction)manuallyGrabVariable:(id)sender;
#end
GrabFromAppDelegate.m
#import "GrabFromAppDelegate.h"
#import "AppDelegate.h"
#implementation GrabFromAppDelegate
#synthesize varSet;
- (IBAction)showVariable:(id)sender {
if (varSet != NULL) {
[variable setStringValue:[NSString stringWithString:varSet]];
NSLog(#"Got String Using (1): %#",varSet);
}
}
- (IBAction)manuallyGrabVariable:(id)sender { // THIS METHOD WORKS (2)
AppDelegate *getString = [[AppDelegate alloc] init];
[getString manualSetVariable];
if ([getString someString] != NULL) {
[variable setStringValue:[NSString stringWithString:[getString someString]]];
NSLog(#"Got String Using (2): %#",[getString someString]);
}
}
#end
This is horribly wrong:
AppDelegate *getString = [[AppDelegate alloc] init];
That allocates an AppDelegate instance, but it's not [[NSApplication sharedApplication] delegate], so the getString instance will never execute the applicationDidFinishLaunching method and your someString iVar will never get set. If you'd set someString within an init function, [[AppDelegate alloc] init] would, of course, call init. But since getString isn't attached to an NSApplication instance, there's nothing delegating the applicationDidFinishLaunching method to it.
If you want to get a pointer to the application delegate, you can do:
AppDelegate *getString = [[NSApplication sharedApplication] delegate];
or, for brevity's sake:
AppDelegate *getString = [NSApp delegate];
In second method you are calling method from app delegate and value is set at that time in someString variable and you get response. However if you are setting value for a varibale in appDelegate using an instance the set value will passed to that particular instance of controller class not to all instances. Hence either you create a shared instance of that variable or call that particular instance
to get the value somestring by showVariable method.
I tried to cancel localNotifications with specific tag number. It's my favorite manner to use tag number for compare logic.
So, I subclassed UILocalNotification and add property NSInteger tag. Then use the subclass instance for scheduling localNotification.
CustomNotification *customNoti = [[CustomNotification alloc] init];
customNoti.fireDate = myDate;
customNoti.timeZone = [NSTimeZone defaultTimeZone];
customNoti.tag = self.tag; // crash
// error : -[UIConcreteLocalNotification setTag:]: unrecognized selector sent to instance 0x75a3630
Here is CustomNotification.h file
#import <UIKit/UIKit.h>
#interface CustomNotification : UILocalNotification
#property (nonatomic, assign) NSInteger tag;
#end
Why is it crash and 'unrecognized selector' message shown? Is UILocalNotification class special? I can't find any missed code.
I am very new to development in Objective C but have a lot of experience in object orientated development in c# ASP. I've been trying to make a simple iPhone app where a PickerView control is accessing a data source.
In my header file (InstaTwitViewController.h) I have declared the following:
#interface InstaTwitViewController : UIViewController
<UIPickerViewDataSource, UIPickerViewDelegate> {
NSArray* activities;
NSArray* feelings;
}
I now try to inititialise my arrays in the viewDidLoad functions in my InstaTwitViewController.m file:
activities = [[NSArray alloc] initWithObjects:#"sleeping", #"eating", #"thinking", nil];
feelings = [[NSArray alloc] initWithObjects:#"psyched", #"sad", #"happy", nil];
but when I run the code on the simulator I get a Thread 1: Program recieved signal "ESC_BAD_ACCESS" error on the first line of code (where I allocate data to the activities array).
I put a break point on the line and it recognises it as an NSArray called activities but says "Invalid Summary" at the end.
Does anyone know why I am getting this error? I have looked at many threads about the ESC_BAD_ACCESS error but none have seemed to have helped me.
.h
#interface InstaTwitViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate> {
NSArray* activities;
NSArray* feelings;
}
#property (nonatomic, retain) NSArray* activities;
#property (nonatomic, retain) NSArray* feelings;
#end
.m
#import "your.h"
#implementation InstaTwitViewController
#synthesize activities, feelings;
- (void)viewDidLoad {
[super viewDidLoad];
[self.activities addObject ~ /* Do your code here */];
}
#end
Becareful you should stay on self.~ if you don't want to lose your value.
By the way, I am Korean~ ^^;