继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

ios一个很棒的面试题(用手指拖动球)

nickcau
关注TA
已关注
手记 114
粉丝 6509
获赞 303

程序主要有两个部分组成,一个程序的显示部分,一个程序的设置部分,显示部分主要是一个可以用手指拖动圆形小球,设置部分主要是对小球的颜色和大小进行参数设置。

1.1  View-ViewController

    主要有三个ViewController,一个是用于显示的MainViewController,还有一个是用于设置的SetingsViewController,还有一个是用于设置小球颜色ColorSettingViewController.

一个RoundBallView,进行显示小球的View。

    程序第一次开启的时候,小球的坐标是界面上一个(30,30)这个位置,小球颜色为红色,直径为50像素。SettingsView的Color选项为Red,Size为最小值50。ColorSettingView的CheckMark为Red。

MainView主要对小球进行拖动操作,程序重启后,小球的位置是最后一次拖动的坐标。

SetingsViewController的第一表格引导进入ColorSettingView,SetingsViewController的第二表格设置小球大小的变化,MainView始终保持小球最后一次设置的大小,小球的直径的最大值为100,最小值为50。

    在ColorSettingViewController进行颜色参数的改变后能直接引起MainViewController中小球颜色对应变化,还有SetingsView的当前颜色的文字描述的对应变化,还有ColorSettingView自身的CheckMark的所在行。

    程序开启的时候始终保持上次最终的状态。

MainView进入SetingView为垂直进入,SetingView进入ColorSettingView为导航横向进入。

 

1.2  Controller

 MainViewController,SetingViewController ,ColorSettingViewController三个都是简单ViewController,MainViewController,SetingViewController可以直接继承UIViewController, ColorSettingViewController继承UITableViewController

RoundBallView继承UIView.

我们先看RoundBallView,绘制球的类:

#import "RoundBallView.h"

@implementation RoundBallView

@synthesize ball = _ball;

        - (void)dealloc {
        [_ball release];

        [super dealloc];
        }

        - (id)initWithFrame:(CGRect)frame ball:(BallModel *)aBall {
        if (self = [super initWithFrame:frame]) {
        _ball = [aBall retain];
        }
        return self;
        }

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
        - (void)drawRect:(CGRect)rect
        {
        [super drawRect:rect];

        // Drawing code
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        [[UIColor whiteColor] set];

        CGContextFillRect(ctx, rect);

        [_ball.color set];
        CGRect ballRect = CGRectMake(_ball.location.x - _ball.radius,
        _ball.location.y - _ball.radius,
        _ball.radius * 2,
        _ball.radius * 2);

        CGContextFillEllipseInRect(ctx, ballRect);
        CGContextStrokePath(ctx);

        }

        - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        UITouch *touch = [touches anyObject];
        CGPoint touchPoint = [touch locationInView:self];

        CGFloat dltX, dltY;

        dltX = touchPoint.x - _ball.location.x;
        dltY = touchPoint.y - _ball.location.y;

        CGFloat dest = sqrtf(powf(dltX, 2) + powf(dltY, 2));
        if (dest > _ball.radius) {
        _draging = NO;
        return;
        }

        _draging = YES;

        _dltPoint = CGPointMake(dltX, dltY);
        }

        - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
        if (!_draging) {
        return;
        }

        {
        CGRect redrawRect = CGRectMake(_ball.location.x - _ball.radius,
        _ball.location.y - _ball.radius,
        _ball.radius * 2,
        _ball.radius * 2);
        _ball.location = CGPointMake(-_ball.radius * 2, -_ball.radius * 2);

        [self setNeedsDisplayInRect:redrawRect];
        }
        UITouch *touch = [touches anyObject];
        CGPoint touchPoint = [touch locationInView:self];

        CGPoint pointLocation = touchPoint;

        pointLocation = CGPointMake(pointLocation.x - _dltPoint.x,
        pointLocation.y - _dltPoint.y);

        _ball.location = pointLocation;

        {
        CGRect redrawRect = CGRectMake(_ball.location.x - _ball.radius,
        _ball.location.y - _ball.radius,
        _ball.radius * 2,
        _ball.radius * 2);

        [self setNeedsDisplayInRect:redrawRect];
        }
        }

        - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
        _draging = NO;
        }
        

@end

然后是Ball:

#import "BallModel.h"
#import "AppDelegate.h"

@implementation BallModel

@synthesize color, radius, location;

        - (void)dealloc {
        [color release];

        [super dealloc];
        }

        - (id)initWithColor:(UIColor *)aColor location:(CGPoint)aPoint radius:(CGFloat)itsRadius {
        if (self = [super init]) {
        self.color = aColor;
        self.location = aPoint;
        self.radius = itsRadius;
        }
        return self;
        }

        + (BallModel *)defaultBall {
        static BallModel *_instance = nil;
        if (nil == _instance) {
        NSDictionary *archive = nil;
        archive = [NSKeyedUnarchiver unarchiveObjectWithFile:[AppDelegate archiveFilename]];

        if (nil == archive) {
        archive = [NSDictionary dictionaryWithObjectsAndKeys:
        [UIColor redColor], @"color",
        NSStringFromCGPoint(CGPointMake(55, 55)), @"location",
        [NSNumber numberWithFloat:25.0f], @"radius",
        nil];
        }

        _instance = [[BallModel alloc] initWithColor:[archive objectForKey:@"color"]
        location:CGPointFromString([archive objectForKey:@"location"])
        radius:[[archive objectForKey:@"radius"] floatValue]];
        }

        return _instance;
        }

