iOS7应用开发3、Objective-C

【跟随教授的讲解和演示,并重做了课上的demo之后,惊奇地发现自己写的程序有bug,界面上12张卡牌出现后,点击任何一个,其他所有卡牌都会变成一块白板……在经历了长时间的调试之后悲催地发现,在最后的updateUI这个函数中改变背景的函数写错了,setBackgroundImage:写成了setImage:,被这一无脑的失误纠结了这么久,丢人啊……各种bug改完后,前几次课的代码都已经传到博客的资源中了,可到我的资源页下载。】

这一课中,之前实现的扑克牌翻转被扩展为一个比较完整的卡牌点数和花色比较游戏。程序的xib界面和包含的文件如下图所示:

其中的各个文件的具体内容,课程附带的pdf中均有详细的代码,也可以参照下载资源中我敲进去的代码。界面上的12张卡牌,每一个都与touchCardButton:函数联系,也就是说点击任意一张牌都会调用touchCardButton这个函数。

- (IBAction)touchCardButton:(UIButton *)sender
{
	int index = [self.cardButtons indexOfObject:sender];
	[self.game chooseCardAtIndex:index];   
	[self updateUI];

}

这个函数中只有三条语句,但是背后实现了全部的功能。

第一句:

int index = [self.cardButtons indexOfObject:sender];

从界面上的12张卡牌的按钮中获取选中的索引,也就是点了哪一张牌;

第二句:

[self.game chooseCardAtIndex:index];

看似简单,背后却包含大量的工作。首先self.game调用了view controller中重载的getter方法:

-(CardMatchingGame *) game
{
    if (!_game)
    {
        _game = [[CardMatchingGame alloc] initWithCardCount:[self.cardButtons count] usingDeck:[self createDeck]];
    }
    return _game;
}

在这个函数中又调用了createDeck和CardMatchingGame类的initWithCardCount方法,模拟了“发牌”的这个过程。当self.game这个函数执行完后,可以认为不但已经完成了游戏规则的定义,同时也确定了扣在牌桌上的12张牌是哪些。

随后调用的chooseCardAtIndex是CardMatchingGame类的成员函数,实现了翻牌后对这张牌状态的判断,包括判断牌之前是否被选中、是否处于与其他牌匹配的状态中等等。

- (void)chooseCardAtIndex:(NSUInteger)index
{
    Card *card = [self cardAtIndex:index];
    if (!card.isMatched)
    {
        if (card.isChosen)
        {
            card.chosen = NO;
        }
        else
        {
            //与其他比较
            for (Card *otherCard in self.cards)
            {
                if (otherCard.isChosen && !otherCard.isMatched)
                {
                    int matchScore = [card match:@[otherCard]];
                    if (matchScore)
                    {
                        self.score += matchScore * MATCH_BONUS;
                        card.matched = YES;
                        otherCard.matched = YES;
                    }
                    else
                    {
                        self.score -= MISMATCH_PENALTY;
                        otherCard.chosen = NO;
                    }
                    break;
                }
            }
            self.score -= COST_TO_CHOOSE;
            card.chosen = YES;
        }
    }
}

该函数执行完成后,Model数据(也就是在self.game中的卡牌数据)根据规则发生了变化(主要是卡牌的match和chosen两个属性)。随后调用的[self updateUI]中将重新遍历这些数据,并根据其变化更新界面,包括显示选定的牌、将处于匹配状态下的牌锁定。

-(void) updateUI
{
    for (UIButton *cardButton in self.cardButtons)
    {
        int index = [self.cardButtons indexOfObject:cardButton];
        Card *card = [self.game cardAtIndex:index];
        [cardButton setTitle:[self titleForCard:card] forState:UIControlStateNormal];
        [cardButton setBackgroundImage:[self backgroundImageForCard:card] forState:UIControlStateNormal];

        cardButton.enabled = !card.isMatched;
    }
    self.scoreLabel.text = [NSString stringWithFormat:@"Score: %d",self.game.score];
}

回顾整个工程,教授的确是将之前讲述的MVC的思想深刻地贯彻到了工程之中,把数据、规则和界面区分的非常清楚。这样做的好处就是不但程序清晰明了,而且扩展性强,在未来对某个模块进行扩展的时候,可以获得更好的兼容性。

时间: 2024-12-28 16:38:43

iOS7应用开发3、Objective-C的相关文章

iOS7应用开发1、菜鸟那点儿事儿

序:今天开始新开一个坑,作为一个准备了许久却依然摆脱不了24k纯菜鸟身份的程序员,跟随Stanford的世界未来精英们一起学习iOS7应用开发的相关知识,同时也是为了自己以后的业余项目做准备,提升自己的工作筹码.我所follow的教程来自itunes上面斯坦福大学的公开课程<Developing iOS 7 Apps for iPhone and iPad>,很容易就能找到.这些博客除了作为追课过程中的笔记之外,可能也会有搜集到的与这次课相关的一些资料,和一些个人体会.只作为自己的记录,不敢保

iOS7应用开发9:autolayout自动布局

[时间太紧张,追课的过程中感觉压力很大,时间不够用的问题相当严重.想单靠业余时间自学一门技术果真不是一件容易的事儿,就拿上节课的animation来说吧,文章里基本上只能记录了一下课程的大纲,很多具体的内容都完全没弄清楚,demo也只是完全按照课上的演示逐句敲好.等赶上进度后,肯定是要回来复习的,届时会尽可能细致地研究ios开发的细节问题.] 1.自动布局的概念: 自动布局会在不同的设备屏幕尺寸或者设备的摆放位置(垂直/水平),以及其他显示视图面积发生改变的时候,自动地设置显示的视图的位置.自动

iOS7应用开发5、视图控制器View Controller及其生命周期

1.UITextView: 该类与Label类类似,可显示多行,可以编辑内容,可以滚动查看内容: 包含属性NSTextStorage *textStorage,该类是NSMutableAttributedString的基类:修改该属性可以自动更新UITextView的内容: 包含属性UIFont *font,用于设置所有字符的字体: NSTextContainer *textContainer和NSLayoutManager *layoutManager属性,用于设置文本的其他一些属性: 2.视

iOS7应用开发6:UINavigation, UITabbar控制器的多态性

1.前期所实现的PlayingCard游戏,其View Controller只能适应PlayingCard这一种游戏规则.而将createDeck函数修改为返回一个nil后,整个View Controller与PlayingCard就没有关系了(同时也就没法运行了),成为了一种抽象的概念(类似于C++中的抽象类),实际的控制器必须派生这个类才能实现自身的功能. 新建一个View Controller类,并实现createDeck方法.此时build工程,无法正常运行.因为当前storyboard

iOS7应用开发14、MapKit框架

MapKit Framework的基本概念: MapKit Framework提供了可以将地图直接嵌入到窗口和视图中的功能,同时还提供了地图标注.添加弹窗显示.进行反地理信息编码以通过地标信息查找经纬度坐标等功能. MKMapView类显示了一个地图视图,其中有一个位置指示器(annotation)提示了当前的位置坐标以及说明.可以利用该类实例显示地图信息并根据应用提供的数据改变地图的内容,如将地图的某个坐标点置于视图中心点.指定地图显示的大小区域和根据自定义信息创建标记点等. MKMapVie

iOS7应用开发7:自定义视图、手势操作

1.视图: #屏幕上表示某一个矩形区域:某个视图只能有一个父视图,但是可能有多个子视图: #UIWindow:屏幕视图,在整个视图结构体系的最上层,仅适用于ios应用: #添加视图的函数: - (void)addSubview:(UIView *)aView; - (void)removeFromSuperview; #在MVC结构中,视图结构体系最上层的是属性@property view: #初始化UIView:awakeFromNib函数,或{[UIView alloc] init]; #视

iOS7应用开发16:模态segue、文本框、警告、Action Sheet

1.模态segue(Modal Segue): 这是除了popover和embed之外的另一种视图控制器切换的方法.当切换到模态视图控制器Modal View Controller出现时,该控制器将占据整个可操作空间知道该控制器消失. 与push方法不同的是,该类viewcontroller出现时左上角通常没有返回箭头,而是采用其他方式返回:从某个界面返回会回到之前的界面. 建立方法:在之前一个vc的某个控件(如按钮等)上ctrl+拖动到目标vc,segue类型选择"Modal". 参

iOS7应用开发4、Foundation框架

1.动态绑定:id类型的对象,表示指向未知类型对象的指针: 指向对象的实际类型在运行时指定.在使用时,注意check该对象是否响应调用的方法(respondsToSelector).可以将一个静态类型的对象付给id类对象. [NSArray firstObject]等函数返回值本质上就是id类型. id本身就是指针类型,所以不存在id *pObject这种写法. 当向id类型的对象发送消息时,编译时不会出现警告,但是若其实际指向的对象没有实际上没有那个方法,则在运行时会崩溃. 2.关于内省(in

iOS7应用开发15:嵌入型segue

同弹出型segue不同,嵌入型segue是另一种视图控制器的切换方式.嵌入型segue将某一个视图控制器的视图(其self.view)嵌入到另一个视图控制器的视图结构中,即让某一个视图控制器的self.view成为另一个视图控制器的self.view的子视图. 1.首先建立一个容器视图:container view,类似其他控件,在右侧栏拖入storyboard中即可: 2.在容器视图和目标视图控制器之间ctrl+拖动,弹出菜单中选择embed: 3.在segue属性中设置segue的id,并实