NSValueTransformer, inserting NULL into core data - iphone

I'm having a problem with NSValueTransformer, instead of transforming the value (NSString) it's putting NULL into the database where the attributes are transformable. I'm using the apple example, which is the same are everyone else's example and I just can't get it to work on a simple level. I'm also putting breakpoints at transformedValue and reverseTransformedValue, but they never get hit.
My custom class
+ (void)registerValueTransformer {
[NSValueTransformer setValueTransformer:[[[self alloc] init] autorelease] forName:#"myTransformerTest"];
}
#pragma mark -
#pragma mark NSValueTransformer implementation
+ (BOOL)allowsReverseTransformation {
return YES;
}
+ (Class)transformedValueClass {
return [NSString class];
}
- (id)transformedValue:(id)value {
return #"Test in";
}
- (id)reverseTransformedValue:(id)value {
return #"Test Out";
}
And this in my app delegate
+(void) initialize
{
[super initialize];
[transformerTest registerValueTransformer];
}
And then in Core data I've made my attribute transformable with a name "myTransformerTest". And according to the apple documentation that should be it.

Related

Two Independent Delegate Methods in a Class

I have two independent delegate methods in a class.
- (void)delegateMethod1:(id)data {
self.data = data;
}
- (void)delegateMethod2 {
[someClass sendData:self.data];
}
Now, this works fine sometimes but the other times, delegateMethod2 gets called before delegateMethod1.
I need to know how to manage this elegantly so that the line: [someClass sendData:self.data]; gets called only when both delegateMethod1 and delegateMethod2 have been called.
I know I can do it by using a variable to set to something on each delegate call but there has to be an elegant way to do this.
Any help?
Remembering which delegate has been called seems the easiest and cleanest solution to me.
But you can make it symmetric by moving the check to a separate method, so that
is does not matter which delegate is called first:
- (void)checkIfDataCanBeSent {
if (self.method1called && self.method2called) {
[someClass sendData:self.data];
}
}
- (void)delegateMethod1:(id)data {
self.method1called = YES;
// ...
[self checkIfDataCanBeSent];
}
- (void)delegateMethod2 {
self.method2called = YES;
// ...
[self checkIfDataCanBeSent];
}
(I have assumed that all delegate methods are called on the main thread, otherwise
one would have to add some synchronization.)
I believe, using a indicative variable to be the most elegant way to get over this. But this variable has to be kept in the delegate caller object.
Pseudo-type explanation
#interface DelegateCaller
{
BOOL hasCalled1stMethod;
}
#property(nonatomic,weak) id delegate;
#end
#implementation DelegateCaller
-(void)in_some_process_1
{
[self.delegate delegateMethod1]; //call
hasCalled1stMethod = YES; //set indicator
}
-(void)in_some_process_2
{
if(hasCalled1stMethod)
{
[self.delegate delegateMethod2]; //call
hasCalled1stMethod = NO; //reset indicator for reuse, if required.
}
}
#end
This way you'll not have to maintain any variable in the delegate itself, because the regulation of calling is maintained in the caller-object itself.
Another case:
If the delegateMethod1 is called from some object1 and the delegateMethod2 is called from some other object2, then again the indicative variable method is the most elegant way (in this limited scenario)
Pseudo-type explanation:
#interface ClassDelegateObject //aka the callee
{
BOOL hasCalledMethod1;
}
#end
#implementation ClassDelegateObject
-(void)delegateMethod1:(NSData*)data
{
self.data = data;
hasCalledMethod1 = YES; //set the indicator.
}
-(void)delegateMethod2
{
//here relying on the self.data!=nil will not be fruitful
//in case the self.data is not nil and hold some previous garbage data then
//this logic will fail.
if(hasCalledMethod1)
{
[someClass sendData:self.data];
hasCalledMethod1 = NO; //reset the variable for reuse if required.
}
}
#end
I would suggest that you rethink how the code works. Maybe you can check if there is no data and if so send it once it is ready:
- (void)delegateMethod1:(id)data {
self.data = data;
if (self.dataShouldBeSentWhenReady) {
[self sendData];
}
}
- (void)delegateMethod2 {
if (self.data) {
[self sendData];
} else {
[self setDataShouldBeSentWhenReady:YES];
}
}
- (void)sendData {
[self setDataShouldBeSentWhenReady:NO];
[someClass sendData:self.data];
}

Normalize or Canonicalize string for Core Data?

I've watched some of the WWDC videos on Core Data and I'm planning on maintaining a canonicalized text property.
Let's say I have the following data:
originalString normalizedString (+lowercase?)
Ønsker onsker
onsker onsker
Onsker onsker
When I query my model, I want to sort it by 'normalizedString' so that it ignores the case and the Ø (or other characters). I also want to be able to run a query like "starts with 'o'" and have it return the 3 words above.
I was trying to avoid to do something like:
[NSPredicate predicateWithFormat:#"(originalString like[cd] %#)"...
for querying the model.
I was also trying to use the 'originalString' for my sorting.
I've tried two different approaches with no success, my normalized string is still saved as the originalString (I override the setter in a category I created):
Calling decomposedStringWithCanonicalMapping:
// ...
[normalizedString decomposedStringWithCanonicalMapping];
// ...
Followed this example:
// ...
CFStringNormalize((CFMutableStringRef)normalizedString, kCFStringNormalizationFormD);
CFStringFold((CFMutableStringRef)normalizedString, kCFCompareCaseInsensitive | kCFCompareDiacriticInsensitive | kCFCompareWidthInsensitive, NULL);
Any ideas on how I can accomplish my goal?
Edit:
Here's my overridden setter, which I know it gets called:
- (void) setNormalizedName:(NSString *)newNormalizedName
{
NSMutableString *normalizedString;
if (![self.lastName length] == 0) {
normalizedString = [NSMutableString stringWithString:self.lastName];
} else {
normalizedString = [NSMutableString stringWithString:self.firstName];
}
// CFStringNormalize((CFMutableStringRef)normalizedString, kCFStringNormalizationFormD);
// CFStringFold((CFMutableStringRef)normalizedString, kCFCompareCaseInsensitive | kCFCompareDiacriticInsensitive | kCFCompareWidthInsensitive, NULL);
[normalizedString decomposedStringWithCanonicalMapping];
[self willChangeValueForKey:#"normalizedName"];
[self setPrimitiveValue:normalizedString forKey:#"normalizedName"];
[self didChangeValueForKey:#"normalizedName"];
}
You should override the setters for the "primary" properties (e.g. firstName, lastName), and not the setter for the "derived" property.
Also note that decomposedStringWithCanonicalMapping returns a new string, it does not
modify the receiver.
The code could roughly look like this (not compiler checked):
- (void) setFirstName:(NSString *)firstName
{
[self willChangeValueForKey:#"firstName"];
[self setPrimitiveValue:firstName forKey:#"firstName"];
[self didChangeValueForKey:#"firstName"];
[self updateNormalizedName];
}
- (void) setLastName:(NSString *)lastName
{
[self willChangeValueForKey:#"lastName"];
[self setPrimitiveValue:lastName forKey:#"lastName"];
[self didChangeValueForKey:#"lastName"];
[self updateNormalizedName];
}
- (void) updateNormalizedName
{
NSString *normalizedString;
if ([self.lastName length] > 0) {
normalizedString = [self.lastName decomposedStringWithCanonicalMapping];
} else {
normalizedString = [self.firstName decomposedStringWithCanonicalMapping];
}
self.normalizedString = normalizedString;
}

How to write OCUnit Test Case

I want to write unit tests using Apple's default SenTestingKit for the below method:
- (NSDictionary*)getValueTags {
return _tags;
}
- (NSString*)getFlag {
NSString* jo = #"";
for (NSString* key in _tags) {
jo = [jo stringByAppendingFormat:#"%#=\"%#\"&", key, [_tags objectForKey:key]];
}
if ([jo length] > 0) {
jo = [jo substringToIndex:[jo length] - 1];
}
return jo;
}
I used default SenTesting
- (void)setUp
{
[super setUp];
// Set-up code here.
}
- (void)tearDown
{
// Tear-down code here.
[super tearDown];
}
-(void)testValueTags{
}
-(void)testGetFlag{
}
I am new to writing TestCases, I need some guideline for sample methods to write test cases
A test case has four distinct phases:
set up
exercise
verify
tear down
Some of these phases can be empty. For example, most tear down happens automatically if you use ARC.
When you're starting, don't put anything into the setUp or tearDown methods. Just write a single unit test. Here's a worked example. (I'm going to change the names, because Objective-C idiom is not to use the word "get". So instead of getFlag let's just call it flag.) I'm going to call the class `Example, and I'll use ARC. And I use the abbreviation "sut" for "system under test".
- (void)testFlagGivenOneEntry
{
// set up
Example *sut = [[Example alloc] init];
[sut setTags:#{ #"key1" : #"value1" }];
// execute & verify
STAssertEqualObjects([sut flag], #"key1=\"value1\"", nil);
}
That's one test. Let's add another.
- (void)testFlagGivenTwoEntries
{
// set up
Example *sut = [[Example alloc] init];
[sut setTags:#{ #"key1" : #"value1",
#"key2" : #"value2" }];
// execute & verify
STAssertEqualObjects([sut flag], #"key1=\"value1\"&key2=\"value2\"", nil);
}
At this point, we have duplicate code: the creation of the sut. Now we can promote the variable up to an instance variable of the class. Then we create it in setUp and destroy it in tearDown:
#interface ExampleTest : SenTestCase
#end
#implementation ExampleTest
{
Example *sut;
}
- (void)setUp
{
[super setUp];
sut = [[Example alloc] init];
}
- (void)tearDown
{
sut = nil;
[super tearDown];
}
- (void)testFlagGivenOneEntry
{
[sut setTags:#{ #"key1" : #"value1" }];
STAssertEqualObjects([sut flag], #"key1=\"value1\"", nil);
}
- (void)testFlagGivenTwoEntries
{
[sut setTags:#{ #"key1" : #"value1",
#"key2" : #"value2" }];
STAssertEqualObjects([sut flag], #"key1=\"value1\"&key2=\"value2\"", nil);
}
#end
For a more involved example, see Objective-C TDD: How to Get Started.

respondsToSelector always fails

I am in the process of writing my own gridview implementation( Based of the tableview pattern). I have followed a datasource model similar to table view, but when I check if the data source responds to the message the call always fails.
I have tried putting in break points and following execution, I even tried missing out the call to respondsToSelector. Nothing I try seems to work. What am I missing here? Thanks in advance
GridView.h
...
#protocol GridViewDataSource
- (NSInteger) numberOfRowsForGridView:(GridView *)gridView;
- (NSInteger) numberOfColumnsForGridView:(GridView *)gridView;
- (GridViewCell *) cellForRow:(NSInteger) row column:(NSInteger )column;
#end
GridView.m
...
#pragma mark datasource methods
-(NSInteger)numberOfRowsForGridView
{
if( [dataSource respondsToSelector:#selector(numberOfRowsForGridView:)] )
return [dataSource numberOfRowsForGridView:self];
// NSLog(#"Failed, dataSource does not implement properly");
return 0;
}
-(NSInteger)numberOfColumnsForGridView
{
if( [dataSource respondsToSelector:#selector(numberOfColumnsForGridView:)] )
return [dataSource numberOfColumnsForGridView:self];
return 0;
}
-(GridViewCell *)cellForRow:(NSInteger)row column:(NSInteger)column
{
if( [dataSource respondsToSelector:#selector(cellForRow:column:)])
return [dataSource cellForRow:row column:column];
return nil;
}
GridViewAppDelegate.h
...
#interface GridViewAppDelegate : NSObject <UIApplicationDelegate, GridViewDataSource>
...
GridViewAppDelegate.m
#pragma mark datasource methods
-(NSInteger)numberOfRowsForGridView:(GridView *)gridView
{
return 1;
}
-(NSInteger)numberOfColumnsForGridView:(GridView *)gridView
{
return 1;
}
-(GridViewCell *)cellForRow:(NSInteger)row column:(NSInteger)column
{
CGRect frame = [view bounds];
GridViewCell *cell = [[GridViewCell alloc]initWithFrame:frame];
return cell;
}
Is your dataSource object nil?
Any message sent to nil will return NO for boolean results (0 for numbers, and nil for objects as well).
Have you checked whether dataSource is non-nil?

Searching for the Right Pattern (iPhone/Objective C)

EDIT: It was suggested to me that I implement the strategy pattern (http://en.wikipedia.org/wiki/Strategy_pattern), which I think I would do as several objects that implement a delegate protocol in Objective-C. This accomplishes the encapsulation I want while still allowing me to have a generic view controller in memory.
I have a class called DetailViewController that displays information about various types of data - waypoints, trails, maps, photos.
Right now, this class is 1400 lines long and it has some messy switch statements. For example:
- (void) changeMiniView:(id)sender {
if (self.track) {
[self changeTrackMiniView:[sender selectedSegmentIndex]];
} else if (self.waypoint) {
[self changeWaypointMiniView:[sender selectedSegmentIndex]];
} else if (self.photo) {
[self changePhotoMiniView:[sender selectedSegmentIndex]];
} else if (self.map) {
[self changeMapMiniView:[sender selectedSegmentIndex]];
}
}
This would be a lot neater if I made subclasses of DetailViewController, but my conundrum is I would like to keep the viewController in memory and just change certain elements, so I can have crisp transitions, particularly on 3G phones.
I feel like if I want my code to be neat, I have to take a performance hit.
Have the current view in a field in your object (rather than one field for every type of miniview you have), and implement changeMiniView for each of them.
Then your method would look like:
- (void) changeMiniView: (id)sender {
[self.currentMiniView changeMiniView: [sender selectedSegmentIndex]];
}
How about using selector?
- (void)viewDidLoad {
if (self.track) {
sel = #selector(changeTrackMiniView:);
} else if (self.waypoint) {
sel = #selector(changeWaypointMiniView:);
} else if (self.photo) {
sel = #selector(changePhotoMiniView:);
} else if (self.map) {
sel = #selector(changeMapMiniView:);
}
}
- (void)changeTrackMiniView:(id)sender {
....
}
- (void)changeMiniView:(id)sender {
[self performSelector:sel withObject:sender];
}