Objective-C : Create and using Objects [duplicate] - objective-c

This question already has answers here:
What is the difference between class and instance methods?
(18 answers)
Closed 9 years ago.
I'm a c++ & c programmer , and i'm new to the world of objective-C , so i have some problem
understanding how it works , here a short code , that confused me,
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
#autoreleasepool {
NSDate *now = [NSDate date];
NSLog(#"The date is %#", now);
double seconds = [now timeIntervalSince1970];
NSLog(#"It has been %f seconds since the start of 1970.", seconds);
}
return 0; }
now is pointer to an object type NSdate my question is why we can not do this :
double seconds = [NSDate timeIntervalSince1970];
normally the first part is the type of the object and the second part is the method
i'm sorry if this is a bad question but i want to understand Objective-C very well from the begining.
Thanks

You can do something similar with
[NSDate timeIntervalSinceReferenceDate];
Although the reference date in this case is 1 January 2001
But, this is a class method. You can call it on the class.
The other methods, such as timeIntervalSince1970 are instance methods, which need to be called on actual objects of the class. In NSDate's case there is no class method for the time interval since 1970.
If you really want to, you can add a Category on to NSDate and add a class method that does this.

This is a class method:
NSDate *now = [NSDate date];
You don't need an instance of the object.
This is an instance method:
[now timeIntervalSince1970];
And you need and instance of the object.
Same in C++ as: Class::classMethod() and myClass::instanceMethod()
More info here:
https://softwareengineering.stackexchange.com/questions/191856/what-is-a-static-method-compared-to-instance-class-private-public-methods

Related

How to convert this NSTimeInterval line from Swift to Objective-C

How to convert this into Objective-C ?
let date = NSDate(timeIntervalSinceReferenceDate: interval)
I tried this:
NSDate *date = [NSDate timeIntervalSinceReferenceDate: (interval)];
It generates an error of course.
Tells me: No known class method for selector timeIntervalSinceReferenceDate:
Also here is some context:
NSTimeInterval interval = [[NSDate alloc]init].timeIntervalSinceReferenceDate + [NSDate weekInSeconds].doubleValue;
NSDate *date = [NSDate timeIntervalSinceReferenceDate: (interval)];
return [self isSameWeekAsDate:(date)];
timeIntervalSinceReferenceDate: is not a method implemented on the NSDate class. When bridging from Objective-C to Swift, Swift does some renaming with initializers.
In order to initialize an NSDate object in Objective-C with a reference date, you must call either the class method dateWith... or the instance method initWith...:
NSDate * const date = [NSDate dateWithTimeIntervalSinceReferenceDate: timeInterval];
or...
NSDate * const date = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: timeInterval];
I've added the const here to make this more closely match the Swift code with the let declaration.

Why can't I store timeIntervalSince1970 return value to a pointer?

I'm a beginner (at programming) learning Objective-C. Xcode will not let me allocate a return value from an NSDate object; I am confused by this.
NSDate *now = [NSDate date];
long seconds = [now timeIntervalSince1970];
If I use a pointer to store the seconds:
long *seconds = [now timeIntervalSince1970];
I see the error:
Initializing 'long *' with an expression of incompatible type 'NSTimeInterval' (aka 'double')
Why can't I say "Give me the return value of now.timeIntervalSince1970 and stick at this address"?
Another question is, why can't I initialize an object and use it without needing a pointer? This will not work.
NSDate dateObject = [NSDate date];
I realize my question probably has a very easy answer, but the book doesn't explain any of the "why does it work this way" questions.
It's because [NSDate timeIntervalSince1970] returns the value as an NSTimeInterval which is a typedefd double, which is a primitive type, not an object type.
The value counts the number of seconds since 1-Jan-1970, and does not need to be an object.
You could store it in a pointer, but that would be silly:
NSTimeInterval *elapsed = (NSTimeInterval *)malloc(sizeof(NSTimeInterval));
*elapsed = [now timeIntervalSince1970];
...
free(elapsed);
timeIntervalSince1970 returns an NSTimeInterval which is a type def of double. In the Apple documentation you will see this defined like
objective-c
typedef double NSTimeInterval;
Swift
typealias NSTimeInterval = Double
and double is a primitive and not an object type so shouldn't be a pointer (Shouldn't is in Apple documentation). The Apple documentation also states the below
NSTimeInterval is always specified in seconds; it yields sub-millisecond precision over a range of 10,000 years.
Here is the Apple Documentation

compare two dates in objective-c

