day04-超级猜图

来源:互联网 发布:泰山学院网络管理系统 编辑:程序博客网 时间:2024/05/16 06:05

前言

视图不能交互的几种情况

1./**视图不能交互的几种情况:1.视图的属性 1》 [[UIButton alloc] init].alpha <= 0.01 2》[[UIButton alloc] init].hidden= YES 3》[[UIButton alloc] init].userInteractionEnabled =NO; UIImageView /UILabel 的userInteractionEnabled 属性默认为NO2. 若父视图不允许交互,则子视图也是一样不能交互 3.位于父视图的不可见范围的子视图部分 是不能交互的(可以使用clip subviews 属性进行验证);即只有在父视图可见范围才可以交互 */- (IBAction)click {    /**     1.Oc风格BOOL 具有 YES 和 NO。实用8位存储空间。从最低位算起。 YES定义为1,NO定义为0。     2.控制台输出布尔值     NSLog(@"ifReadOnly value: %@" ,ifReadOnly?@"YES":@"NO");     */    NSLog(@"%d",([[UIImageView alloc]init].userInteractionEnabled ? YES: NO));//@property (nonatomic, getter=isUserInteractionEnabled) BOOL userInteractionEnabled; // default is NO    NSLog(@"%d",([[UIButton alloc] init].userInteractionEnabled? YES: NO));//1}2.//  UIView.userInteractionEnabled属性@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled;  // default is YES. if set to NO, user events (touch, keys) are ignored and removed from the event queue.,但 UIImageView /UILabel 的userInteractionEnabled 属性默认为NO

掌握:
一、按钮的多功能使用
图层(蒙板、或者说遮罩)的操作--蒙板通常是UIButton对象

二、@2x的含义
1、Retina 屏幕

1》对点和像素的理解

这里写图片描述

提交App Store的时候记得上传这类图标1024x1024 App list in iTunes on devices with retina display

四、数组乱序的实现

////  ViewController.m//  02-for////  Created by devzkn on 3/12/16.//  Copyright © 2016 hisun. All rights reserved.//#import "ViewController.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    //使用块代码实现数组排序和乱序    //  数组不能存储nil,因为OC是采用nil 来判断数组是否结束--Collection element of type 'void *' is not an Objective-C object    NSArray *array = @[@(1),@(4),@(5),@(2)];//快速包装NSNumber类型数组    for (NSNumber *number  in array) {        NSLog(@"%@",number);    }    array = [array sortedArrayUsingComparator:^NSComparisonResult(NSNumber *number1, NSNumber *number2) {        //乱序-->一会升序,一会乱序        //随机        int seed = arc4random_uniform(2);//0-1 之间的随机数        if (seed) {//1 YES 被定义为1            return [number2 compare:number1];        }        return [number1 compare:number2];    }];    NSLog(@"%@",array);}/** sortedArrayUsingComparator 块代码数组排序 */- (NSArray *) sortedArrayUsingComparator: (NSArray *)array{    //0 . 数组排序Returns an array that lists the receiving array’s elements in ascending order, as determined by the comparison method specified by a given NSComparator Block.    //1> 返回参数typedef NS_ENUM(NSInteger, NSComparisonResult) {NSOrderedAscending = -1L, NSOrderedSame, NSOrderedDescending};    array = [array sortedArrayUsingComparator:^NSComparisonResult(NSNumber *number1, NSNumber *number2) {        //比较方法(规则)        /**         2016-03-12 11:46:04.539 02-for[1880:51443] nimber1= 1 ;number2= 4         2016-03-12 11:46:04.539 02-for[1880:51443] nimber1= 5 ;number2= 2         2016-03-12 11:46:04.540 02-for[1880:51443] nimber1= 4 ;number2= 5         2016-03-12 11:46:04.540 02-for[1880:51443] nimber1= 4 ;number2= 2         2016-03-12 11:46:04.540 02-for[1880:51443] nimber1= 1 ;number2= 2         1 4 5 2->4 1 5 2 ->4 1 5 2 ->5 4 1 2 -> 5 4 1 2 -> 5 4 2 1         */        NSLog(@"nimber1= %@ ;number2= %@",number1,number2);        return [number2 compare:number1];//NSOrderedAscending if the value of aNumber is greater than the number object’s, NSOrderedSame if they’re equal, and NSOrderedDescending if the value of aNumber is less than the number object’s. 返回数组元素的比较结果    }];    NSLog(@"%@",array);    return array;}/** 块代码遍历数组 */- (void)arrayWith: (NSArray *)array {    //1》 数组的遍历Executes a given block using each object in the array, starting with the first object and continuing through the array to the last object.    //2>obj    The element in the array.对象    idx    The index of the element in the array. 索引   stop    A reference to a Boolean value. The block can set the value to YES to stop further processing of the array. The stop argument is an out-only argument. You should only ever set this Boolean to YES within the Block.是否中断    //3 > 块数组的遍历方法效率比 for in 方式来的高    [array enumerateObjectsUsingBlock:^(NSNumber *obj, NSUInteger idx, BOOL *stop) {        NSLog(@"%@ idx= %lu",obj,idx);        if (1 == idx) {            *stop = YES;//退出循环        }    }];}@end

五、主要方法,尽量保留简洁代码,体现思路和流程即可

ps:p s:0>xcode 的快捷键:option+command+left(代码折叠)、
1> 模拟器的快捷键 :切换屏幕 shift+command+h(显示主界面)、shift+command+h+h(结束程序)

六、等待一段时间,再让线程调用方法的例子

1》 延迟进入下一题-》目的是给玩家展示绿色答案文字//等待0.5秒,直接进入下一题Invokes a method of the receiver on the current thread using the default mode after a delay.        [self updateAnswerButtonTitleColor:[UIColor greenColor]];//动画显示答案字体为绿色        [self performSelector:@selector(nextQuestion) withObject:nil afterDelay:1.0];//2》 动画结束要清空UIImageView 对象的属性AnimationImages,即设置其为nil    //清除内存的代码简化--可以避免定义cleanUpAnimationsArray方法,直接调用setAnimationImages方法进行arrayImage的清除    [self.imageList performSelector:@selector(setAnimationImages:) withObject:nil afterDelay:self.imageList.animationDuration];//- (void)cleanUpAnimationsArray{//    NSLog(@"%s ",__func__);//    //动画结束之后清除帧动画数组//    [self.imageList setAnimationImages:nil];////}

七、 实现方法的时候,考虑执行该方法的条件

//1.再定义方法时,首先考虑的一个问题是:先判断是否达到执行该方法的资格(条件),否则直接return//1》答案区的点击事件#pragma mark - 答题按钮的监听方法,若答案按钮标题的空的,没必要执行本方法/** 处理答题按钮点击事件 */- (void) answerButtonClick:(UIButton *) answerButton{    //1.如果当前答案按钮没有标题,直接return    if (nil == answerButton.currentTitle) {        return;    }//2》 候选区的点击事件,若答案区都是满的,就没必要执行该方法#pragma mark - 候选按钮点击方法;- (void)optionButtonClick:(UIButton *)button{    //1.找到答案区的第一个没有标题的按钮    UIButton *nilTitleButton = [self firstNilTitleAnswerButton];    if (nil == nilTitleButton) {//找不到空标题按钮,return        return;    }

八、字符串对象是否为空的判断

//1.对象比较的效率 比数值型比较效率低//1>效率好些的空字符串对象判断: if (0 == answerButton.currentTitle.length) {        return;    }//2>效率低: if (nil == nilTitleButton) {//找不到空标题按钮,return        return;    }

正文

疯狂猜图案例的需求分析
Click here to expand…疯狂猜图案例的需求分析

1.搭建界面
1》上半部分空间位置固定的,使用storyBoard进行布局连线
2》下半部分的控件,是根据题目的变化而变化-》采用代码方式进行界面搭建
2.编写代码(按照流程进行实现,即用户的操作习惯流程)
1》大图小图的切换
2》下一题的实现
3》备选按钮点击事件处理(让文字进入答案区)
4》判断胜负:胜利,界面切换到下一题;失败,提示用户重新选择答案
5》答题按钮点击事件的处理:把答案区的文字恢复到备选区域
3.收尾工作
图标和启动页面

总结

OC 解决NSArray直接打印中文出现乱码的问题?

解决方法:就是需要通过为NSArray添加分类,重写 - (NSString *)descriptionWithLocale:(id)locale方法即可

控制器的代码实现

////  ViewController.m//  01-超级猜图////  Created by devzkn on 3/9/16.//  Copyright © 2016 devzkn. All rights reserved.//#import "ViewController.h"#import "HSQuestion.h"#define KButtonWidth  35#define KButtonSpacingWidth 10 // 按钮的行间距#define KButtonSpacingHeight 5 //按钮的列间距#define KButtonHeight  35//九宫格算法 x 决定的是其所在的列,y 决定其所在的行#define KButtonColumn 7 //列数#define KButtonRow 3//行数@interface ViewController ()@property (weak, nonatomic) IBOutlet UIButton *iconButton;//图像按钮@property (nonatomic,weak) UIButton *cover;//蒙板@property (nonatomic,strong) NSArray *questions;//问题数组@property (nonatomic,assign) int index;//当前题目index@property (weak, nonatomic) IBOutlet UILabel *noLabel;@property (weak, nonatomic) IBOutlet UILabel *titleLabel;@property (weak, nonatomic) IBOutlet UIButton *nextButton;@property (weak, nonatomic) IBOutlet UIView *answerView;@property (weak, nonatomic) IBOutlet UIView *optionsView;@property (weak, nonatomic) IBOutlet UIButton *coinButton;//金币按钮@end@implementation ViewController/** 懒加载questions */- (NSArray *) questions{    if (nil == _questions) {        _questions = [HSQuestion questionList];    }    return _questions;}/** 懒加载蒙板按钮控件 */- (UIButton *)cover{    if (nil == _cover){        //创建蒙板        UIButton *tmpCover = [[UIButton alloc]initWithFrame:self.view.bounds];        [tmpCover setBackgroundColor: [UIColor colorWithWhite:0.0 alpha:0.5]];        [tmpCover setAlpha:0.0];        //添加conver图层的监听事件        [tmpCover addTarget:self action:@selector(smallerIconButton) forControlEvents:UIControlEventTouchUpInside];        _cover=tmpCover;        [self.view addSubview:_cover];//cover强引用+1    }    return _cover;}- (void)viewDidLoad {    [super viewDidLoad];    //上半部分的界面控件基本是静态的,采用storyBoard进行实现    //搭建下半部分的界面,采用代码实现    //初始化界面    [self nextQuestion];}/** he preferred status bar style for the view controller.调整状态栏颜色 */- (UIStatusBarStyle)preferredStatusBarStyle NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED{// Defaults to UIStatusBarStyleDefault    return UIStatusBarStyleLightContent;}/** pecifies whether the view controller prefers the status bar to be hidden or shown. 重写方法 */- (BOOL)prefersStatusBarHidden NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED{    return NO;//A Boolean value of YES specifies the status bar should be hidden. Default value is NO.}/** 大图小图切换 */#pragma mark - 大图小图切换--pragma 是预处理命令- (IBAction)biggerSmallerIconButton {    //判断当前的图像按钮是否处于放大状态,如果是就进行缩小,否则进行放大;    //判断依据为蒙板cover的Alpha属性值    if (1.0 == self.cover.alpha) {// Alpha: 1.0 放大状态,0.0 缩小状态        [self smallerIconButton];        return ;    }    [self biggerImage];}#pragma mark - 下一题的实现/** 下一题 1.在主要方法中,尽量保留简短代码,体现思路和流程即可 */- (IBAction)nextQuestion{    //如果题号大于等于总题数 ,直接return,即只有题号self.index为“0-题目总数” 的时候才执行本方法    if (self.questions.count <= self.index || 0 >self.index) {        return;    }    //下一题,在数据模型中是数据递增的关系    //1> 当前答题的index递增    self.index = (self.index <self.questions.count) ? self.index+1 :self.index;    //禁用next Button 的判断,(在题目序号递增之后判断)//    [self.nextButton setEnabled: (self.index >=self.questions.count || self.index < 0 ) ? NO : YES];//当前题目序号大于或者等于题目总数,以及小于0 就禁用,否则就启用    [self.nextButton setEnabled:(self.index>0 && self.index < self.questions.count)];//当题号》0且题号小于总题数,就启用nextbutton按钮,否则禁用button    //2> 根据题目index从数据模型数组取出question对象(题目数据)    HSQuestion *question = self.questions [self.index-1];//当前题目的数据模型在数组中的index=当前题目的index-1    // 3> 通过建立连线获得基本信息控件;修改题目的基本信息(iconImage、title 以及题目的index控件)    [self setupBasicInfo:question];    //4>答案区按钮设置,根据答案的文字个数进行布局    [self createAnswerButtons:question];    //5>创建备选按钮    [self createOptionButtons:question];}/** 设置基本信息 */- (void)setupBasicInfo:(HSQuestion *)question{    //设置iconImage    [self.iconButton setImage:question.iconImage forState:UIControlStateNormal];    //设置title控件    [self.titleLabel setText:[NSString stringWithFormat: @"%@",question.title]];    //设置题目的index    [self.noLabel setText:[NSString stringWithFormat:@"%d/%lu",self.index,self.questions.count]];}/** 创建答案区按钮 */- (void)createAnswerButtons: (HSQuestion *)question{    //清空上一题的答案按钮    for (UIView *button in [self.answerView subviews]) {//使用的UIbutton 都继承于UIView        [button removeFromSuperview];//多态的应用    }    //布局答案区,类似九宫格    //根据答案文字个数往视图添加按钮    //  获取问题答案的个数    long answerNo = question.answer.length;    //第一个button的x值    CGFloat answerX =(CGRectGetWidth(self.answerView.frame)- answerNo*KButtonWidth-(answerNo-1)*KButtonSpacingWidth)*0.5 ;    for (int i= 0; i<answerNo; i++) {        CGFloat x =  answerX + i*(KButtonWidth+KButtonSpacingWidth);        UIButton *answerButton = [[UIButton alloc]initWithFrame:CGRectMake(x, 0, KButtonWidth, KButtonHeight)];        [answerButton setBackgroundColor:[UIColor whiteColor]];        [answerButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];        //设置背景图片        [answerButton setBackgroundImage:[UIImage imageNamed:@"btn_answer"] forState:UIControlStateNormal];        [answerButton setBackgroundImage:[UIImage imageNamed:@"btn_answer_highlighted"] forState:UIControlStateHighlighted];        //设置按钮的监听方法        [answerButton addTarget:self action:@selector(answerButtonClick:) forControlEvents:UIControlEventTouchUpInside];        [self.answerView addSubview:answerButton];    }}/** 创建候选区按钮, */- (void)createOptionButtons:(HSQuestion *)question{    //1》如果已经存在候选按钮,就直接修改按钮标题,不用在创建候选按钮    NSArray *subviewsArray = [self.optionsView subviews];    if (subviewsArray.count >=        question.options.count) {        //获取按钮文字        for (int i=0 ;i<subviewsArray.count;i++) {            [subviewsArray[i] setTitle:question.options[i] forState:UIControlStateNormal];            //设置按钮为可见            [subviewsArray[i] setHidden:NO];        }        return;//设置完标题直接结束方法    }    //2》创建候选按钮    // 设置候选区按钮显示内容(用模型数据装配),根据候选文字总数 进行布局,并使用乱序算法进行装配按钮控件//    //  清空上一题候选按钮(清除optionsView的所有子视图)    for (UIView *view in [self.optionsView subviews]) {        [view removeFromSuperview];    }    //根据列数、行数 的个数 进行候选区的的布局(九宫格)    //定义行第一列的buttonX值    CGFloat optionMarginX = (CGRectGetWidth(self.optionsView.frame)-KButtonColumn*KButtonWidth -(KButtonColumn-1)*KButtonSpacingWidth)*0.5;    CGFloat optionMarginY = (CGRectGetHeight(self.optionsView.frame)- KButtonRow*KButtonHeight-(KButtonRow-1)*KButtonSpacingHeight)*0.5;    //对候选答案进行乱序可在数据模型HSQuestion questionList方法中实现    //布局候选按钮,并装配数据    for (int i =0 ; i<question.options.count; i++) {        //创建候选按钮        int columnNo = i%KButtonColumn ;//button 所在的列        int rowNo = i/KButtonColumn;//button 所在的行数        //计算button 的x,y        CGFloat x = optionMarginX +columnNo*(KButtonWidth+KButtonSpacingWidth);//x 值与列数相关        CGFloat y = optionMarginY+rowNo*(KButtonHeight+KButtonSpacingHeight);//y值与行数关联        UIButton *optionButton = [[UIButton alloc] initWithFrame:CGRectMake(x, y, KButtonWidth, KButtonHeight)];        [optionButton setBackgroundColor:[UIColor whiteColor]];        //设置候选答案文字        [optionButton setTitle:question.options[i] forState:UIControlStateNormal];        //设置按钮文字font        [optionButton.titleLabel setFont:[UIFont systemFontOfSize:12]];        //设置文字颜色        [optionButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];        //设置按钮的背景图片        [optionButton setBackgroundImage:[UIImage imageNamed:@"btn_option"] forState:UIControlStateNormal];        [optionButton setBackgroundImage:[UIImage imageNamed:@"btn_option_highlighted"] forState:UIControlStateHighlighted];        //设置候选按钮的监听方法        [optionButton addTarget:self action:@selector(optionButtonClick:) forControlEvents:UIControlEventTouchUpInside];        [self.optionsView addSubview:optionButton];    }}#pragma mark - 候选按钮点击方法- (void)optionButtonClick:(UIButton *)button{    //1.找到答案区的第一个没有标题的按钮    UIButton *nilTitleButton = [self firstNilTitleAnswerButton];    if (nil == nilTitleButton) {//找不到空标题按钮,return        return;    }    //找到了空标题按钮的操作:    //2.将按钮标题设置到答题区视图的第一个空标题按钮中    [nilTitleButton setTitle:button.titleLabel.text forState:UIControlStateNormal];    [button setHidden:YES];        //将按钮设置为不可见    //3.判断胜负(如果答案区的按钮均非空,即可进行答案判断)    [self judge];}/** 判断结果,并提示玩家 */-(void)judge{    //1>  判断用户是否填写完问题,填完整了,才需要判断结果,否则return    NSArray *array = [self.answerView subviews];    //用户填写答案    NSMutableString *userAnswer = [[NSMutableString alloc]init];    for (UIButton *btn in array) {        if (btn.currentTitle.length == 0) {//如果有一个空为空,直接return            return ;        }        [userAnswer appendString:btn.currentTitle];    }    //2> 获取问题答案,进行比对,如果错误,就在答案区提示玩家,否则直接进入下一题    //获取正确答案    HSQuestion *question = self.questions[self.index-1];//当前题号-1 即使其所在数组对应的下标    if ([question.answer isEqualToString:userAnswer]) {        [self updateAnswerButtonTitleColor:[UIColor greenColor]];//动画显示答案字体为绿色        //分数奖励        [self changeScore:500];        //等待0.5秒,直接进入下一题Invokes a method of the receiver on the current thread using the default mode after a delay.        [self performSelector:@selector(nextQuestion) withObject:nil afterDelay:1.0];        return;    }    //3>提示玩家重新选择,将答题按钮文字颜色改为红色    [self updateAnswerButtonTitleColor:[UIColor redColor]];}/** 修改答题区按钮的颜色 */- (void) updateAnswerButtonTitleColor:(UIColor *)color{    [UIView animateWithDuration:10.0f animations:^{        for (UIButton *answerButton in [self.answerView subviews]) {            [answerButton setTitleColor:color forState:UIControlStateNormal];        }    }];}#pragma mark - 答题按钮的监听方法/** 处理答题按钮点击事件 */- (void) answerButtonClick:(UIButton *) answerButton{    //1.如果当前答案按钮没有标题,直接return    if (0 == answerButton.currentTitle.length) {        return;    }    //2.执行此方法,意味着用户去除掉了一个字(即答题区的内容不完整),此时应将答案区的文字颜色恢复成黑色    [self updateAnswerButtonTitleColor:[UIColor blackColor]];    //3.设置与“当前按钮的”相同标题的候选区按钮为可见(执行到这里按理都会有存在这样的候选按钮)    [[self optionButtonWithTitle:answerButton.currentTitle isHidden:YES] setHidden:NO ];    //移除当前按钮的标题    [answerButton setTitle:nil forState:UIControlStateNormal];}/** 根据title查找候选区按钮,特殊要求(规则,目标按钮的Hidden属性为YES 或者为NO)  */- (UIButton *) optionButtonWithTitle:(NSString *)title isHidden:(BOOL)isHidden{    //考虑候选区有重复标题按钮的问题,增加Hidden属性的判断,只有为YES才是“答案按钮点击功能”要找的目标按钮;只有为NO的按钮才是“提示功能”要找的目标    for (UIButton *optionButton in [self.optionsView subviews]) {        if ([title isEqualToString:optionButton.currentTitle] && (optionButton.hidden == isHidden)) {            return optionButton;        }    }    return nil;}/** 查找文字为空的按钮 */- (UIButton *)firstNilTitleAnswerButton{    NSArray *answerButtonArray =[self.answerView subviews];    for (UIButton *button in answerButtonArray) {        //找出没有标题的按钮        if (0 == button.currentTitle.length ) {//这个判断方法比使用nil 进行判断的效率更高            return button;        }    }    return nil;}/** 放大图片 */- (void)biggerImage {    //0>biggerSmallerIconButton 保证将图像按钮bringSubviewToFront之前,cover的已经创建完成    //1》将图像按钮添加至最顶层 Moves the specified subview so that it appears on top of its siblings.    [self.view bringSubviewToFront:self.iconButton];    //2》用块动画放大图像按钮    CGFloat width = CGRectGetWidth(self.view.frame);    CGFloat height = width;    CGFloat x=0;    CGFloat y= (CGRectGetHeight(self.view.frame)- height)*0.5;    //块动画    [UIView animateWithDuration:1.0f animations:^{        //动画内容:修改图像按钮大小、位置以及cover的透明度        [self.iconButton setFrame:CGRectMake(x, y, width, height)];        [self.cover setAlpha:1.0];    }];}/** 将图像按钮恢复原来大小 */- (void) smallerIconButton{    //使用块动画恢复icon Button的大小和位置,块动画是预先准备好的代码,一旦定义,将立即执行    [UIView animateWithDuration:1.0f animations:^{        [self.iconButton setFrame:CGRectMake(85, 85, 150, 150)];        [self.cover setAlpha:0.0];//将cover按钮控件设为不可见    }];    //设置图像按钮的放大、缩小状态    [self.iconButton setTag:0];}#pragma mark - 提示功能/** 1.提示功能的实现(用代码代替用户的按钮点击行为) 2. 提示功能,是要进行扣分,即执行该功能你必须达到消费的积分额度 */- (IBAction) tip{    if (self.coinButton.currentTitle.intValue <500) {//金币数小于本次消费的金币额度,直接结束        return;    }    //1.清空答案区的title并恢复候选按钮    [self cleanAnswerButtons];    // 2.取出正确答案的第一个字,并设置到都一个答案按钮,并隐藏候选区对应的按钮    //获取当前题目模型对象    HSQuestion *question =self.questions[self.index-1];    //获取与“正确答案第一个字母”相同标题候选按钮    UIButton *optionButton = [self  optionButtonWithTitle:[question.answer substringToIndex:1] isHidden:NO];    //设置标题到答案区,并隐藏候选区按钮    [self optionButtonClick:optionButton];    //进行分数的扣减    [self changeScore:-500];}/** 清空答案区按钮,并恢复候选按钮 */- (void) cleanAnswerButtons{    for (UIButton *btn in [self.answerView subviews]) {        //直接调用答案按钮的监听方法        [self answerButtonClick:btn];//    }}#pragma mark - 分数处理/** 分数处理 */- (void) changeScore:(int) score{    score += self.coinButton.currentTitle.intValue ;    [self.coinButton setTitle: [NSString stringWithFormat:@"%d",score] forState:UIControlStateNormal];}@end
原创粉丝点击