仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2017|回复: 19
打印 上一主题 下一主题

[学习教程] IOS编程:TDD的iOS开辟开端和Kiwi利用进门仓酷云

[复制链接]
小魔女 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:32:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
又盲看一些关于Objective-C的一些语法基础和规则。之前有一定的C和C++还有Java的基础,所以看起来还是不会很吃力的,各种语言的思想相差还是不会很大的。测试驱动开辟(TestDrivenDevelopment,以下简称TDD)是包管代码质量的不贰法例,也是先辈程序开辟的共鸣。Apple一向努力于在iOS开辟中集成加倍便利和可用的测试,在Xcode5中,新的IDE和SDK引进了XCTest来替换本来的SenTestingKit,而且作废了新建工程时的“包含单位测试”的可选项(一样报酬的另有利用ARC的可选项)。新工程将主动包括测试的target,而且相干框架也搭建终了,能够说测试终究挣脱了iOS开辟中“二等国民”的位置,如今已变得和产物代码一样主要了。我信任每一个工程师在完成本人的营业代码的同时,也有最基础的编写和保护响应的测试代码的任务,以包管本人的代码可以准确运转。更进一步,假如可以利用TDD来举行开辟,不但能包管代码运转的准确性,也有助于代码布局的布置和思索,有助于本身的不休进步。我在最入手下手举行开辟时也曾对测试五体投地,但厥后有数的凄惨教导让我分明那末多工程师痴迷于测试大概寻求更完善的测试,是有其深入寄义的。假如您之前还没有入手下手为您的代码编写测试,我激烈倡议,从明天入手下手,从如今入手下手(大概做不到的话,也请从下一个项目入手下手),编写测试,大概实验一下TDD的开辟体例。

<p>而Kiwi是一个iOS平台非常好用的举动驱动开辟(BehaviorDrivenDevelopment,以下简称BDD)的测试框架,有着十分大度的语法,能够写出布局性强,十分简单读懂的测试。由于国际如今有关Kiwi的先容对照少,加上在测试这块很能良多工程师们并没有出格寄望,程度条理大概相差会很远,因而在这一系列的两篇博文中,我将重新入手下手先复杂地先容一些TDD的观点和头脑,然后从XCTest的最复杂的例子入手下手,过渡到Kiwi的测试天下。鄙人一篇中我将持续深切先容一些Kiwi的其他稍高一些的特征,以期更多的开辟者可以打仗并利用Kiwi这个优异的测试框架。
甚么是TDD,为何我们要TDD

测试驱动开辟并非一个很奇怪的观点了。软件开辟工程师们(固然包含你我)最入手下手进修程序编写时,最喜好干的事变就是编写一段代码,然后运转察看了局是不是准确。假如不合错误就前往代码反省毛病,大概是到场断点大概输入跟踪程序并找堕落误,然后再次运转检察输入是不是与料想分歧。假如输入只是把持台的一个复杂的数字大概字符那还好,可是假如输入必需在点击一系列按钮以后才干在屏幕上显现出来的工具呢?岂非我们就只能一次一次地守候编译部署,启动程序然后操纵UI,一向点到我们必要察看的中央么?这类举动无疑是对优美性命和壮丽芳华的伟大华侈。因而有一些已华侈了有数工夫的资深工程师们俄然发明,本来我们能够在代码中构建出一个相似的场景,然后在代码中挪用我们之前想反省的代码,并将运转的了局与我们的假想了局在程序中举行对照,假如分歧,则申明了我们的代码没有成绩,是依照预期事情的。好比我们想要完成一个加法函数add,输出两个数字,输入它们相加后的了局。那末我们无妨假想我们真的具有两个数,好比3和5,依据大家会的十之内的加法常识,我们晓得谜底是8.因而我们在相加后与展望的8举行对照,假如相称,则申明我们的函数完成最少关于这个例子是没有成绩的,因而我们对“这个办法能准确事情”这一命题的信念就增添了。这个例子的伪码以下:
  1. //ProductCodeadd(floatnum1,floatnum2){...}//Testcodeleta=3;letb=5;letc=a+b;if(c==8){//Yeah,itworks!}else{//Somethingwrong!}
