UA-17470720-3

Jump to content


Photo
- - - - -

How to optimize this block of code?


  • Please log in to reply
3 replies to this topic

#1 Sebastian Roth

Sebastian Roth

    Jr. Member

  • STV 3.0 Pro
  • PipPip
  • 20 posts
  • LocationTaipei, Taiwan
Reputation: 1
Good

Posted 25 March 2013 - 05:49 PM

Hi there:

Finally I'm using STV again - and the first time in version 3.0.
Here's a sample of how it's being used:

    model = [[SCTableViewModel alloc] initWithTableView:self.tableView];
   
    // Hide the PREV/NEXT & DONE accessory view.
    model.inputAccessoryView = nil;
   
    SCUserDefaultsDefinition *userDefaultsDef = [SCUserDefaultsDefinition definitionWithDictionaryKeyNamesString:@":(email,password):Will be automatically signed in"];
    if(self.isRegistration) {
	    userDefaultsDef = [SCUserDefaultsDefinition definitionWithDictionaryKeyNamesString:@":(name,email,phone,password):"];
    }
   
    SCUserDefaultsStore *userDefaultsStore = [SCUserDefaultsStore
											  storeWithDefaultDataDefinition:userDefaultsDef];
   
    [userDefaultsStore.standardUserDefaultsObject removeObjectForKey:@"email"];
    [userDefaultsStore.standardUserDefaultsObject removeObjectForKey:@"password"];
   
    if(self.isRegistration) {
	    SCPropertyDefinition *firstNameDef = [userDefaultsDef propertyDefinitionWithName:@"displayName"];
	    firstNameDef.cellActions.willDisplay = ^(SCTableViewCell *cell, NSIndexPath *indexPath) {
		    [cell becomeFirstResponder];
	    };
    }
    SCPropertyDefinition *usernameDef = [userDefaultsDef propertyDefinitionWithName:@"email"];
    usernameDef.attributes = [SCTextFieldAttributes attributesWithPlaceholder:nil
															  secureTextEntry:NO
														   autocorrectionType:UITextAutocorrectionTypeNo
													   autocapitalizationType:UITextAutocapitalizationTypeNone];
    usernameDef.cellActions.willDisplay = ^(SCTableViewCell *cell, NSIndexPath *indexPath) {
	    SCTextFieldCell *textFieldCell = (SCTextFieldCell *)cell;
	    textFieldCell.textField.keyboardType = UIKeyboardTypeEmailAddress;
	    if(!self.isRegistration) {
		    [cell becomeFirstResponder];
	    }
    };
    usernameDef.cellActions.valueIsValid = ^BOOL(SCTableViewCell *cell, NSIndexPath *indexPath) {
	    BOOL valid = FALSE;
	    if([cell isKindOfClass:[SCTextFieldCell class]]) {
		    SCTextFieldCell *textFieldCell = (SCTextFieldCell *)cell;
		    if([textFieldCell.textField.text length] > 4)
			    valid = TRUE;
		   
		    textFieldCell.textLabel.textColor = valid ? [UIColor blackColor] : [UIColor redColor];
	    }
	   
	    return valid;
    };
   
    SCPropertyDefinition *phoneDef = [userDefaultsDef propertyDefinitionWithName:@"phone"];
    phoneDef.attributes = [SCTextFieldAttributes attributesWithPlaceholder:nil
															  secureTextEntry:NO
														   autocorrectionType:UITextAutocorrectionTypeNo
													   autocapitalizationType:UITextAutocapitalizationTypeNone];
    phoneDef.cellActions.willDisplay = ^(SCTableViewCell *cell, NSIndexPath *indexPath) {
	    SCTextFieldCell *textFieldCell = (SCTextFieldCell *)cell;
	    textFieldCell.textField.keyboardType = UIKeyboardTypePhonePad;
    };
    SCPropertyDefinition *passwordDef = [userDefaultsDef propertyDefinitionWithName:@"password"];
    passwordDef.attributes = [SCTextFieldAttributes attributesWithPlaceholder:nil
															  secureTextEntry:YES
														   autocorrectionType:UITextAutocorrectionTypeNo
													   autocapitalizationType:UITextAutocapitalizationTypeNone];
    passwordDef.cellActions.willConfigure = ^(SCTableViewCell *cell, NSIndexPath *indexPath) {
	    SCTextFieldCell *tfc = (SCTextFieldCell *) cell;
	    tfc.textField.returnKeyType = self.isRegistration ? UIReturnKeyNext : UIReturnKeySend;
    };
   
    passwordDef.cellActions.valueIsValid = ^BOOL(SCTableViewCell *cell, NSIndexPath *indexPath) {
	    BOOL valid = FALSE;
	    if([cell isKindOfClass:[SCTextFieldCell class]]) {
		    SCTextFieldCell *textFieldCell = (SCTextFieldCell *)cell;
		    if([textFieldCell.textField.text length] >= kMinimumPasswordLength)
			    valid = TRUE;
		   
		    textFieldCell.textLabel.textColor = valid ? [UIColor blackColor] : [UIColor redColor];
	    }
	   
	    return valid;
    };
    passwordDef.cellActions.returnButtonTapped = ^(SCTableViewCell *cell, NSIndexPath *indexPath) {
	    [model commitChanges];
	    if(!model.valuesAreValid) {
		    [SVProgressHUD showErrorWithStatus:@"Form incomplete"];
	    } else {
		    [cell resignFirstResponder];
		   
		    [SVProgressHUD showWithStatus:self.isRegistration ? @"Registering" : @"Logging in"];
		   
		    if(self.isRegistration) {
			    [self registerOnServer:@{
					 @"username" : [userDefaultsStore.standardUserDefaultsObject valueForKey:@"email"],
					 @"email" : [userDefaultsStore.standardUserDefaultsObject valueForKey:@"email"],
					 @"password" : [userDefaultsStore.standardUserDefaultsObject valueForKey:@"password"],
					 @"displayName" : [userDefaultsStore.standardUserDefaultsObject valueForKey:@"name"],
					 @"phone" : [userDefaultsStore.standardUserDefaultsObject valueForKey:@"phone"]
				 }];
		    } else {
			    [self loginUser:@{
					 @"username" : [userDefaultsStore.standardUserDefaultsObject valueForKey:@"email"],
					 @"password" : [userDefaultsStore.standardUserDefaultsObject valueForKey:@"password"]
				 }];
		    }
	    }
    };
   
    [model generateSectionsForUserDefaultsDefinition:userDefaultsDef];

