I'm sure I'm just missing something simple here, but can't find the answer though I looked in the other examples here, my code seems to be the same.
I'm trying to define a global class with some methods that I can access from the other classes in my project. I can define it, but can not access the methods from my other classes, though I always import the global class header to the class where I want to use the method. Heres the code:
1st The Global class def:
#import <Foundation/Foundation.h>
#interface GlobalMethods : NSObject {}
- (unsigned long long)getMilliSeconds:(NSDate*)d;
- (NSDate *)getDateFromMs:(unsigned long long)ms;
#end
#import "GlobalMethods.h"
#implementation GlobalMethods
//SET DATE TO MILLISECONDS 1970 EPOCH
- (unsigned long long)getMilliSeconds:(NSDate*)d
{
unsigned long long seconds = [d timeIntervalSince1970];
unsigned long long milliSeconds = seconds * 1000;
return milliSeconds;
}
// GET DATE FROM MILLISECONDS 1970 EPOCH
- (NSDate *)getDateFromMs:(unsigned long long)ms
{
unsigned long long seconds = ms / 1000;
NSDate *date = [[NSDate alloc] initWithTimeIntervalSince1970: seconds];
return date;
}
#end
and then where I want to use my methods in another class:
#import "GlobalMethods.h"
// GET MILLISECONDS FROM 1970 FROM THE PICKER DATE
NSDate *myDate = _requestDatePicker.date;
milliSeconds = [self getMilliSeconds: myDate];
Error is : No visable interface for viewcontroller declares the selector getMilliSeconds.
Thanks for the help with this.
You are trying to call the getMilliSeconds: method (which is an instance method of the GlobalMethods class) on an instance of your view controller class. That is the cause of the error.
As written you need to change this line:
milliSeconds = [self getMilliSeconds: myDate];
to:
GlobalMethods *global = [[GlobalMethods alloc] init];
milliSeconds = [global getMilliSeconds:myDate];
A better solution is to first change all of the instance methods of your GlobalMethods class to be class methods. In other words, in both the .h and .m file for GlobalMethods, change the leading - to a + for both methods.
Then in your view controller you can do:
milliSeconds = [GlobalMethods getMilliSeconds:myDate];
Related
I am creating a simple drum machine. This function controls the time between each sample that is played (thus controlling the tempo of the drum machine). I need to control the tempo with a slider, so I'm hoping to be able to control the 'time duration until next step' value with this if possible. However, when I have tried to do this, it tells me "time is part of NSDate"
-(void)run
{
#autoreleasepool
{
// get current time
NSDate* time = [NSDate date];
// keeping going around the while loop if the sequencer is running
while (self.running)
{
// sleep until the next step is due
[NSThread sleepUntilDate:time];
// update step
int step = self.step + 1;
// wrap around if we reached NUMSTEPS
if (step >= NUMSTEPS)
step = 0;
// store
self.step = step;
// time duration until next step
time = [time dateByAddingTimeInterval:0.5];
}
// exit thread
[NSThread exit];
}
}
This tells me NSTimeInterval is an incompatable type
// time duration until next step
time = [time dateByAddingTimeInterval: self.tempoControls];
Here is where the slider is declared
.m
- (IBAction)sliderMoved:(UISlider *)sender
{
AppDelegate* app = [[UIApplication sharedApplication] delegate];
if (sender == self.tempoSlider)
{
PAEControl* tempoControl = app.tempoControls[app.editIndex];
tempoControl.value = self.tempoSlider.value;
}
}
.h
#interface DetailController : UIViewController
#property (weak, nonatomic) IBOutlet UISlider *tempoSlider;
- (IBAction)sliderMoved:(UISlider *)sender;
Any help would me much appriciated, thanks in advance.
It looks like self.tempoControls is an array of PAEControl objects. The method named dateByAddingTimeInterval: needs an argument of type NSTimeInterval (aka double). It looks like you're trying to pass in this array instead.
Try changing this line -
time = [time dateByAddingTimeInterval: self.tempoControls];
To maybe this -
PAEControl* tempoControl = self.tempoControls[self.editIndex];
time = [time dateByAddingTimeInterval: (NSTimeInterval)tempoControl.value];
On another note, if this is all running on the main thread, be aware that you are blocking it and the UI will become very unresponsive.
i am doing one application.In that i have to show the time for how much time user is in the application.For that,i calculated the difference between application opened time and current time for every one second and showing.But if i try to change the device time,that result also changing.But i want to show the exact result if user change the time also.So how to get the exact correct time based on that timezone.
You can set a default time zone to GMT for your application in initialize method.
#interface AppDelegate ()
#property (nonatomic, strong) NSDate startDate;
#end
#implementation AppDelegate
+ (void)initialize
{
[NSTimeZone setDefaultTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
self.startDate = [NSDate date];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"User has stayed for %4.2f seconds.", [[NSDate date] timeIntervalSinceDate:self.startDate]);
}
In addition to that, don't forget to set time zone for your NSDateFormatter instances when you convert a string representation of a date into actual NSDate instance.
I'm just beginning with XCode and coding for iOS, have the following problem. I want to add a function that sets UITextField values in the ViewController based around the value from a UIStepper. The code actually handles formatting three UITextFields, cut it to one to shorten the example. This code works fine:
- (IBAction)Temp_Stepper_Changed:(UIStepper *)sender {
integer_t stepperValue = (integer_t) sender.value;
NSString *temp_format = [[NSString alloc]
initWithFormat: #"%%.%df",stepperValue];
double fahrenheit = [_TempF_Text.text doubleValue];
NSString *FresultString = [[NSString alloc]
initWithFormat: temp_format,fahrenheit];
_TempF_Text.text = FresultString;
}
I have several places I want to do this, so want to create a function to call, and so I put this function into the view controller's .m file:
void Temp_Text_Update (double F_Temp){
NSString *FresultString = [[NSString alloc]
initWithFormat: #"%.2f",F_Temp];
_TempF_Text.text = FresultString;
}
The function won't compile, results in error:
use of undeclared identifier '_TempF_Text'
Without the line, it compiles fine, can call the function, pass values, etc. I had assumed (remember, beginning at this) as the UIStepper had _TempF_Text in it's scope, the function being in the same .m file would as well. Is there some magic happening behind the scenes that allows the IBAction type calls to access any value from the ViewController items, but my function is missing said magic? I'll also need the UIStepper value to complete the function. This was built using Storyboard, control-drag for outlets and actions, header file is:
#interface TemperatureViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *TempF_Text;
#property (weak, nonatomic) IBOutlet UIStepper *Temp_Stepper;
- (IBAction)TempF_CnvButton:(id)sender;
- (IBAction)Temp_Stepper_Changed:(UIStepper *)sender;
I've spent a few hours searching, including this site, found references from one ViewController to another and so forth, but doesn't really match; tried a few things anyway, but nothing worked (though some yielded extra errors). I suspect it is so obvious and simple as to not be asked, but I've run out of ideas and any help would be appreciated.
To answer the specific question, the correct syntax for the signature you're trying to write would look like this:
- (void)Temp_Text_Update:(double)F_Temp {
This says we have a method named Temp_Text_Update: that takes a double parameter called F_Temp and doesn't return anything.
A more general solution would be to use NSNumberFormatter to go between strings and doubles in a locale sensitive way, something like this:
// get a double from a string
- (double)doubleFromString:(NSString *)string {
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *number = [formatter numberFromString:string];
return [number doubleValue];
}
// get a string from a double:
- (NSString *)stringFromDouble:(double)aDouble {
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
return [formatter stringFromNumber:[NSNumber numberWithDouble:aDouble]];
}
Then your computing functions would look like this:
NSString *text = self.someControlView.text;
double aDouble = [self doubleFromString:text];
// do computation on aDouble, resulting in
double result = // whatever
[self setOutputTextWithResult:result];
Finally, your method (better named):
- (void) setOutputTextWithResult:(double)result {
self.someControlView.text = [self stringFromDouble:result];
}
It's so short now, it almost doesn't need it's own method.
Hi a very simple app it takes in 2 arguments via 2 text boxes, and then totals them and displays them in a label called result. The idea is to have it handled via an object called brain, for which in the later part i have given the code. problem is foo is zero and when you click the button the result goes to nothing.
The plan is to use this to build a better model view architecture for a bigger app i have completed.
#import "calbrain.h"
#import "ImmyViewController.h"
#interface ImmyViewController ()
#property (nonatomic, strong) calbrain *brain;
#end
#implementation ImmyViewController
#synthesize brain;
#synthesize num1;
#synthesize num2;
#synthesize result;
-(calbrain *) setBrain
{
if (!brain) {
brain = [[calbrain alloc] init];
}
return brain;
}
- (IBAction)kickit:(UIButton *)sender {
NSString *number1 = self.num1.text;
NSString *number2 = self.num2.text;
NSString *foo;
foo = [brain calculating:number1 anddouble:number2];
self.result.text = foo;
// self.result.text = [brain calculating:self.num1.text anddouble:self.num2.text];
}
#end
#implementation calbrain
-(NSString *) calculating:(NSString *)number1 anddouble:(NSString *)number2
{
double numb1 = [number1 doubleValue];
double numb2 = [number2 doubleValue];
double newresult = (numb1 + numb2);
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
NSString *numberAsString = [numberFormatter stringFromNumber:[NSNumber n numberWithFloat:newresult]];
return numberAsString;}
Check your brain using NSLog in the (IBAction)kickit:(UIButton *)sender function. I guess you didn't initialise brain. If this is not the case, you need to provide more code.
i did just that, i came to the conclusion the setter for brain isnt working properly
i put the alloc init line of code before i needed to alloc init the brain, and it works fine, i stubbed out the setter,
i will go back and see why it wasnt overriding the setter made by properties, but interesting stuff none the less. it means i can change my actual larger app to have a cleaner more organised architecture.
thanks for your time.
Try initializing your brain object in viewDidLoad() using your setter method. You have to call setter method to get your brain object initialized.
Something like this
viewDidLoad()
{
brain = [self setBrain];
//You can also do this
brain = [[calbrain alloc] init];
}
and use that brain object in your (IBAction)kickit: method.
Hope this helps.
I am trying to set the property of a child view controller (DateViewController) from the parent and getting a bad access error the second time I do so. Here is the code. This is the DateViewController.h. The problem lies with the selectedDate property:
#import <UIKit/UIKit.h>
#protocol DateViewDelegate <NSObject>
-(void) dateViewControllerDismissed:(NSDate *)selectedDate;
#end
#interface DateViewController : UIViewController {
IBOutlet UIDatePicker *dateReceipt;
id myDelegate;
}
-(IBAction)btnDone;
#property(nonatomic,assign)NSDate *selectedDate;
#property(nonatomic,assign)id<DateViewDelegate> myDelegate;
#end
Inside DateViewController.m, I do synthesize selectedDate. Now in the parent view controller (ComdataIOSViewController.m) I set the selectedDate property of the DateViewController to the variable receiptDate which is declared as an NSDate * in the #interface section of ComdataIOSViewController.h. This is a snippet of ComdataIOSViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
receiptDate = [NSDate date];
}
-(IBAction)btnSetDate {
dlgDate=[[DateViewController alloc] initWithNibName:nil bundle:nil];
dlgDate.selectedDate = receiptDate;
dlgDate.myDelegate = self;
[self presentModalViewController:dlgDate animated:true];
[dlgDate release];
}
-(void) dateViewControllerDismissed:(NSDate *)selectedDate
{
NSDateFormatter *dateFormat = [[[NSDateFormatter alloc] init] autorelease];
[dateFormat setDateStyle:NSDateFormatterShortStyle];
receiptDate = selectedDate;
dateString = [dateFormat stringFromDate:receiptDate];
lblDate.text = dateString;
}
So the first time I click the set date button on the parent controller, the DateViewController appears, I pick the date from the datepicker control, and the controller is dismissed. In the parent view controller, dateViewControllerDismissed gets called and I set the receiptDate to the selectedDate parameter. The next time I click the date button, I get a bad access error where I set the DateViewController's selectedDate property to the receiptDate. I'm assuming this is some sort of memory issue that I'm not handling correctly. IOS programming is still new to me.
I have found several problems in your code which could lead your application to crash. Actually they are memory management problem.
Assigning autoreleased object to receiptDate:
receiptDate = [NSDate date];
when you will try to use this value later it will cause app crash because memory where receiptDate point could be already released. You could fix it by retaining the value:
receiptDate = [[NSDate date] retain];
and releasing in dealloc or anywhere you are changing it (I dont know how it is declared. It should be retain property).
You are assigning NSDate without retaining it:
receiptDate = selectedDate;
you could fix it by retaining:
receiptDate = [selectedDate retain];
I am sorry because I could not write all aspects of memory management in objective-C. It is better to use ARC if you don't know iOS memory managent well.
You could find a lot of useful information in this two guides from Apple: Advanced Memory Management Programming Guide and Memory Management Programming Guide for Core Foundation
Your property is never retained. What I would suggest to do would be to change the assign to retain in your property declaration. That'll solve your problem and you won't have to call retain everywhere you set selectedDate. The property will do that for you.
If you're not using ARC, don't forget to set the property to nil in your dealloc method, like so:
self.selectedDate = nil;
Note that I use self.selectedDate. It's important so that selectedDate is accessed as a property, not a variable.