@end

MainViewController:

#import "MainViewController.h"

@interface MainViewController ()

@end

@implementation MainViewController

        - (void)dealloc {
        [_ball removeObserver:self forKeyPath:@"color"];
        [_ball removeObserver:self forKeyPath:@"radius"];

        [_ball release];
        [_canvas release];

        [super dealloc];
        }

        - (id)init {
        if (self = [super init]) {
        _ball = [BallModel defaultBall];
        [_ball addObserver:self
        forKeyPath:@"color"
        options:NSKeyValueObservingOptionNew
        context:nil];
        [_ball addObserver:self
        forKeyPath:@"radius"
        options:NSKeyValueObservingOptionNew
        context:nil];
        }
        return self;
        }

        - (void)loadView {
        [super loadView];

        _canvas = [[RoundBallView alloc] initWithFrame:[UIScreen mainScreen].bounds ball:_ball];

        UIButton *button = [UIButton buttonWithType:UIButtonTypeInfoDark];
        button.frame = CGRectMake(256, 396, 64, 64);
        [button addTarget:self
        action:@selector(onInfoButtonTapped:)
     forControlEvents:UIControlEventTouchUpInside];

             [self.view addSubview:_canvas];

             [self.view addSubview:button];

             [_canvas release];
             }

             - (void)viewDidLoad
             {
             [super viewDidLoad];
             // Do any additional setup after loading the view.
             }

             - (void)viewDidUnload
             {
             [super viewDidUnload];
             // Release any retained subviews of the main view.
             }

             #pragma mark - 按钮事件

             - (void)onInfoButtonTapped:(id)sender {
             SettingsViewController *settingVC = [[SettingsViewController alloc] initWithBall:_ball];
             UINavigationController *nav = [[UINavigationController alloc]
             initWithRootViewController:settingVC];

             [self presentModalViewController:nav animated:YES];

             [settingVC release];
             [nav release];
             }

             #pragma mark - 观察者

             - (void)observeValueForKeyPath:(NSString *)keyPath
             ofObject:(id)object
             change:(NSDictionary *)change
             context:(void *)context {
             if (object == _ball) {
             [_canvas setNeedsDisplay];
             }
             }

@end

SettingViewController:

#import "SettingsViewController.h"

@implementation SettingsViewController

        - (void)dealloc {
        [_ball removeObserver:self forKeyPath:@"color"];
        [_ball release];

        [super dealloc];
        }

        - (id)initWithStyle:(UITableViewStyle)style
        {
        self = [super initWithStyle:style];
        if (self) {
        // Custom initialization
        }
        return self;
        }

        - (id)initWithBall:(BallModel *)aBallModel {
        if (self = [self initWithStyle:UITableViewStyleGrouped]) {
        _ball = [aBallModel retain];
        [_ball addObserver:self
        forKeyPath:@"color"
        options:NSKeyValueObservingOptionNew
        context:nil];
        }
        return self;
        }

