Когда метод shouldChangeCharactersInRange вызывается, текстовое поле все еще имеет старое значение, поэтому, если его длина равна 4, вы застряли.Лучшим способом проверки ввода будет вычисление строки, которую вы будете иметь в поле после изменения, и проверка, является ли она действительной:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString: (NSString *)string{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range
withString:string];
return [newString length] <= 4;
}