NSString custom md5 class method warning: - iphone

I have done I custom class method for NSString to md5 a NSString.
This is my code:
NSString+CustomMethod.h
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#interface NSString (CustomMethod)
+ (NSString*)MD5:(NSString *)string;
#end
NSString+CustomMethod.m
#import "NSString+CustomMethod.h"
#implementation NSString (CustomMethod)
+ (NSString*)MD5:(NSString *)string
{
// Create pointer to the string as UTF8
const char *ptr = [string UTF8String];
// Create byte array of unsigned chars
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
// Create 16 byte MD5 hash value, store in buffer
CC_MD5(ptr, strlen(ptr), md5Buffer);
// Convert MD5 value in the buffer to NSString of hex values
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x",md5Buffer[i]];
return output;
}
#end
This Methodclass works great, but compiler give me a warring:
warning: class method '+MD5:' not found (return type defaults to 'id') [3]
How can I remove this warning ??
PS: if a put #import "NSString+CustomMethod.h" no warning is shown, but it's a workAround, I have created a custom method class not to include my custom class everywhere I need it
Thanks for any helps !!

Put #import "NSString+CustomMethod.h" in .pch file or in file where you want to use it.

Related

Index for character in NSString

I have NSString *string = #"Helo"; and NSString *editedString = #"Hello";. How find index for changed character or characters (for example here is #"l").
Start going through one string and compare each character with the character at the same index in the other string. The place where the comparison fails is the index of the changed character.
I've written a category on NSString that will do what you want. I've used my StackOverflow username as a postfix on the category method. This is to stop an unlikely potential future collision with a method of the same name. Feel free to change it.
First the interface definition NSString+Difference.h:
#import <Foundation/Foundation.h>
#interface NSString (Difference)
- (NSInteger)indexOfFirstDifferenceWithString_mttrb:(NSString *)string;
#end
and the implementation 'NSString+Difference.m`:
#import "NSString+Difference.h"
#implementation NSString (Difference)
- (NSInteger)indexOfFirstDifferenceWithString_mttrb:(NSString *)string; {
// Quickly check the strings aren't identical
if ([self isEqualToString:string])
return -1;
// If we access the characterAtIndex off the end of a string
// we'll generate an NSRangeException so we only want to iterate
// over the length of the shortest string
NSUInteger length = MIN([self length], [string length]);
// Iterate over the characters, starting with the first
// and return the index of the first occurence that is
// different
for(NSUInteger idx = 0; idx < length; idx++) {
if ([self characterAtIndex:idx] != [string characterAtIndex:idx]) {
return idx;
}
}
// We've got here so the beginning of the longer string matches
// the short string but the longer string will differ at the next
// character. We already know the strings aren't identical as we
// tested for equality above. Therefore, the difference is at the
// length of the shorter string.
return length;
}
#end
You would use the above as follows:
NSString *stringOne = #"Helo";
NSString *stringTwo = #"Hello";
NSLog(#"%ld", [stringOne indexOfFirstDifferenceWithString_mttrb:stringTwo]);
You can use -rangeOfString:. For example, [string rangeOfString:#"l"].location. There are several variants of that method, too.

Loop through all object properties at runtime

I want to create an Objective-C base class that performs an operation on all properties (of varying types) at runtime. Since the names and types of the properties will not always be known, how can I do something like this?
#implementation SomeBaseClass
- (NSString *)checkAllProperties
{
for (property in properties) {
// Perform a check on the property
}
}
EDIT: This would be particularly useful in a custom - (NSString *)description: override.
To expand on mvds' answer (started writing this before I saw his), here's a little sample program that uses the Objective-C runtime API to loop through and print information about each property in a class:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#interface TestClass : NSObject
#property (nonatomic, retain) NSString *firstName;
#property (nonatomic, retain) NSString *lastName;
#property (nonatomic) NSInteger *age;
#end
#implementation TestClass
#synthesize firstName;
#synthesize lastName;
#synthesize age;
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
unsigned int numberOfProperties = 0;
objc_property_t *propertyArray = class_copyPropertyList([TestClass class], &numberOfProperties);
for (NSUInteger i = 0; i < numberOfProperties; i++)
{
objc_property_t property = propertyArray[i];
NSString *name = [[NSString alloc] initWithUTF8String:property_getName(property)];
NSString *attributesString = [[NSString alloc] initWithUTF8String:property_getAttributes(property)];
NSLog(#"Property %# attributes: %#", name, attributesString);
}
free(propertyArray);
}
}
Output:
Property age attributes: T^q,Vage
Property lastName attributes: T#"NSString",&,N,VlastName
Property firstName attributes: T#"NSString",&,N,VfirstName
Note that this program needs to be compiled with ARC turned on.
Use
objc_property_t * class_copyPropertyList(Class cls, unsigned int *outCount)
and read https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html on how to do this exactly.
Some code to get you going:
#import <objc/runtime.h>
unsigned int count=0;
objc_property_t *props = class_copyPropertyList([self class],&count);
for ( int i=0;i<count;i++ )
{
const char *name = property_getName(props[i]);
NSLog(#"property %d: %s",i,name);
}
Adding some detial to #mvds:
unsigned int count=0;
objc_property_t *props = class_copyPropertyList([self class],&count);
for ( int i=0;i<count;i++ )
{
const char *name = property_getName(props[i]);
NSString* dataToGet = [NSString swf:#"%s",name];
#try { // in case of this pair not key value coding-compliant
id value = [barButton valueForKey:dataToGet];
NSLog(#"prop %d: %s %#",i,name, value);
} #catch (NSException *exception) {
// NSLog(#"Exception:%#",exception);
}
#finally {
// Display Alternative
}
}
Please give #mvds the upvote.

"implicit declaration of function" error in Objective-C

i want to convert a short string to md5 hash , I found several post about it but noone worked.
it's the simplest example that I found . i have this error
implicit declaration of function CC_MD5 is invalid in C99
- (NSString *) md5:(NSString *) input
{
const char *cStr = [input UTF8String];
unsigned char digest[16];
CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
return output;
}
UPDATE
i added #import , it work fine when i call the method like this :
[self md5:#"admin"];
, i get the right md5 hash. But when i do this
[self md5:userId];
i get an error ,
[NSDecimalNumber UTF8String]: unrecognized selector sent to instance
0x4d3e280
But userId is not decimal , he contain facebook id , but it's declared as NSString
NSString *userId;
#property(retain,nonatomic) NSString *userId;
Because the declaration of CC_MD5 has not been seen.
Include the security framework in your project and
#import <CommonCrypto/CommonDigest.h>
You need to include the CommonDigest Header file from the Crypto library at the top of your class where the MD5 function is defined as well as include the Security Framework
#import <CommonCrypto/CommonDigest.h>
Are you importing the right interface that defines CC_MD5?
#import "CommonDigest.h"

How do I create a hash of a file on iOS?

I'm trying to create unique file names by renaming them using their hashed value in iOS. How can I do that?
you could achieve this by extending NSString,
Try this in your .h:
#interface NSString(MD5)
- (NSString *)generateMD5Hash
#end
and this in your .m
- (NSString*)generateMD5Hash
{
const char *string = [self UTF8String];
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5(string, strlen(string), md5Buffer);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x",md5Buffer[i]];
return output;
}
you can implement this by making a new class called NSString+MD5, and inserting the code above in the corresponding files (.h and .m)
EDIT: Do not forget to import
< CommonCrypto/CommonDigest.h >
EDIT 2:
And for NSData;
#interface NSData(MD5)
- (NSString *)generateMD5Hash;
#end
your .m:
- (NSString *)generateMD5Hash
{
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5(self.bytes, (CC_LONG)self.length, md5Buffer);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x",md5Buffer[i]];
return output;
}
Please note that the value returned is autorelease and might need to be retained by the receiver.
Hope this helps.
Why don't you simply generate unique identifiers and use it? like
CFUUIDRef uuidObj = CFUUIDCreate(nil);
NSString *uniqueId = (NSString*)CFUUIDCreateString(nil, uuidObj);
CFRelease(uuidObj);
NSLog(#"%#",uniqueId);
[uniqueId autorelease];
Using NSData is an expensive choice. Better use NSFileHandler extension if you are dealing with big files anytime.

Constant in objective-c

I would like to add some constant keys for my application, these constants can be accessed anywhere in program. So I declare the constants in interface file:
#import <UIKit/UIKit.h>
NSString * MIN_INTERVAL_KEY = #"MIN_INTERVAL_KEY";
NSString * MAX_TOBACCO_KEY = #"MAX_TOBACCO_KEY";
NSString * ICON_BADGE = #"ICON_BADGE";
#interface SmokingViewController : UIViewController {
}
And I would like to access them from the MinIntervalViewController class:
- (void)viewDidAppear:(BOOL)animated {
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
if (user) {
self.selectedValue = [user objectForKey:MIN_INTERVAL_KEY];
}
[super viewDidAppear:animated];
}
But the application shows an error in the MinIntervalViewController class:
error: 'MIN_INTERVAL_KEY' undeclared (first use in this function)
Do I miss something? Any help would be appreciated.
Thanks
Constants.h
#import <Cocoa/Cocoa.h>
#interface Constants : NSObject {
}
extern int const kExampleConstInt;
extern NSString * const kExampleConstString;
#end
Constants.m
#import "Constants.h"
#implementation Constants
int const kExampleConstInt = 1;
NSString * const kExampleConstString = #"String Value";
#end
To use:
#import "Constants.h"
Then, simply call the specific variable you wish to use.
NSString *newString = [NSString stringWithString:kExampleConstString];
In the .h file:
extern NSString * const MIN_INTERVAL_KEY;
In one (!) .m file:
NSString * const MIN_INTERVAL_KEY = #"MIN_INTERVAL_KEY";
And what you seemed to have missed is to actually import the header file declaring MIN_INTERVAL_KEY ;-) So if you declared it in SmokingViewController.h but like to use it in MinIntervalViewController.m, then you need to import "SmokingViewController.h" in your MinIntervalViewController.m. Since Objective-C is really more or less an extension to C all C visibility rules apply.
Also, what helps to debug things like that is to right-click on the .m file in Xcode and select "Preprocess". Then you see the file preprocess, i.e. after CPP has done its work. This is what the C compiler REALLY is digesting.