//  颜色列表
        + (NSArray *)arrayColorList {
static NSArray *colorList = nil;
        if (nil == colorList) {
        colorList = [[NSArray alloc] initWithObjects:
        [NSDictionary dictionaryWithObjectsAndKeys:
        [UIColor redColor], @"color",
@"Red", @"name",
        nil],
        [NSDictionary dictionaryWithObjectsAndKeys:
        [UIColor greenColor], @"color",
@"Green", @"name",
        nil],
        [NSDictionary dictionaryWithObjectsAndKeys:
        [UIColor blueColor], @"color",
@"Blue", @"name",
        nil],
        [NSDictionary dictionaryWithObjectsAndKeys:
        [UIColor yellowColor], @"color",
@"Yellow", @"name",
        nil],
        [NSDictionary dictionaryWithObjectsAndKeys:
        [UIColor brownColor], @"color",
@"Brown", @"name",
        nil],
        nil];
        }
        return colorList;
        }

        - (void)viewDidLoad
        {
        [super viewDidLoad];

        // Uncomment the following line to preserve selection between presentations.
        // self.clearsSelectionOnViewWillAppear = NO;

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc]
        initWithBarButtonSystemItem:UIBarButtonSystemItemDone
        target:self
        action:@selector(onDismissButtonTapped:)] autorelease];
        self.title = @"Settings";
        }

        - (void)viewDidUnload
        {
        [super viewDidUnload];
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;
        }

        #pragma mark - TableViewCell

        - (UIView *)sizeSliderView {
        UISlider *slider = [[UISlider alloc]
        initWithFrame:CGRectMake(120, 0, 170, 44)];
        slider.maximumValue = 50.0f;
        slider.minimumValue = 25.0f;
        slider.value = _ball.radius;
        slider.continuous = NO;

        [slider addTarget:self
        action:@selector(onSizeSliderValueChanged:)
     forControlEvents:UIControlEventValueChanged];

             return [slider autorelease];
             }

             #pragma mark - Table view data source

             - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
             {
             // Return the number of sections.
             return 1;
             }

             - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
             {
             // Return the number of rows in the section.
             return 2;
             }

             - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
             {
static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (nil == cell) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
        reuseIdentifier:CellIdentifier] autorelease];
        }

        // Configure the cell...
        cell.textLabel.text = nil;
        cell.accessoryType = UITableViewCellAccessoryNone;
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;

        for (UIView *subview in [cell.contentView subviews]) {
        [subview removeFromSuperview];
        }

        if (0 == indexPath.section) {
        switch (indexPath.row) {
        case 0: {
        NSArray *colorList = [SettingsViewController arrayColorList];
        cell.textLabel.text = @"Color";
        for (NSDictionary *colorInfo in colorList) {
        if ([[colorInfo objectForKey:@"color"] isEqual:_ball.color]) {
        cell.detailTextLabel.text = [colorInfo objectForKey:@"name"];
        break;
        }
        }
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        } break;
        case 1: {
        cell.textLabel.text = @"Size";
        [cell.contentView addSubview:[self sizeSliderView]];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        } break;
default:
        break;
        }
        }

        return cell;
        }

        - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
        switch (section) {
        case 0:
        return @"Display";
        break;

default:
        break;
        }

        return nil;
        }

        #pragma mark - Table view delegate

        - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
        {
        [tableView deselectRowAtIndexPath:indexPath animated:YES];

        // Navigation logic may go here. Create and push another view controller.
        if (0 == indexPath.section) {
        switch (indexPath.row) {
        case 0: {
        ColorSettingViewController *detailViewController = [[ColorSettingViewController alloc]
        initWithBall:_ball];
        // ...
        // Pass the selected object to the new view controller.
        [self.navigationController pushViewController:detailViewController animated:YES];
        [detailViewController release];
        } break;

default:
        break;
        }
        }
        }

        #pragma mark - 按钮事件

        - (void)onDismissButtonTapped:(id)sender {
        [self dismissModalViewControllerAnimated:YES];
        }

        - (void)onSizeSliderValueChanged:(id)sender {
        if ([sender isKindOfClass:[UISlider class]]) {
        _ball.radius = [(UISlider *)sender value];
        }
        }

        #pragma mark - 观察者

        - (void)observeValueForKeyPath:(NSString *)keyPath
        ofObject:(id)object
        change:(NSDictionary *)change
        context:(void *)context {
        if (object == _ball) {
        [self.tableView reloadData];
        }
        }

@end

ColorSettingViewController:

#import "ColorSettingViewController.h"
        #import "SettingsViewController.h"

@implementation ColorSettingViewController

        - (void)dealloc {
        [_ball release];

        [super dealloc];
        }

        - (id)initWithBall:(BallModel *)aBall {
        if (self = [self initWithStyle:UITableViewStyleGrouped]) {
        _ball = [aBall retain];
        }
        return self;
        }

        - (void)viewDidLoad
        {
        [super viewDidLoad];

        // Uncomment the following line to preserve selection between presentations.
        // self.clearsSelectionOnViewWillAppear = NO;

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem;

        self.title = @"Color";
        }

        - (void)viewDidUnload
        {
        [super viewDidUnload];
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;
        }

        #pragma mark - Table view data source

        - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
        {
        // Return the number of sections.
        return 1;
        }

        - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
        {
        // Return the number of rows in the section.
        return [[SettingsViewController arrayColorList] count];
        }

        - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
        {
static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (nil == cell) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
        reuseIdentifier:CellIdentifier] autorelease];
        }

        cell.accessoryType = UITableViewCellAccessoryNone;

        // Configure the cell...

        NSDictionary *colorInfo = [[SettingsViewController arrayColorList] objectAtIndex:indexPath.row];
        cell.textLabel.text = [colorInfo objectForKey:@"name"];
        if ([[colorInfo objectForKey:@"color"] isEqual:_ball.color]) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        }

        return cell;
        }

        - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
        if (0 == section) {
        return @"Color Select";
        }

        return nil;
        }

        #pragma mark - Table view delegate

        - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        if (0 == indexPath.section) {
        UIColor *color = [[[SettingsViewController arrayColorList]
        objectAtIndex:indexPath.row] objectForKey:@"color"];
        _ball.color = color;
        [tableView reloadData];
        }
        return indexPath;
        }

        - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
        {
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        }

@end

代码在https://download.csdn.net/download/baidu_nod/10837939

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP