斯坦福大学IOS7开发课程2
这节课就着手开始实现”Card Matching Game”,纸牌匹配游戏。
具体来说就是实现涉及的各种类,以及XCode的简单使用。
Card类
下面代码是课程1结束时的Card类,包括Card.h
和Card.m
:
1 | // Card.h |
1 | // Card.m |
Deck类
这节课首先添加另外一个类:整幅牌Deck,下面是上节课学的类的基本结构
1 | // Deck.h |
1 | // Deck.m |
接下来为Deck类添加两个基础的方法:
- 向Deck中添加牌的
addCard
,其中atTop表示是否将新的牌放在牌堆的顶部。 - 另一个是从Deck中随机抽取牌的
drawRandomCard
:
1 | // Deck.h |
如果希望addCard
的参数atTop
是可选参数,在Objective-C中唯一的方法就是声明一个新的函数,这个函数也叫addCard
,但是没有参数atTop
。这两个addCard
是两个不同的函数,相互之间并没有关联。
1 | // Deck.h |
为了存储牌堆中的牌,需要在私密API中添加一个属性,类型是可变数组NSMutableArray
。mutable意味着可以向数组中添加或删除数据,而普通的NSArray
是不能修改的,一旦被建立,不能添加数据也不能删除。
在Objective-C中声明数组没办法指定数据类型。
1 | // Deck.m |
根据上节课说到构建属性时自动生成的getter和setter,新建一个Deck类后,其所有的变量和属性都会被自动初始化为0/nil,属性cards
是一个空指针,因此调用addCard
时虽然不会导致程序的崩溃,但是也不能正常工作。
那么怎么解决这个问题呢?方法是重写属性的getter函数,在getter中添加一个判断结构,属性cards自动生成的getter是:
1 | - (NSMutableArray *)cards |
为了在其中添加一个判断逻辑,需要手动重写这个getter:
1 | // Deck.m |
接下来实现drawRandomCard
1 | // Deck.m |
至此,Deck类已经完成。
PlayingCard类
接下来再添加一个类:PlayingCard
,同样的,基本结构如下:
1 | // PlayingCard.h |
1 | // PlayingCard.m |
给类添加两个属性suit
和rank
,前者表示牌的花色“桃(hearts)”、“(方片)diamons”、“(梅花)clubs”,后者表示1到13。另外在.m
文件中,重写父类属性content的getter。
1 | // PlayingCard.h |
1 | // PlayingCard.m |
注意到,字符串前面有个@
,这表示把字符串变成一个字符串类。其中%@
表示一个对象,当然可以是字符串。
重写父类属性contents的getter之后,获取contents内容会返回“数字 + 花色”,比如“3红桃”、“1梅花”、“13方片”等。但是在纸牌中,我们一般会把1说成A,11说成J等……,为了符合这个习惯,上面的contents重写可以改成下面的代码:
1 | // PlayingCard.m |
将rank的0设置为”?“是因为objective-C默认将rank初始化为0,”?“表示这是未知的,没有经过设置的。那如果花色没经过设置也会显示”?“就更好了,解决方法也是重写suit属性的getter函数。
1 | // PlayingCard.m |
suit的选择应该只有四种,为了防止suit被设置为其他值,还要重写suit属性的setter:setSuit
1 | // PlayingCard.m |
值得注意的是,setSuit
中的第一个@
表示创建新的数组,在这里,每次判断都会新建这个数组。为了性能和代码简介,可以新建函数来判断setter收到的suit是否有效。实际上,这种改变对性能的提升是极其有限的。
1 | // PlayingCard.m |
这里在函数实现前面第一次出现了+
符号,这个符号表示这个函数是类的函数(而不是对象的函数)。
一般只在两种情况下使用类的函数:
工具函数(utility method),比如这里的
validSuits
。创建类的函数,比如
stringWithFormat
。对rank属性做同样的检查和优化,并添加一个公开API
maxRank
返回rank的最大值,比如现在是13。
1 | // PlayingCard.h |
1 | // PlayingCard.m |
PlayingCardDeck类
接下来可以开始玩牌了,创建一个新的类PlayingCardDeck
,继承自Deck
类,但是需要重写构造函数:
1 | // PlayingCardDeck.h |
1 | // PlayingCardDeck.m |
XCode的简单使用
课程剩余的部分就是以纸牌游戏为例,简单介绍XCode的使用,开发一个简单的App,App内容是显示纸牌,点击纸牌将其翻转。
由于课程介绍的是XCode 5,笔者记笔记的时候已经是XCode 12.4了,有了不小的变化,参考笔者另一篇笔记(Objective-C IOS开发之HelloWorld),应该也不难完成,就不再具体介绍实现了。
相较于HelloWorld这个App,课程中实现的App另外涉及了以下知识点:
图像添加
直接将图片拖到
Assets.xcassets
文件夹中button背景图片的设置
点击button,在属性中点击
Background
下拉菜单,就会显示上一步添加的图片选项,以及一些原始icon。Action中的sender其实就是触发事件的View对象
类的添加
添加类的方法,XCode 12中其实就是新建
Cocoa Touch Class
。