复制代码
当测试充足周全和具有代表性的时分,我们即可以信念爆棚,拍着胸脯说,这段代码没成绩。我们做出某些前提和假定,并以其为前提利用到被测试代码中,并对照预期的了局和实践运转的了局是不是相称,这就是软件开辟中测试的基础体例。

<br>
而TDD是一种相对一般头脑的体例来讲,对照极度的一种做法。我们一样平常能想到的是先编写营业代码,也就是下面例子中的add办法,然后为其编写测试代码,用来考证产物办法是否是依照计划事情。而TDD的头脑恰好与之相反,在TDD的天下中,我们应当起首依据需求大概接口情形编写测试,然后再依据测试来编写营业代码,而这实际上是违背传统软件开辟中的先验认知的。可是我们能够举一个生存中相似的例子来讲明TDD的需要性:有履历的砌砖徒弟老是会先拉一条垂线,然后沿着线砌砖,由于有直线的包管,因而能够做到笔挺划一;而新进行的徒弟常常二话不说间接完工,然后在一阶段完成后再用直尺垂线之类的工具举行丈量和修补。TDD的优点不言自明,由于老是先测试,再编码,以是最少你的一切代码的public部分都应当含有需要的测试。别的,由于测试代码实践是要利用产物代码的,因而在编写产物代码前你将有一次深切思索和理论怎样利用这些代码的时机,这对进步计划和可扩大性有很好的匡助,试想一下你测试都很难写的接口,他人(大概本人)用起来很多纠结。在测试的绳尺下,你能够有目标无方向地编码;别的,由于有测试的回护,你能够宁神对原有代码举行重构,而不用忧虑损坏逻辑。这些实在都指向了一个终极的目标:让我们康乐放心高效地事情。
在TDD准绳的引导下,我们先编写测试代码。这时候由于还没有对应的产物代码,以是测试代码一定是没法经由过程的。在年夜多半测试体系中,我们利用白色来暗示毛病,因而一个测试的初始形态应当是白色的。接上去我们必要利用最小的价值(起码的代码)来让测试经由过程。经由过程的测试将被暗示为平安的绿色,因而我们回到了绿色的形态。接上去我们能够增加一些测试例,来考证我们的产物代码的完成是不是准确。假如不幸新的测试例让我们回到了白色形态,那我们就能够修正产物代码,使其回到绿色。云云重复直到各类界限和测试都举行终了,此时我们即可以失掉一个具有测试包管,鲁棒性超强的产物代码。在我们以后的开辟中,由于你有这些测试的包管,你能够勇敢重构这段代码大概与之相干的代码,最初只必要包管项目处于绿灯形态,你就能够包管代码没重构没有呈现成绩。
复杂说来,TDD的基础步骤就是“红→绿→勇敢重构”。
利用XCTest来实行TDD

Xcode5中已集成了XCTest的测试框架(之前版本是SenTestingKit和OCUnit),所谓测试框架,就是一组让“将测试集成到工程中”和“编写和理论测试”变得复杂的库。我们以后将经由过程完成一个栈数据布局的例子,来用XCTest开端理论一下TDD开辟。在人人对TDD有一些直不雅熟悉以后,再转到Kiwi的先容。假如您已在利用XCTest大概其他的测试框架了的话,能够间接跳过本节。
起首我们用Xcode新建一个工程吧,选择模板为空项目,在ProductName中输出工程名字VVStack,固然您可使用本人喜好的名字。假如您利用过Xcode之前的版本的话,应当有寄望到之前在这个界面是能够选择是不是利用UnitTest的,可是如今这个选框已被作废。

<br>
新建工程后,能够发明在工程中默许已有一个叫做VVStackTests的target了,这就是我们测试时利用的target。测试部分的代码默许放到了{ProjectName}Tests的group中,如今这个group下有一个测试文件VVStackTests.m。我们的测试例不必要向其余类表露接口,因而不必要.h文件。别的一样平常XCTest的测试文件城市以Tests来做文件名开头。

<br>
运转测试的快速键是⌘U(大概可使用菜单的Product→Test),我们这时候候间接对这个空工程举行测试,Xcode在编译项目后会利用你选择的设备大概摹拟器运转测试代码。不出不测的话,此次测试将会失利,如图:

<br>
VVStackTests.m是Xcode在新建工程时主动为我们增加的测试文件。由于这个文件其实不长,以是我们能够将其内容全体抄写以下:
  1. #import<XCTest/XCTest.h>@interfaceVVStackTests:XCTestCase@end@implementationVVStackTests-(void)setUp{[supersetUp];//Putsetupcodehere.Thismethodiscalledbeforetheinvocationofeachtestmethodintheclass.}-(void)tearDown{//Putteardowncodehere.Thismethodiscalledaftertheinvocationofeachtestmethodintheclass.[supertearDown];}-(void)testExample{XCTFail(@"Noimplementationfor"%s"",__PRETTY_FUNCTION__);}@end
复制代码
能够看到,VVStackTests是XCTestCase的子类,而XCTestCase恰是XCTest测试框架中的测试用例类。XCTest在举行测试时将会寻觅测试target中的一切XCTestCase子类,并运转个中以test开首的一切实例办法。在这里,默许完成的-testExample将被实行,而在这个办法里,Xcode默许写了一个XCTFail的断言,来强迫这个测试失利,用以提示我们测试还没有完成。所谓断言,就是判别输出的前提是不是满意。假如不满意,则抛堕落误并输入事后划定的字符串作为提醒。在这个Fail的断言必定会失利,并提醒没有完成该测试。别的,默许另有两个办法-setUp和-tearDown,正如它们的正文里所述,这两个办法会分离在每一个测试入手下手和停止的时分被挪用。我们如今正要入手下手编写我们的测试,以是先将本来的-testExample删撤除。如今再利用⌘U来举行测试,应当能够顺遂经由过程了(由于我们已没有任何测试了)。
接上去让我们想一想要做甚么吧。我们要完成一个复杂的栈数据布局,那末固然会有一个类来代表这类数据布局,在这个工程中我盘算就叫它VVStack。依照惯例,我们能够新建一个CocoaTouch类,承继NSObject而且入手下手完成了。可是别忘了,我们如今在TDD,我们必要先写测试!那末起首测试的方针是甚么呢?没错,是测试这个VVStack类是不是存在,和是不是可以初始化。有了这个方针,我们就能够下手入手下手编写测试了。在文件开首加上#import"VVStack.h",然后在VVStackTests.m的@end后面加上以下代码:
  1. -(void)testStackExist{XCTAssertNotNil([VVStackclass],@"VVStackclassshouldexist.");}-(void)testStackObjectCanBeCreated{VVStack*stack=[VVStacknew];XCTAssertNotNil(stack,@"VVStackobjectcanbecreated.");}
复制代码
嘛,固然是不成能经由过程测试的,并且乃至连编译都没法完成,由于我们如今基本没有一个叫做VVStack的类。最复杂的让测试经由过程的办法就是在产物代码中增加VVStack类。新建一个CocoaTouch的Objective-Cclass,取名VVStack,作为NSObject的子类。注重在增加的时分,应当只将其到场产物的target中:

<br>
因为VVStack是NSObject的子类,以是下面的两个断言应当都能经由过程。这时候候再运转测试,乐成变绿。接上去我们入手下手思索这个类的功效:栈的话一定必要可以push,而且push后的栈顶元素应当就是方才所push出来的元素。那末创建一个push办法的测试吧,在方才增加的代码之下持续写:
  1. -(void)testPushANumberAndGetIt{VVStack*stack=[VVStacknew];[stackpush:2.3];doubletopNumber=[stacktop];XCTAssertEqual(topNumber,2.3,@"VVStackshouldcanbepushedandhasthattopvalue.");}
复制代码
由于我们还没有完成-push:和-top办法,以是测试毫无疑问地失利了(在ARC情况中间接没法编译)。为了使测试当即经由过程我们起首必要在VVStack.h中声明这两个办法,然后在.m的完成文件中举行完成。令测试经由过程的最复杂的完成是一个空的push办法和间接前往2.3这个数:
  1. //VVStack.h@interfaceVVStack:NSObject-(void)push:(double)num;-(double)top;@end//VVStack.m@implementationVVStack-(void)push:(double)num{}-(double)top{return2.3;}@end
