I was under the assumption that the entire point of constants was to avoid typos and make life easier....but thats not so true if I cant get const to auto suggest in classes they are available in. Am I doing something wrong?
#import <Foundation/Foundation.h>
#interface NSDefaultsConstants : NSObject
FOUNDATION_EXPORT NSString* const user_full_name;
FOUNDATION_EXPORT NSString* const user_first_name;
FOUNDATION_EXPORT NSString* const user_last_name;
FOUNDATION_EXPORT NSString* const user_cover_photo;
FOUNDATION_EXPORT NSString* const user_default_photo;
FOUNDATION_EXPORT NSString* const user_udid;
FOUNDATION_EXPORT NSString* const session_draft_status_text;
FOUNDATION_EXPORT NSString* const session_draft_image_url;
#end
#import "NSDefaultsConstants.h"
#implementation NSDefaultsConstants
#end
NSString* const user_full_name = #"user_fullname";
NSString* const user_first_name = #"user_first_name";
NSString* const user_last_name = #"user_last_name";
NSString* const user_cover_photo = #"user_cover_photo";
NSString* const user_default_photo = #"user_default_photo";
NSString* const user_udid = #"user_udid";
NSString* const session_draft_status_text = #"session_draft_status_text";
NSString* const session_draft_image_url = #"session_draft_image_url";
Related
I'm developing an app that uses a barcode to pull data from an API.
For each call I need to generate a hash value as a signature. Which is a combination of my API ID and the barcode.
I've got an issue where my hashed value is the same each time, therefore my calls are failing.
The functions to create the hash are in objective-C and I have a bridge so I can call it in SwiftUI.
NSString+SHA1.m
#import "NSString+SHA1.h"
#import <CommonCrypto/CommonHMAC.h>
#implementation NSString (SHA1)
- (NSString *)hashedValue:(NSString *)key
{
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
const char *cData = [self cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
NSString *hash = [HMAC base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
//Used to be [HMAC base64Encoding], but is now depreciated
return hash;
}
#end
As base64Encoding is depreciated, I tried to use base64EncodedStringWithOptions instead. This may be done incorrectly and could be the cause of why my hash value is the same each time.
This is how I call it in SwiftUI:
let hashedValue = scannedCode.barcode.hashedValue("(API ID)")
scannedCode is an observable object that stores the scanned barcode under "barcode" as a String.
In the bridging header:
#import "NSString+SHA1.h"
#import "NSString+SHA1.m"
NSString+SHA1.h
#import <Foundation/Foundation.h>
#interface NSString (SHA1)
- (NSString *)hashedValue:(NSString *)key;
#end
EDIT:
I fixed the problem of the hash value being the same, but the API still isn't accepting my signature. So it's to do with the calculation being wrong.
I have an ABPeoplePickerNavigationController as below
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
I need to disable some of the contacts being selected from the ABPeoplePickerNavigationController's list view.
While browsing, got some idea like this
// Predicate to enable only the contacts having a mail id atleast.
picker.predicateForEnablingPerson = [NSPredicate predicateWithFormat:#"emailAddresses.#count > 0"];
So I implemented a predicate like below to exclude the selection of contact with the first name I have.
NSString *firstName = #"Kate";
// Predicate to disable selection of the contacts with the first name given.
picker.predicateForEnablingPerson = [NSPredicate predicateWithFormat:#"firstName != %#",firstName];
Unfortunately its not working.
I found the list of the constants that you can use in the predicate in ABPeoplePickerNavigationController.h
// Constants to use in predicates:
// A LabeledValue has a 'label' property and a 'value' property.
// A PhoneNumber has a 'stringValue' property, a 'countryCode' property, a 'formattedStringValue' property and a 'normalizedStringValue' property
// A InstantMessageAddress has a 'username' property and a 'service' property
// A SocialProfile has a 'username' property and a 'service' property
// A PostalAddress has a 'street' property, a 'subLocality' property, a 'city' property, a 'subAdministrativeArea' property, a 'state' property, a 'postalCode' property, a 'country' property and a 'ISOCountryCode' property
//
extern NSString * const ABPersonNamePrefixProperty NS_AVAILABLE_IOS(8_0); // "namePrefix" NSString
extern NSString * const ABPersonGivenNameProperty NS_AVAILABLE_IOS(8_0); // "givenName" NSString
extern NSString * const ABPersonMiddleNameProperty NS_AVAILABLE_IOS(8_0); // "middleName" NSString
extern NSString * const ABPersonFamilyNameProperty NS_AVAILABLE_IOS(8_0); // "familyName" NSString
extern NSString * const ABPersonNameSuffixProperty NS_AVAILABLE_IOS(8_0); // "nameSuffix" NSString
extern NSString * const ABPersonPreviousFamilyNameProperty NS_AVAILABLE_IOS(8_0); // "previousFamilyName" NSString
extern NSString * const ABPersonNicknameProperty NS_AVAILABLE_IOS(8_0); // "nickname" NSString
extern NSString * const ABPersonPhoneticGivenNameProperty NS_AVAILABLE_IOS(8_0); // "phoneticGivenName" NSString
extern NSString * const ABPersonPhoneticMiddleNameProperty NS_AVAILABLE_IOS(8_0); // "phoneticMiddleName" NSString
extern NSString * const ABPersonPhoneticFamilyNameProperty NS_AVAILABLE_IOS(8_0); // "phoneticFamilyName" NSString
extern NSString * const ABPersonOrganizationNameProperty NS_AVAILABLE_IOS(8_0); // "organizationName" NSString
extern NSString * const ABPersonDepartmentNameProperty NS_AVAILABLE_IOS(8_0); // "departmentName" NSString
extern NSString * const ABPersonJobTitleProperty NS_AVAILABLE_IOS(8_0); // "jobTitle" NSString
extern NSString * const ABPersonBirthdayProperty NS_AVAILABLE_IOS(8_0); // "birthday" NSDateComponents
extern NSString * const ABPersonNoteProperty NS_AVAILABLE_IOS(8_0); // "note" NSString
extern NSString * const ABPersonPhoneNumbersProperty NS_AVAILABLE_IOS(8_0); // "phoneNumbers" array of LabeledValue with PhoneNumber values
extern NSString * const ABPersonEmailAddressesProperty NS_AVAILABLE_IOS(8_0); // "emailAddresses" array of LabeledValue with NSString values
extern NSString * const ABPersonUrlAddressesProperty NS_AVAILABLE_IOS(8_0); // "urlAddresses" array of LabeledValue with NSString values
extern NSString * const ABPersonDatesProperty NS_AVAILABLE_IOS(8_0); // "dates" array of LabeledValue with NSDateComponents values
extern NSString * const ABPersonInstantMessageAddressesProperty NS_AVAILABLE_IOS(8_0); // "instantMessageAddresses" array of LabeledValue with InstantMessageAddress values
extern NSString * const ABPersonRelatedNamesProperty NS_AVAILABLE_IOS(8_0); // "relatedNames" array of LabeledValue with NSString values
extern NSString * const ABPersonSocialProfilesProperty NS_AVAILABLE_IOS(8_0); // "socialProfiles" array of LabeledValue with SocialProfile values
extern NSString * const ABPersonPostalAddressesProperty NS_AVAILABLE_IOS(8_0); // "postalAddresses" array of LabeledValue with PostalAddress values
With iOS 8 ABPeoplePickerNavigationController has:
// Optionally determines if a person can be selected or not.
// If not set, all persons will be selectable.
//
#property(nonatomic,copy) NSPredicate *predicateForEnablingPerson NS_AVAILABLE_IOS(8_0);
I'd like to disable the address book contacts that don't have a street address.
I've seen (and tested) the following, which only enables contacts with at least one email address:
if ([peoplePickerNavigationController respondsToSelector:#selector(predicateForEnablingPerson)]) {
peoplePickerNavigationController.predicateForEnablingPerson = [NSPredicate predicateWithFormat:#"emailAddresses.#count > 0"];
}
What do I replace the string "emailAddresses.#count > 0" with in order to only enable contacts with at least one street address?
You can use:
controller.predicateForEnablingPerson = [NSPredicate predicateWithFormat:#"%K.#count > 0", ABPersonPostalAddressesProperty];
The header gives a list of the acceptable constants to be used in predicates:
// Constants to use in predicates:
// A LabeledValue has a 'label' property and a 'value' property.
// A PhoneNumber has a 'stringValue' property, a 'countryCode' property, a 'formattedStringValue' property and a 'normalizedStringValue' property
// A InstantMessageAddress has a 'username' property and a 'service' property
// A SocialProfile has a 'username' property and a 'service' property
// A PostalAddress has a 'street' property, a 'subLocality' property, a 'city' property, a 'subAdministrativeArea' property, a 'state' property, a 'postalCode' property, a 'country' property and a 'ISOCountryCode' property
//
extern NSString * const ABPersonNamePrefixProperty NS_AVAILABLE_IOS(8_0); // "namePrefix" NSString
extern NSString * const ABPersonGivenNameProperty NS_AVAILABLE_IOS(8_0); // "givenName" NSString
extern NSString * const ABPersonMiddleNameProperty NS_AVAILABLE_IOS(8_0); // "middleName" NSString
extern NSString * const ABPersonFamilyNameProperty NS_AVAILABLE_IOS(8_0); // "familyName" NSString
extern NSString * const ABPersonNameSuffixProperty NS_AVAILABLE_IOS(8_0); // "nameSuffix" NSString
extern NSString * const ABPersonPreviousFamilyNameProperty NS_AVAILABLE_IOS(8_0); // "previousFamilyName" NSString
extern NSString * const ABPersonNicknameProperty NS_AVAILABLE_IOS(8_0); // "nickname" NSString
extern NSString * const ABPersonPhoneticGivenNameProperty NS_AVAILABLE_IOS(8_0); // "phoneticGivenName" NSString
extern NSString * const ABPersonPhoneticMiddleNameProperty NS_AVAILABLE_IOS(8_0); // "phoneticMiddleName" NSString
extern NSString * const ABPersonPhoneticFamilyNameProperty NS_AVAILABLE_IOS(8_0); // "phoneticFamilyName" NSString
extern NSString * const ABPersonOrganizationNameProperty NS_AVAILABLE_IOS(8_0); // "organizationName" NSString
extern NSString * const ABPersonDepartmentNameProperty NS_AVAILABLE_IOS(8_0); // "departmentName" NSString
extern NSString * const ABPersonJobTitleProperty NS_AVAILABLE_IOS(8_0); // "jobTitle" NSString
extern NSString * const ABPersonBirthdayProperty NS_AVAILABLE_IOS(8_0); // "birthday" NSDateComponents
extern NSString * const ABPersonNoteProperty NS_AVAILABLE_IOS(8_0); // "note" NSString
extern NSString * const ABPersonPhoneNumbersProperty NS_AVAILABLE_IOS(8_0); // "phoneNumbers" array of LabeledValue with PhoneNumber values
extern NSString * const ABPersonEmailAddressesProperty NS_AVAILABLE_IOS(8_0); // "emailAddresses" array of LabeledValue with NSString values
extern NSString * const ABPersonUrlAddressesProperty NS_AVAILABLE_IOS(8_0); // "urlAddresses" array of LabeledValue with NSString values
extern NSString * const ABPersonDatesProperty NS_AVAILABLE_IOS(8_0); // "dates" array of LabeledValue with NSDateComponents values
extern NSString * const ABPersonInstantMessageAddressesProperty NS_AVAILABLE_IOS(8_0); // "instantMessageAddresses" array of LabeledValue with InstantMessageAddress values
extern NSString * const ABPersonRelatedNamesProperty NS_AVAILABLE_IOS(8_0); // "relatedNames" array of LabeledValue with NSString values
extern NSString * const ABPersonSocialProfilesProperty NS_AVAILABLE_IOS(8_0); // "socialProfiles" array of LabeledValue with SocialProfile values
extern NSString * const ABPersonPostalAddressesProperty NS_AVAILABLE_IOS(8_0); // "postalAddresses" array of LabeledValue with PostalAddress values
If you look at the header, that's postalAddresses
I am trying to encrypt a string with HMAC-SHA1 using CCHmac(). I created an NSString category
for this:
NSString+HMAC.h
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonHMAC.h>
#interface NSString (HMAC)
- (NSString *)HMACSHA1WithKey:(NSString *)key;
#end
NSString+HMAC.m
#import "NSString+HMAC.h"
#implementation NSString (HMAC)
- (NSString *)HMACSHA1WithKey:(NSString *)key
{
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
const char *cData = [self cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
return [[NSString alloc] initWithData:HMAC encoding:NSUTF8StringEncoding];
}
#end
I am using this category from RubyMotion like so:
key = "ZjiUOHkl5tllz2PwaoZYrDRMkg9b43k5CcIOUjSE&"
string = "POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_consumer_key=XXX&oauth_nonce=OWhJeFpZbzRoVU4xck1RTENyN0w4T1J0czNIa01rSVA&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1389974660&oauth_version=1.0"
string.HMACSHA1WithKey(key) # => nil
However, the HMACSHA1WithKey: method returns nil all the time...
What am I doing wrong please?
The result of the SHA-1 algorithm (which is stored in HMAC) is a sequence of
bytes, but not a valid UTF-8 sequence. Therefore
[[NSString alloc] initWithData:HMAC encoding:NSUTF8StringEncoding]
fails and returns nil.
What you probably want is to convert the NSData *HMAC to a NSString containing the hexadecimal representation of the data.
There are many solutions available for that, for example How to convert an NSData into an NSString Hex string?.
I've been through Introduction to Exception Programming Topics for Cocoa. Under Throwing Exceptions, there is one exception name shown: FileNotFoundException:
NSException *e = [NSException
exceptionWithName:#"FileNotFoundException"
reason:#"File Not Found on System"
userInfo:nil];
#throw e;
However, the Predefined Exceptions page lists about 10 exceptions and FileNotFoundException is not listed.
Where can I find a list of common or expected exceptions and names?
That's weird, these are the only constants defined in NSExcpetion.h that I see:
FOUNDATION_EXPORT NSString * const NSGenericException;
FOUNDATION_EXPORT NSString * const NSRangeException;
FOUNDATION_EXPORT NSString * const NSInvalidArgumentException;
FOUNDATION_EXPORT NSString * const NSInternalInconsistencyException;
FOUNDATION_EXPORT NSString * const NSMallocException;
FOUNDATION_EXPORT NSString * const NSObjectInaccessibleException;
FOUNDATION_EXPORT NSString * const NSObjectNotAvailableException;
FOUNDATION_EXPORT NSString * const NSDestinationInvalidException;
FOUNDATION_EXPORT NSString * const NSPortTimeoutException;
FOUNDATION_EXPORT NSString * const NSInvalidSendPortException;
FOUNDATION_EXPORT NSString * const NSInvalidReceivePortException;
FOUNDATION_EXPORT NSString * const NSPortSendException;
FOUNDATION_EXPORT NSString * const NSPortReceiveException;
FOUNDATION_EXPORT NSString * const NSOldStyleException;
The exception FileNotFoundException shown in that particular example is not a predefined exception. All predefined exceptions begin with prefix NS, like NSRangeException etc. Hence you cannot see it listed under the predefined list of exceptions.
From Apple docs
Note that all predefined exceptions begin with the prefix "NS", so you should avoid using the same prefix when creating new exception names.
FileNotFoundException is custom exception, which needs to be raised and handled by the developer for custom error conditions. It is recommended that all custom exception should avoid using the prefix NS.
As mentioned by pfrank in his answer, list of predefined exceptions can be found here
extern NSString *NSGenericException;
extern NSString *NSRangeException;
extern NSString *NSInvalidArgumentException;
extern NSString *NSInternalInconsistencyException;
extern NSString *NSMallocException;
extern NSString *NSObjectInaccessibleException;
extern NSString *NSObjectNotAvailableException;
extern NSString *NSDestinationInvalidException;
extern NSString *NSPortTimeoutException;
extern NSString *NSInvalidSendPortException;
extern NSString *NSInvalidReceivePortException;
extern NSString *NSPortSendException;
extern NSString *NSPortReceiveException;
extern NSString *NSOldStyleException;
Hope that helps!