Magical Bronze + Silver Challenge Solution


#1

I don’t know if this is the correct solution, but it works fine in my opinion.
Comments are always welcome! I’m a beginner… :wink:

BNRItemsViewController.m


#import "BNRItemsViewController.h"
#import "BNRItem.h"
#import "BNRItemStore.h"

@implementation BNRItemsViewController


// designated initializer
- (instancetype)init
{
    //call the superclass designated initializer
    //set it to grouped of you want multiple sections
    self = [super initWithStyle:UITableViewStyleGrouped];
    
    
    if (self) {
        
        for (int i = 0; i < 5; i ++) {

            [[BNRItemStore sharedStore] createItem];
   
        }
        
        //Making sure it will display even if there is no data
        [[BNRItemStore sharedStore] endArray];
  
    }
    return self;
    
    
}


- (instancetype)initWithStyle:(UITableViewStyle)style
{
    
    //return init as new designated initializer
    // we now only need 'init' instead of using 'initWithStyle:UITableViewStylePlain' all the time
    return [self init];
    
}



//declaring that there are three sections
// all items + higher than 50 + lower than 50
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
   
    
    // adding the section count for the 'No more items' text
    // I used an empty array
    return [[[BNRItemStore sharedStore] allItems] count] + [[[BNRItemStore sharedStore] emptyArray] count];
}


// this is the first step to display the data in tableview
// letting the compiler now how many (int) rows he needs to reserve
- (NSInteger) tableView:(UITableView *)tableView
            numberOfRowsInSection:(NSInteger)section

{
   
    // declaring the empty array and putting it in the items array
    // otherwise the compilere will throw an NSRangeException error [0..2]
    NSArray *ending = [[BNRItemStore sharedStore] emptyArray];
    NSArray *items = [[[BNRItemStore sharedStore] allItems] arrayByAddingObjectsFromArray:ending];
    NSArray *sectionItems = items[section];
    return [sectionItems count];
}



// this is the second step to display the data in tableview
- (UITableViewCell *) tableView:(UITableView *)tableView
          cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"
                                                            forIndexPath:indexPath];
    
    
    // declaring the empty array and putting it in the items array
    // otherwise the compilere will throw an NSRangeException error [0..2]
    NSArray *ending = [[BNRItemStore sharedStore] emptyArray];
    NSArray *items = [[[BNRItemStore sharedStore] allItems] arrayByAddingObjectsFromArray:ending];
    //putting everything in the correct section and row
    BNRItem *item = items[indexPath.section][indexPath.row];
    cell.textLabel.text = [item description];
    return cell;
}

/*

 // I first used this but realized that this does not create a row
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
 
    NSString *footer = [NSString stringWithFormat:@"No more items!"];
    return footer;
 
} 

*/


- (void)viewDidLoad
{
    
    [super viewDidLoad];
    [self.tableView registerClass:[UITableViewCell class]
           forCellReuseIdentifier:@"UITableViewCell"];
  
}


@end

BNRItemstore.m


#import "BNRItemStore.h"
#import "BNRItem.h"


// class extension
@interface BNRItemStore ()


@property (nonatomic) NSMutableArray *privateItems;
@property (nonatomic) NSMutableArray *endItems;


@end


@implementation BNRItemStore


+ (instancetype)sharedStore
{
    
    static BNRItemStore *sharedStore = nil;
    
    if (!sharedStore) {
        
        sharedStore = [[self alloc] initPrivate];
    
    }
    
    
    return sharedStore;
    
}



- (instancetype) init
{
    
    // throws an exception if let's say
    // somebody else tries to do this:
    // bnritemstore *fail = [bnritemstore alloc] init];
 
   @throw  [NSException exceptionWithName:@"Singleton"
                            reason:@"Use + [BNRItemStore sharedStore]"
                                userInfo:nil];
    
    return nil;
}






- (instancetype)initPrivate
{
    
    self = [super init];
    
    if (self) {
  
        _privateItems = [[NSMutableArray alloc] init];
        
        
        //reserve [3] places in the memory
         [_privateItems addObject:[[NSMutableArray alloc] init]];
         [_privateItems addObject:[[NSMutableArray alloc] init]];
         [_privateItems addObject:[[NSMutableArray alloc] init]];
      

        //reserve [2] places
        //one for the ending and one for the empty array
         _endItems = [[NSMutableArray alloc] init];
         [_endItems addObject:[[NSMutableArray alloc] init]];
         [_endItems addObject:[[NSMutableArray alloc] init]];
     
    }
    
    return self;
   
}


// because bnritem uses an NSArray
// we also need one to acces it
- (NSArray *)allItems
{
  
    return self.privateItems;
    
}


- (NSArray *)endArray
{
    
    
    NSArray *ending = @[@"No more items!"];
    
    [self.endItems[0] addObjectsFromArray:ending];

    
    
    return self.endItems;
    
}


// i used an empty array to pu
- (NSArray *)emptyArray

{
    
    [self.endItems[1] arrayByAddingObject:@[@" "]];
    return self.endItems;
    
}


//this is were the random array data comes from
//and also is linked tot the random item array
- (BNRItem *)createItem
{
    
    
    // creating instance of BNRItem
    BNRItem *item = [BNRItem randomItem];
    [self.privateItems[0] addObject:item];
    
  
    if ([item valueInDollars] > 50) {
        
        
            [self.privateItems[1] addObject:item];
    
    //remember you do not need brackets {} if there's only one statement
    } else [self.privateItems[2] addObject:item];
    
    

    return item;
    
    
}








@end