Chapter 6 Solutions - Bronze / Silver Challenges: w/Output

#1

[size=140]Bronze Challenge - [/size]
Add a third tab bar item to include quiz project

AppDelegate.m
Added a third view controller to the Tab bar controller array, after importing existing quiz assets

[code]- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

// Create instance of ZGCHypnosisviewcontroller
ZGCHypnosisViewController *hvc = [[ZGCHypnosisViewController alloc] init];

// Create instance of ZGCReminderViewController
ZGCReminderViewController *rvc = [[ZGCReminderViewController alloc] init];

// Create an instance of ZGCQuizViewController
ZGCQuizViewController *qvc = [[ZGCQuizViewController alloc] init];

// BRONZE Challenge //
// UITabControllers keep array of view controllers and also maintain
// a tab bar at the botom of the screen with a tab for each view controller
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = @[hvc, rvc, qvc];

self.window.rootViewController = tabBarController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;

}[/code]

ZGCQuizViewController.m
Configure a tabBarItem via the designated initializer for the Quiz Controller

[code]- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
// Call the init method implemented by the superclass
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

if (self) {
    // Create two arrays filld with questions and answers and make pointers
    self.questions = @[@"From what is Cognac made?",
                       @"What is 7+7?",
                       @"What is the capital of Vermont?"];
    
    self.answers = @[@"Grapes",
                     @"14",
                     @"Montpelier"];
    
    // adding tabbaritem title
    self.tabBarItem.title = @"Quiz";
    
}
// Return the address of the new object
return self;

}[/code]

[size=140]Silver Challenge - [/size]
Add a UISegmentedControl to switch circle colors - Red, Green, Blue

ZGCHypnosisViewController.m
Overwrote -(void)viewDidLoad to configure the view after it has been loaded programmatically via -(void)loadView (no NIB)
Class reference indicates this is preferred method for configuring the view after using loadView to ensure view is loaded before further action is taken.

1.- added segmented control
2.- defined a target action with self.view as the target and a new public method as selector
3.- made segmented control a subview of self.view

[code]- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// Adding this to illustrate lazy loading, that is
// views load when they are needed - never call a class view in its
// init method to not break this.
NSLog(@"%@ loaded its view", NSStringFromClass(self.class)); // could’ve just used literal name

/* SILVER Challenge - adding a UISegmentedControl for red, green, blue
 when the user taps a segmented control, circle color changes */
// Using viewDidLoad as per reference doc. you configure view elements here if overridinf loadView for manual view
// Adding new control
UISegmentedControl *colorControl = [[UISegmentedControl alloc] initWithItems:@[@"red", @"green", @"blue"]];
// Defining frame for control
colorControl.frame = CGRectMake((self.view.bounds.origin.x + 85), self.view.bounds.origin.y + 550, 200, 30);
// configuring control
colorControl.tintColor = [UIColor blackColor];

// define target actions
[colorControl addTarget:self.view
                 action:@selector(selectCircleColor:)
       forControlEvents:UIControlEventValueChanged];


[self.view addSubview:colorControl];

// Key-value testing //
//[self.view setValue:[UIColor redColor] forKey:@"circleColor"];

}[/code]

ZGCHypnosisView.h
Declared new public method (selector for above target-action callback

[code]#import <UIKit/UIKit.h>

@interface ZGCHypnosisView : UIView

// target-action for segment controler

  • (void)selectCircleColor:(id)sender;

@end[/code]

ZGCHypnosisView.m
Implemented target-action method using a switch statement:
1.- Defined an expression colorIndex set to the selectedSegmentIndex property for the bsender[/b] object (the view controller behind the call back in this case)
2.- Implemented 3 case statements to set the circleColor property to either red, green, or blue based on the index# from selectedSegmentIndex

[code]#pragma - target action method for selector control

  • (void)selectCircleColor:(id)sender {
    char colorIndex = [sender selectedSegmentIndex];
    switch (colorIndex) {
    case 0:
    self.circleColor = [UIColor redColor];
    break;
    case 1:
    self.circleColor = [UIColor greenColor];
    break;
    case 2:
    self.circleColor = [UIColor blueColor];
    break;

      default:
         break;
    

    }
    }
    [/code]

#2

Bronze Solution:

  1. Include QuizViewController.m, QuizViewController.h & QuizViewController.xib file to the HypnoNerd project
  2. Import QuizViewController.h to the AppDelegate.m file
  3. Create quiz view controller object and add it to the tab controller
QuizViewController *qvc = [[QuizViewController alloc] init];
UITabBarController *tabBar = [[UITabBarController alloc] init];
tabBar.viewControllers = @[hvc, rvc, qvc];
self.window.rootViewController = tabBar;

Silver Solution:

  1. Include property circleColor to the BNYHypnosisView.h file
@interface BNRHypnosisView : UIView
@property (nonatomic, strong) UIColor *circleColor;
@end
  1. Create and add segment controller to in the loadView method of the BNYHYpnosisViewController.m
- (void) loadView {
    //BNRHypnosisView *hypnosisView = [[BNRHypnosisView alloc] init];
    BNRHypnosisView *hypnosisView = [[BNRHypnosisView alloc] init];
    self.view = hypnosisView;
    
    self.colorButton = [[UISegmentedControl alloc] initWithItems:@[@"Red", @"Green", @"Blue"]];
    
    CGRect bounds = [[UIScreen mainScreen] bounds];
    CGRect segmentBounds;
    NSLog(@"X: %f, Y: %f ", bounds.origin.x, bounds.origin.y);
    segmentBounds.size.height = bounds.size.height/20;
    segmentBounds.size.width = bounds.size.width;
    segmentBounds.origin.y = bounds.origin.y + 584.0;
    
    
    self.colorButton.frame = segmentBounds;
    [self.colorButton setBackgroundColor:[UIColor lightGrayColor]];
    [self.view addSubview:self.colorButton];
}
  1. Implement changeColor method in BNYHYpnosisViewController.m
- (void) changeColor: (id) sender {
    BNRHypnosisView *view = self.view;
    NSLog(@"%lu", [sender selectedSegmentIndex]);
    switch ([sender selectedSegmentIndex]) {
        case 0:
            //self.view.backgroundColor = [UIColor redColor];
            NSLog(@"%@", self);
            view.circleColor = [UIColor redColor];
            break;
        case 1:
            view.circleColor = [UIColor greenColor];
            break;
        case 2:
            view.circleColor = [UIColor blueColor];
            break;
        default:
            break;
    }
}
  1. Add code to detect and call changeColor method when user hits any of the buttons on the segmented control:

- (void) viewDidAppear:(BOOL)animated {
    [super viewDidAppear];
    [self.colorButton addTarget:self
                    action:@selector(changeColor:)
          forControlEvents:UIControlEventValueChanged];
}