I am sure this question came up before I am pulling my hair out. I have two dates - one from an Object on Parse.com and the other one local. I try to determine whether the remote object has been updated so that I can trigger actions locally.
When looking at the NSDate of both objects they seem identical but a comparison reveals that the remote object is newer - when checking the time internal (since1970) it becomes obvious that there is a difference but why? When I first created the local object all I did was
localObject.updatedAt = remoteObject.updatedAt //both NSDate
But when looking closer I get this:
Local Time Interval: 1411175940.000000
Local Time: 2014-09-20 01:19:00 +0000
Remote Time Interval: 1411175940.168000
Remote Time: 2014-09-20 01:19:00 +0000
Does anyone have an idea why that is and whether I can ignore this detail? Does iOS round up or something?
Adding more code:
#property (strong, nonatomic) NSDate *date;
...
PFQuery *query = [PFObject query];
[query whereKey:#"Product" equalTo:#"123456"]
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error)
{
self.date = objects[0].updatedAt;
NSTimeInterval localTime = [self.date timeIntervalSince1970];
NSTimeInterval remoteTime = [objects[0].updatedAt timeIntervalSince1970];
NSLog(#"Local Time Interval: %f", localTime);
NSLog(#"Local Time: %#", self.date);
NSLog(#"Remote Time Interval: %f", remoteTime);
NSLog(#"Remote Time: %#", objects[0].updatedAt);
}
else
{
NSLog(#"Error with query");
}
}];
That results in the console output above - and I don't understand why these dates are different.
I cannot explain why there is a difference, but the important thing to understand is that there can be a difference and that when comparing dates you have to use a tolerance value.
The Apple Date and Time Programming Guide has an example of how to compare two dates within a given tolerance:
To compare dates, you can use the isEqualToDate:, compare:,
laterDate:, and earlierDate: methods. These methods perform exact
comparisons, which means they detect sub-second differences between
dates. You may want to compare dates with a less fine granularity. For
example, you may want to consider two dates equal if they are within a
minute of each other. If this is the case, use timeIntervalSinceDate:
to compare the two dates. The following code fragment shows how to use
timeIntervalSinceDate: to see if two dates are within one minute (60
seconds) of each other.
if (fabs([date2 timeIntervalSinceDate:date1]) < 60) ...
It's up to you decide on the tolerance value, but something like 0.5 seconds seems reasonable:
+ (BOOL)date:(NSDate *)date1
equalsDate:(NSDate *)date2
{
return fabs([date2 timeIntervalSinceDate:date1]) < 0.5;
}
Parse stores dates as iso8601 format. This makes things very complex as Apple does not manage the format well. While the idea of the standard is awesome, until everyone plays by the same rules, anarchy rules..
I convert everything inbound from parse into usable format before attempting anything on their date time values..
Drop this into a library somewhere, and save yourself tons of headaches. This took weeks of searching and scratching to overcome.
+ (NSDate *)convertParseDate:(NSDate *)sourceDate {
NSDateFormatter *dateFormatter = [NSDateFormatter new];
NSString *input = (NSString *)sourceDate;
dateFormatter.dateFormat = #"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
// Always use this locale when parsing fixed format date strings
NSLocale* posix = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
dateFormatter.locale = posix;
NSDate *convertedDate = [dateFormatter dateFromString:input];
assert(convertedDate != nil);
return convertedDate;
}

Objective C: Questions regarding time and array

Q1. NSDate *now = [NSDate date];
NSLog(#"Current date:%#",now);
The time shown is 4 hours ahead of the system time. I am wondering why is it so and how can I correct it?
Q2.. In C/C++, strings are treated as an array of characters. Is it the case in Objective-C also?
NSDate *now = [NSDate date];
NSLog(#"Current date:%#",now);
it's "now" not "date".
A1: NSLog(#"%#", now) is effectively the same as NSLog(#"%#", [now description]). The NSDate object doesn't care what the timezone is, so its description method will just give you the time in UTC. If you need to format with the right timezone and locale, you'll need to use an NSDateFormatter object to convert it to a nicely formatted string first.
A2: Yes and no, but mostly no. You can do this:
char *cString = "I am a C string";
to create a C string, which you can treat exactly as you would in C. That's something you very rarely see in Objective-C, though, except when it's absolutely necessary. The "normal" way to use strings is with instances of NSString or NSMutableString, which are fully-fledged objects:
NSString *normalString = #"I'm above all that."; (note the # symbol)

How to calculate the time taken by one process in objective c?

Hey there, I am fresh to iPhone development and Objective C. Sorry if this question is too stupid....
Here is my problem, I want to calculate the time taken by one of my function. like UIGetScreenImage. Here is the code:
-(void)screenCapture{
CGImageRef screen = UIGetScreenImage();
UIImage* image = [UIImage imageWithCGImage:screen];
CGImageRelease(screen);
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}
what should I do to calculate the time taken by this process? Sample code would be appreciated.
Thanks for your kind assistance. Look forward to your replies and ideas. :D
You can get current date on method start and finish and check time passed between those 2 moments:
-(void)screenCapture{
NSDate* startDate = [NSDate date];
...
NSDate* finishDate = [NSDate date];
NSLog(#"%f", [finishDate timeIntervalSinceDate: startDate]);
}
Edit: I believe my approach described above is (to put it mildly) not the best solution to measure process time. Now I use approach described in "Big Nerd Ranch" blog here that uses mach_absolute_time function. I copied the code from the post to illustrate that method - with this code snippet you can measure rub time of arbitrary block:
#import <mach/mach_time.h> // for mach_absolute_time() and friends
CGFloat BNRTimeBlock (void (^block)(void)) {
mach_timebase_info_data_t info;
if (mach_timebase_info(&info) != KERN_SUCCESS) return -1.0;
uint64_t start = mach_absolute_time ();
block ();
uint64_t end = mach_absolute_time ();
uint64_t elapsed = end - start;
uint64_t nanos = elapsed * info.numer / info.denom;
return (CGFloat)nanos / NSEC_PER_SEC;
} // BNRTimeBlock
I think an easier (and more straightforward) solution can be found here
NSDate *methodStart = [NSDate date];
/* ... Do whatever you need to do ... */
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];