复制代码
再次运转测试,我们顺遂回到了绿灯形态。大概你很快就会说,这算哪门籽实现啊,假如再增添一组测试例,好比push一个4.6,然后反省top,不就失利了么?我们岂非不该该间接完成一个真实的公道的完成么?对此的回覆是,在实践开辟中,我们一定不会以如许的措施来处置像例子中如许相似的复杂成绩,而是会间接跳过一些error-try的步骤,完成一个对照完全的计划。可是在更多的时分,我们所体贴和必要完成的方针并非如许简单。出格是在对TDD还不熟习的时分,我们有需要加快节拍和举措,将全部开辟理念举行充实理论,如许才有大概在以后更庞大的案例中准确利用。因而我们发扬不怕冗杂,不断改进的精力,在方才的测试例上增添一个测试,回到VVStackTests.m中,在方才的测试办法中加上:
  1. -(void)testPushANumberAndGetIt{//...[stackpush:4.6];topNumber=[stacktop];XCTAssertEqual(topNumber,4.6,@"TopvalueofVVStackshouldbethelastnumpushedintoit");}
复制代码
很好,这下子我们回到了红灯形态,这恰是我们所希冀的,如今是时分来思索完成这个栈了。这个完成过于复杂,也有十分多的思绪,个中一种是利用一个NSMutableArray来存储数据,然后在top办法里前往最初到场的数据。修正VVStack.m,到场数组,变动完成:
  1. //VVStack.m@interfaceVVStack()@property(nonatomic,strong)NSMutableArray*numbers;@end@implementationVVStack-(id)init{if(self=[superinit]){_numbers=[NSMutableArraynew];}returnself;}-(void)push:(double)num{[self.numbersaddObject:@(num)];}-(double)top{return[[self.numberslastObject]doubleValue];}@end
复制代码
测试经由过程,注重到在-testStackObjectCanBeCreated和testPushANumberAndGetIt两个测试中都天生了一个VVStack对象。在这个测试文件中基础每一个测试城市必要初始化对象,因而我们能够思索在测试文件中增加一个VVStack的实例成员,并将测试中的初始化代码移到-setUp中,并在-tearDown中开释。
接上去我们能够仿照持续完成pop等栈的办法。鉴于篇幅这里不再持续具体完成,人人能够本人下手碰运气。记着先完成测试,然后再完成产物代码。一入手下手您大概会以为这很无聊,效力低下,可是请记着这是起步实习不成短少的一部分,并且在我们的例子中实在统统都是以“慢举措”在举行的。信任在经由理论和利用后,您将会渐渐把握本人的节拍和重点测试。关于利用XCTest到这里为止的代码,能够在github上找到。
Kiwi和BDD的测试头脑

XCTest是基于OCUnit的传统测试框架,在誊写性和可读性上都不太好。在测试用例太多的时分,因为各个测试办法是分裂的,想在某个很长的测试文件中找到特定的某个测试并弄分明这个测试是在做甚么并非很简单的事变。一切的测试都是由断言完成的,而良多时分断言的意义并非出格的明白,关于项目托付大概新的开辟职员到场时,常常要花上很年夜本钱来举行了解大概转换。别的,每个测试的形貌都被写在断言以后,同化在代码当中,难以寻觅。利用XCTest测试别的一个成绩是难以举行mock大概stub,而这在测试中长短常主要的一部分(关于mock测试的成绩,我会鄙人一篇中持续深切)。
举动驱动开辟(BDD)恰是为懂得决上述成绩而生的,作为第二代急迅办法,BDD倡始的是经由过程将测试语句转换为相似天然言语的形貌,开辟职员可使用更切合公共言语的习气来誊写测试,如许不管在项目交代/托付,大概以后本人修正时,都能够顺遂良多。假如说作为开辟者的我们一样平常事情是写代码,那末BDD实在就是在讲故事。一个典范的BDD的测试用例包活完全的三段式高低文,测试年夜多能够翻译为Given..When..Then的格局,读起来轻松满意。BDD在其他言语中也已有一些框架,包含最早的Java的JBehave和大名鼎鼎的Ruby的RSpec和Cucumber。而在objc社区中BDD框架也正在欣欣茂发地开展,得益于objc的语法原本就十分靠近天然言语,再加上C言语宏的能力,我们是有大概写出大度幽美的测试的。在objc中,如今对照盛行的BDD框架有cedar,specta和Kiwi。个中团体对照喜好Kiwi,利用Kiwi写出的测试看起来也许会是这个模样的:
  1. describe(@"Team",^{context(@"whennewlycreated",^{it(@"shouldhaveaname",^{idteam=[Teamteam];[[team.nameshould]equal:@"BlackHawks"];});it(@"shouldhave11players",^{idteam=[Teamteam];[[[teamshould]have:11]players];});});});
复制代码
我们很简单依据高低文将其提取为Given..When..Then的三段式天然言语
Givenateam,whennewlycreated,itshouldhaveaname,andshouldhave11players
很复杂啊有木有!在如许的语法下,是否是写测试的乐趣都被引发出来了呢。关于Kiwi的进一步语法和利用,我们稍后具体睁开。起首来看看怎样在项目中增加Kiwi框架吧。
在项目中增加Kiwi

最复杂和最保举的办法固然是CocoaPods,假如您对CocoaPods还对照生疏的话,保举您花工夫先看一看这篇CocoaPods的简介。Xcode5和XCTest情况下,我们必要在Podfile中增加相似上面的条目(记得将VVStackTests换成您本人的项目标测试target的名字):
  1. target:VVStackTests,:exclusive=>truedopodKiwi/XCTestend
复制代码
以后podinstall今后,翻开天生的xcworkspace文件,Kiwi就已处于可用形态了。别的,为了我们在新建测试的时分能省点事儿,能够在官方repo里下载并运转安装Kiwi的XcodeTemplate。假如您保持不必CocoaPods,而想要本人举行设置Kiwi的话,能够参考这篇wiki。
举动形貌(Specs)和希冀(Expectations),Kiwi测试的基础布局

我们先来新建一个Kiwi测试吧。假如安装了Kiwi的Template的话,在新建文件当选择Kiwi/KiwiSpec来创建一个Specs,取名为SimpleString,注重选择方针target为我们的测试target,模板将会在新建的文件名字前面加上Spec后缀。传统测试的文件名一样平常以Tests为后缀,暗示这个文件中含有一组测试,而在Kiwi中,一个测试文件所包括的是一组关于举动的形貌(Spec),因而习气上利用必要测试的方针类来作为名字,并以Spec作为文件名后缀。在Xcode5中创建测试时已不会同时创立.h文件了,可是如今的模板中包括有对同名.h的援用,能够在创立后将其删往。假如您没有安装Kiwi的Template的话,能够间接创立一个一般的Objective-Ctestcaseclass,然后将内容交换为上面如许:
  1. #import<Kiwi/Kiwi.h>SPEC_BEGIN(SimpleStringSpec)describe(@"SimpleString",^{});SPEC_END
复制代码
你大概会以为这不是objc代码,乃至嫌疑这些语法是不是可以编译经由过程。实在SPEC_BEGIN和SPEC_END都是宏,它们界说了一个KWSpec的子类,并将个中的内容包装在一个函数中(有乐趣的伴侣无妨点出来看看)。我们如今先增加一些形貌和测试语句,并运转看看吧,将下面的代码的SPEC_BEGIN和SPEC_END之间的内容交换为:
  1. #import<XCTest/XCTest.h>@interfaceVVStackTests:XCTestCase@end@implementationVVStackTests-(void)setUp{[supersetUp];//Putsetupcodehere.Thismethodiscalledbeforetheinvocationofeachtestmethodintheclass.}-(void)tearDown{//Putteardowncodehere.Thismethodiscalledaftertheinvocationofeachtestmethodintheclass.[supertearDown];}-(void)testExample{XCTFail(@"Noimplementationfor"%s"",__PRETTY_FUNCTION__);}@end0
复制代码
<p>describe形貌必要测试的对象内容,也即我们三段式中的Given,context形貌测试高低文,也就是这个测试在When来举行,最初it中的是测试的本体,形貌了这个测试应当满意的前提,三者配合组成了Kiwi测试中的举动形貌。它们是能够nest的,也就是一个Spec文件中能够包括多个describe(固然我们很少这么做,一个测试文件应当专注于测试一个类);一个describe能够包括多个
再见西城 该用户已被删除
沙发
发表于 2015-1-21 09:39:29 | 只看该作者
边吃零食边看Stanford的视频教程
乐观 该用户已被删除
板凳
发表于 2015-1-22 06:58:40 | 只看该作者
看完这个你就可以有多种选择来踏入做应用的阶段
老尸 该用户已被删除
地板
发表于 2015-1-30 23:31:07 | 只看该作者
其次学习方法和学习心态很重要,在学习当中应该保持一颗良好的心态。应该借鉴别人好的学习方法,大家互相帮助,取长补短。
愤怒的大鸟 该用户已被删除
5#
发表于 2015-2-6 16:54:15 | 只看该作者
这个办法就是在WindowsXP或Win7的电脑上,使用vmware虚拟机来搭建一个真实的Mac OS X环境。
第二个灵魂 该用户已被删除
6#
发表于 2015-2-9 09:24:07 | 只看该作者
down下code4app网站的每个分类的代码挨着看
飘灵儿 该用户已被删除
7#
发表于 2015-2-27 05:10:19 | 只看该作者
自从苹果公司开放iOS SDK以来,大量的国内外的软件开发者将关注的目光聚集在苹果的iOS平台上。由于iPhone和iPad自一出现就给人带来了颠覆性的感觉
再现理想 该用户已被删除
8#
发表于 2015-3-1 19:22:51 | 只看该作者
中国如今已然发展成为一个软件大国,软件人才的数量跃居全球之首。当然,在苹果平台的开发领域,也保持了相当强劲的发展势头。然而,很多初入iOS开发门槛的开发者,
分手快乐 该用户已被删除
9#
发表于 2015-3-10 22:28:47 | 只看该作者
AD: iPhone文件系统NSFileManager讲解是本文要介绍的内容,主要是通过iphone文件系统来学习NSFileManager的使用方法,具体内容来看本文详解。
简单生活 该用户已被删除
10#
发表于 2015-3-11 06:22:08 | 只看该作者
每个行业都一样,想要一天学有所成是不可能的,一定要做好努力的准备,做ios不是简单的学会oc语言。不怕多走弯路,就怕不肯动手。
兰色精灵 该用户已被删除
11#
发表于 2015-3-17 22:10:20 | 只看该作者
这个办法就是在WindowsXP或Win7的电脑上,使用vmware虚拟机来搭建一个真实的Mac OS X环境。
只想知道 该用户已被删除
12#
发表于 2015-3-25 03:33:30 | 只看该作者
中国如今已然发展成为一个软件大国,软件人才的数量跃居全球之首。当然,在苹果平台的开发领域,也保持了相当强劲的发展势头。然而,很多初入iOS开发门槛的开发者,
小妖女 该用户已被删除
13#
发表于 2015-4-6 17:14:46 | 只看该作者
从C语言入门,因为IOS开发用的是OC语言,是在C基础上的,不过也跟C不是很搭界,你可以直接学习OC语言也可以,
admin 该用户已被删除
14#
发表于 2015-4-15 05:12:05 | 只看该作者
众多研发人员积极参与到iOS平台的开发中来也就不足为奇了。
蒙在股里 该用户已被删除
15#
发表于 2015-4-17 01:55:09 | 只看该作者
每个行业都一样,想要一天学有所成是不可能的,一定要做好努力的准备,做ios不是简单的学会oc语言。不怕多走弯路,就怕不肯动手。
柔情似水 该用户已被删除
16#
发表于 2015-4-27 07:59:56 | 只看该作者
有办法利用自己手头的电脑立刻开始这个美妙旅程的。
海妖 该用户已被删除
17#
发表于 2015-5-5 05:56:43 | 只看该作者
因为我们老师也是自学的,给我们讲课说的最多的就是百度,谷歌,查文档。
若天明 该用户已被删除
18#
发表于 2015-5-6 20:27:27 | 只看该作者
自从苹果公司开放iOS SDK以来,大量的国内外的软件开发者将关注的目光聚集在苹果的iOS平台上。由于iPhone和iPad自一出现就给人带来了颠覆性的感觉
若相依 该用户已被删除
19#
发表于 2015-5-10 20:01:18 | 只看该作者
还有开发工具是用Xcode,是在Mac系统的,你多摸索一下就可以开发简单的应用了,建议你买一本iphone开发秘籍第二版看看,希望可以帮到你,谢谢。
因胸联盟 该用户已被删除
20#
发表于 2015-5-11 15:39:41 | 只看该作者
同很多iOS开发者一样,我也是通过培训进入到iOS开发这个行业,开始没有打算培训,只准备自己学习一些计算机编程相关的知识,毕业时找一份编程相关工作(本人是信息与计算科学这个专业,是数学系)。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-22 23:54

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表