I think that's quite a lot of code and quite a lot of functionality too. The question is: How would you optimize this and remove LOC, if possible?

(This question is not about a specific problem, I just like to know how the experts use this library). :-)

Best wishes,
Sebastian

#2 Tarek

Tarek

    Forum Admin

  • Administrators
  • 3670 posts
Reputation: 452
Popular

Posted 26 March 2013 - 06:47 PM

Hi Sebastian,

You've actually done a very good job, and there is a lot of functionality implemented here as you said. The only critical issue I see here is that you've used 'self' inside your blocks several times, which will definitely lead to a retain cycle and will prevent your view controller from ever being released. I recommend creating the following variable at the start of your viewDidLoad code and use it inside all blocks instead of using self.

unsafe_unretained *weak_self = self;

Hope this helps.

#3 Dave Guerin

Dave Guerin

    Forum Master

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 545 posts
  • LocationIreland
Reputation: 137
Popular

Posted 05 June 2013 - 03:15 AM

I following the advice to use an __unsafe_unretained *weakSelf in all blocks but had odd crashes occurring, an activeDetailModel would sometimes crash if its tableView was accessed for example.

 

I've just got a new book, "Effective Objective-C 2.0" by Matt Galloway, published by Informit. There the recommendation is to use __weak *weakSelf in blocks.

 

Changing to a __weak *weakSelf and all the odd crashes seem to have disappeared.

 

I don't have enough depth of knowledge of the subject to know which is best, but __weak *weakSelf seems to be working better in my case.


Cheers,

Dave

www.dgapps.ie

#4 Everett

Everett

    Ev

  • STV 5.0 Pro
  • PipPipPipPipPip
  • 191 posts
  • LocationMichigan
Reputation: 60
Outstanding

Posted 05 June 2013 - 06:44 AM

Hi Dave, 

 

great book by the way, I'm reading it as well!

 

I'm interested in Tarek's take on this.  

 

I understand it like this:

the weak type is first available in IOS5 so if you are supporting older sdk, like IOS4 the new weak type is not available.

 

The actual difference is that a weak typed reference will actually be treated as nil after it is deallocated.  Remember that a nil object will accept messages and do nothing.  unsafe untretained is basically unknown after it is deallocated.  That is why its called unsafe.  If you have a message call to that deallocated object, if its typed to unsafe  unretained and it has been previously deallocated, it will crash.  If its typed to weak (or strong for that matter) and deallocated, it will do nothing because it responds as 'nil' would.

 

I understand there may be some nuance for primitive object types and special objects like CGRects and CGPoints and things like that which are fundamentally wrappers on a set of C structs.

 

But in this case, a discussion on referencing "self" inside of a block, for IOS5 and later, weak is the recommended approach.

 

just my .02






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users