要开发苹果ios必须先学ios c语言编译器,Objective-C吗?这两个先学哪个?我零基础

我是没有编程基础而又想学iOS 软件开发,所以我想问问先学C 语言再学objective C ,需要_百度知道
我是没有编程基础而又想学iOS 软件开发,所以我想问问先学C 语言再学objective C ,需要
我是没有编程基础而又想学iOS 软件开发,所以我想问问先学C 语言再学objective C ,需要多长时间?注:我还是个学生,周一到周五要上学,晚上还要晚自习,周末还要一天抽4小时学习,大约一个星期只有两三小时学习编程,那么要多长时间呢
有什么好的适合自己的方法呢
提问者采纳
如果你时间紧成这个样子强烈的建议你放弃从C开始,直接学习OC,仅仅是简单的学习C(不包括高级编程)至少需要30个小时(这时假设你学得蛮有感觉没走弯路的情况下简单了解最少的时间)。OC的话加入了面向对象的编程,以及开发ios程序的包括UI设计,程序关联,等各方面的内容,再加上现在中文的OC很好的的入门资料几乎没有(如果你英语很好有另当别论),以及没有mac的话搭建开发环境也是一件麻烦的事情,这样下来等你学得勉强能做一个很简单的程序已经不知道到什么时候去了。所以说还不如找到好的资料直接从OC学起。
其他类似问题
为您推荐:
其他4条回答
不是有很多当型和直到型结构语句吗?你一个一个都弄懂,以把他们看成一个整体的思想来思考就会很简单了,不要想一次性就能学好,都是慢慢来的,每天早上抽时间看一个编程,你觉得应该是怎么编,能不能编出来 , 不一定要照着它的弄,只要运行没问题说明你的思路就没问题,书上的只是告诉你一些技巧,这个是很活的
自己买一本书看看 然后在找你们计算机老师聊聊,实践是最重要的
学 C 吧、Objective C 主要应用是苹果的系统。C是编程语言之根本、至于多少时间、就要看你领会程度了、当然最好能经常练习。
还是建议你选择培训机构学习,可以选择上周末的课,一方面自学需要购买一系列的苹果硬件设备;另一方面没有真实的项目经验。其实建议你可以直接学习O-C,苏州园区这边有家风云学校,是个国有机构,他们的ios培训还不错,至少比私营机构在信誉方面好很多,不过他们貌似走的都是口碑路线~网上的信息可能会比较少
ios的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁视频正在处理中,暂不能播放,请您稍候访问...
分享给站外好友
页面地址:
FLASH地址:
HTML代码:
通用代码:
可以让视频在手机、平板电脑上播放!
举报此视频包含不当内容:
请填写你要举报的内容,标明举报内容所在地时段,将有助于我们更及时的处理举报内容。感谢您对PPS的支持!
广告和欺诈
触犯我的版权
你可以把视频下载到不同的设备
使用电脑飞速下载轻易收藏喜欢的视频
使用苹果设备支持iPhone、iPad高清视频亦可离线观看
使用Android设备支持手机、平板高清视频亦可离线观看
拍下二维码,视频随身看
用PPS影音IOS/Android版扫描二维码,在您的移动设备上继续观看视频,也可以分享给您的好友。
iOS开发零基础Objective-C语言04-01字符串原始 Part2
手机没装PPS影音?
注:数据来自爱奇艺、PPS全平台
上传时间:11天前
分&&&&&&类:
暂无相关内容
视频简介:扣丁学堂视频还在持续更新,如果想看完整的视频,就来扣丁学堂网站注册观看,网站的资源全部免费开放的,注册就能观看。
现在可以用QQ账号直接发表评论,分享给我的好友
大家都在看
互联网药品信息服务许可证:
互联网医疗保健信息服务许可证:
Copyright&2005 - 2014 PPStream, Inc. All Rights ReservedObjective-C 和 Swift 语言,哪个更容易学习?
的观点是 Objective-C 比 Swift 更容易学习:& Objective-C requires programmers to be explicit. The Swift language lets the compiler do more work for the programmer. This is great—less typing for the programmer, right?—but it means that when you look at a line of code, it won't mean much without a deep understanding of the context in which that line lives. Explicit languages are easier for beginners to understand.Source: 而另外一边,Ash Furrow 认为 Swift 更容易,Objective-C 太难:& I read
by Aaron Hillegrass this morning and was immediately disappointed. There are many things that I disagree with about this article, but there is one in particular that I took offence to. “Objective-C is easier to learn than Swift.” Really? Come on now. That's just silly.Source:
按投票排序
谢邀。看了几天的 Swift, 对比 Objective-C 个人觉得还是要分情况:从语言上讲,Swift 比 Objective-C 更简单,但是简单是对于有编程基础的人来讲,它的 syntax 更清楚,简洁,很多程序员看到了真是爱不释手。从开发角度上讲,Swift 比 Objective-C 难的多,首先虽然 Swift 出来没几天,出来一堆一堆的教程,但是仔细翻翻讲真正 iOS 或者 OS X 开发的真心没有多少。所以虽然你明白了语言怎么回事,但是真正上手开发,可能就不是想象中的那样了。不过这又得分:对于已经熟悉 Cocoa, Cocoa touch 开发的开发人员来讲,Swift 还是很容易上手的,Apple 的开发团队在这方面真是下了不少功夫,帮助开发者尽可能的方便的使用 Swift。如果你已经非常熟悉Cocoa, Cocoa touch 的开发环境,各种 Framework,API,你会觉得 Swift 用于开发真的很方便,也容易上手。对于完全不懂 Objective-C 并且没有任何 Cocoa, Cocoa touch 开发经验的人来讲,直接上手学习 Swift 依然会非常困难。语言懂了不顶用,你还要去熟悉各种 API, 熟悉整个Cocoa, Cocoa touch 的开发环境,卡住不懂了,搜一下,全是 Objective-C 的例子,真的会很难受。结论,如果你已经是使用 Objective-C 的程序员的话,Swift 真的很简单,你可以用很少的时间掌握它,并且直接使用它开发。如果你是初学者的话,Swift 和 Objective-C 对于你来说都会很难,可能 Swift 本身简洁的语言特色会让你觉得容易理解,如果你是为了学习立马进行开发的话,Objective-C 相比下会简单很多。你会找到更多的学习资源和参考,寻求帮助的时候也能得到更有经验和专业的回答。
Objective C 显然更容易学习,现在的XCode默认打开ARC,几乎不需要手工管理指针资源,除了偶尔要处理一下 weak strong dance ,基本上就是一个“平凡的高级语言”。swift等于是在arc的objc基础上加了类型推导、泛型和运算符重载。这都不是那么容易的东西……貌似swift还没有异常捕捉?到时候还得死一批人。觉得这个简单的都是被playground给骗了吧。===swift是类似Haskell那种支持类型推导的强类型静态编译语言。它不但有类型而且看起来挺严格。看看有多少朋友误认为它没有类型或者是动态类型,可以想象一下swift要坑多少人。
OC要是好学好用,苹果有必要出SWIFT吗?
作为语言都不是很难上手。框架的熟悉都是要靠练习靠经验,所以请不要觉得学了这个语言本身开发就会很溜。假设没有什么apple script的经验,新学objective c基本没简单到一看就会。若有c或c++背景,objective c也不会巨难无比。大多科班程序员都写过些python啊ruby啊什么的,swift跟一般的scripting language看起来没什么差别,伪代码式样。同时,用法抽象了很多objective c的样式。简单来说就是能写,但是写出来什么呢?又还没有consumer ios8给开发。写出来也不支持。Swift是一个strongly typed语言,甚至连(id)之类的灵活玩意都没有,这个我到现在还不是很习惯。一个dictionary同时有int跟float,我想iterate一下,编译器就疯了。我感觉用swift会有很多难看的downcasting,不过也算是C family的精髓啦(自黑)!swift的optional value好奇葩,是不是进一步除nil的努力呢?还有,真的没有指针的世界也可以运行的吗?(你看,这是作为C family programmer的偏见)还有作为新语言,开发环境目前还不佳啊,所以从这点来看学起来不会比ruby容易的。人家库啊讨论啊社区啊都很成熟了,我要是问一个关于swift的问题是肯定没有人答的。
从语言角度,Swift比OC简单了很多。这就像100元比50元多一样明显。Swift就是为了简化OC的开发才发明出来的,汇集了几乎所有流行语言的优势,用更高效更少更清晰更简洁的代码来完成以前同样的工作。而从语言环境,就是说相关资料教程和网络讨论来看,OC经过多年积淀自然是资料更多。就目前而言,用Swift完成同样的项目可供查阅的资料和参考的代码还是少很多。但是Swift正式发行可以上架App才几天的时间(写下本文时)。从后续发展来看,必然是Swift的天下:1、首先,完成同样的功能Swift代码比OC更简洁高效,开发效率更高。2、其次,Swift运行速度不低于OC,调用的相同的底层。而Apple公布的资料Swift还要更快,估计是编译器也做了更强的优化。3、第三,苹果的官方支持。很明显,苹果的战略是要将Swift来替换OC,在1、2成立的前提下,苹果不主推OC那就是傻瓜吧。从官方文档来看,苹果已经在努力,一段时间内在官方资料方面估计将达成OC、Swift并行的情况,类似.net中VB和C#的文档都是一式两份一样。而更远的未来,Swift将逐渐替换OC。再更远的未来,苹果发布新语言AnyWay。再更远的未来,苹果居然被小米收购了。好吧,后两条纯属虚构。对于初学者来说,必然选择Swift,更容易学习。想象一下那些在.net刚推出的时候选择了VB6的人,在Java刚推出的时候选择了Delphi的人。还有,OC让我想到了大学里的Fortran(我不太喜欢,有点老旧怪异)。而已经掌握OC的开发者,可自行选择是否学习Swift,因为OC至少还会流行5年以上,并在10年内依然被平台支持。然后,新版的iOS99已经不兼容OC了。。。
还是objective-c好学一点吧- objective-c是更接近机器的语言objective-c和swift都是要编译成机器码的语言,都不是脚本语言,也不是虚拟机语言。相比swift各种高级的语法特性(类型推断、泛型、函数式语言特性、闭包等等),objective-c作为一个对C语言的面向对象扩展,功能比较有限,而且完全兼容C,有一点C基础、计算机原理基础的(大部分学计算机的应该都有这个基础)同学,应该很容易理解objective-c的各种语法特性。- objective-c是非常传统的面向过程和对象的语言既然是C的扩展,就基本上具有所有面向过程语言的特性,会很自然地用各种控制结构去实现基本的代码逻辑,而且用控制结构是用objective-c时正常的使用模式。objective-c没有泛型支持,单根继承;这就意味着面向对象的特性也是比较简单的;不需要学习者有太多的高级语言特性的知识,基本的面向对象的概念,控制结构的概念就足够应付学习这门语言。swift就不太一样了,如果不懂泛型,最基本的?和!的本质就不能理解。其实Optional类型就是一个类似C#的Nullable&T&的泛型类型。更进一步的,Optional实际上是枚举类型,如果没有接触过类似Haskell这样的函数式语言中的相似的类型,估计理解这样的枚举也要费一番功夫。- swift的语法特性很复杂apple自己官方的文档里,language guide也没有完全覆盖所有的特性,至少有一些讲的非常粗浅,读者很难通过它理解的很深入,也缺乏示例代码片段帮助理解。language reference覆盖的内容更多一些,但是就更加粗浅了。- swift的很多语法特性在xcode里面还没有实现举一个例子,截止今天(9.23),class var(相当于类的静态成员变量)还不支持,只能用其他方式模拟,写singleton就要很奇怪的嵌套一个struct类型,把静态成员放在struct里面,然后用一个class func去访问struct里面的静态成员。而且xcode的编辑器对swift的支持也不是很完善,补全和代码提示功能(SourceKitService)常常崩溃。- Cocoa库基本上是为Objective-C写的swift去调用objective-c的cocoa库,看起来怎么都不算非常优雅
为什么老有人纠结于 Swift 没有异常捕获,跟在 OC 里你用过异常似的。说正题,新手为了找工作的话还是学 OC 好,Swift 没两年在国内大规模不起来。
首先你问问题的方式就是不正确的,难与不难,对每个人而言都是不一样的。有些人觉得OC简单,也有人觉得swift更简单,大家所学的知识不一样,理解水平不一样,得到的答案当然也不一样。对别人而言简单的东西,对你而言,可能并不容易。你更应该告诉我你要达到的目的,你现在的水平,这样我可以凭借我的经验给你一些更合理的建议,而不是告诉你难与不难,难道难的话你就要打算放弃吗?不过根据你所问的问题,你应该是有点编程经验,想学iOS开发,却不知如何下手目前swift刚出来,还有很多不完善的地方,不管是编译器,还是语法本身,都还有很多要改善的地方,所以对于大部分公司而言,应该不会轻易的换swift,里边有太多的未知,一不小心遇到一个蛋疼的bug,网上又找不到解决方案,你的工期就要被无限期延长了,如果你没觉得你牛逼到碉堡的话还是安心学习OC吧,swift业余关注一下就好,不用太过于着急。编程的基本思想都是一样的,学好任何一门语言对你学习其它语言都是很有帮助的。等你熟练掌握一门语言再去看另一门语言的时候,你自己就会找到答案,而从一门过去的语言往更高级的语言过度,你也会明白更多。静下心来,学就好了割线---------------------------------Swift 确切的说是让编程更自由了,但是简单那就是在开玩笑,里边有太多的规则需要你去理解记忆,它让学习这门语言的过程变得更加陡峭了
没有IOS/MAC OS开发基础的话,都不容易学,有IOS/MAC OS开发基础的话。。。OC你不是已经会了么。。。
谢邀!Swift发布之后,在iOS开发者圈掀起了一波热潮,这个大家都看到了,也被这问题体现了。swift和OC,哪个更容易学习?以我现在看官方的swift书不到三分之一,还没做过一个swift项目的情况来解答这个问题,明显做不到公平公正。简单说下个人的感觉:都不难。swift和oc的语言特性对比我就不说了,网上有很多学得快的人已经总结了。当然,
也说了swift的具体的一些缺点,我就说不出来。但要明白,swift作为一个刚发布的语言,还有长久的发展,OC也是发展了那么久才让人觉得好用些。其实从语言特性上,我们基本上可以认为swift是比OC更为高级的语言,具体表现就是:更方便易用的语法(如string,collection,control flow等)和更多的高级特性(closure,tuple等)。现在有这种那种问题只不过还需要时间发展而已。所以题主现在还是重点关注OC,在实践中用用swift。我觉得两者都不难,是因为个人认为比语言更重要的是通用的技能:内存,多线程,网络,系统,设计模式,编译,调试...每个语言有每个语言的特性,题主可以把学过的语言拿出来看看,C/C++/java/OC,这些语言,假如你经常用,那他的语法和特性你会经常纠结么?在开发过程中,我们往往纠结于:内存缓存和释放是否合理;怎么样合理构建线程池,解决锁和数据线程安全性;如何使用好的设计模式;编译调试方法是否足够高效(假如有人还在使用print或nslog来debug,请反省下)。可能回答的并非题主想要的,不知道题主是害怕学习了OC之后被Swift替换了很可惜,还是学OC学到一半,想重新选择swift。我只是想说,语言这东西,假如你用起来了,学习就不是什么难的事。你觉得学一个语言难,不过是因为你真的只是在学习,而没有用起来。
身为已经使用Objective-C的码农,我依旧觉得swift的语法很别扭!文档竟然有3000页...我认为初学者还是先学习Objective-C 比较靠谱!!!!swift可能未来是主流.但是不会Objective-C直接先学swift我觉得是非常不靠谱的!!!而且Xcode 6的beta 版本 跟屎一样难用!!!经常莫名crash!!!swift 应该很牛.但目前我只想黑他~~~------------------------------------swift肯定比Objective-C强大但是,目前swift学习资料也不多,都在摸索阶段!目前阶段的结论是Objective-C比swift更容易学习!!
谢邀。swift相对来说现在类库太少,虽然可以调用oc的类库,但代码里存在两种语言对于后期维护和代码规范都是头疼的问题。更何况swift现在编译还有各种问题,2年内,oc还是开发iOS的首选。至于哪种更好学,我认为swift对于懂js或python的人比较容易,学习曲线可能是一开始很平滑,到后面就很陡了。也就是入门容易,master it would be quit hard.
既然被邀请,就发表下个人看法.swift绝对不是一个简单的语言,任何语言无论属于何种类何风格,只能说你容易上手,容易理解,但绝不容易写出程序,这里的程序是指健壮的能符合实际开发的代码,所以我目前还在把oc深入学习阶段,swift推迟三个月再看,也来得及,至少有信心swift短时间内不会把oc怎么样~~~
不管是初学者还是编程多年的人,swift学习曲线低,编程高效,结合了面向对象和函数编程的优点。而很多人觉得swift难的部分原因是没有跟上现在语言的发展,例如java8,scala,python,ruby等,都是推动语言发展的新秀。此外还有些老程序员不愿学习有关。
看技术背景,如果是javascript或者ruby程序员来说,应该是swift更容易学习,如果对于c程序员来说,objective-c会更容易上手一些。
谢谢邀请,这个问题估计很难有标准的答案,因为每个人的知识储备都不一样。如果是想在比较短的时间学会做iOS App的话,OC应该容易点。Objective-C已经有很多年了,学习的路径相对成熟些,会的人也多,资源会比较丰富,遇到问题应该比较容易得到解决,对学习有帮助。从Apple对Swift的介绍来看,它应该是未来的当家语言,肯定是要学的,但现阶段学起来应该比OC慢。
现在来看oc更容易,学习资料多,范例代码也有很多。swift应该是未来ios开发主流但是现在学习资料比较少
谢邀。个人感觉oc比swift容易上手,可能是因为之前有c和Java基础,很快就有了亲切感。如果有脚本语言的学习经验,可能会感觉swift更亲切些。如果是IOS新手纠结于从哪个语言开始,或者是先学哪个,建议选择前者。毕竟现在优秀的开源代码(当然同时也是优秀的学习资源)都是oc写的,对oc熟悉了之后再顺势去了解swift,相信到时候也不会再对”哪个容易学习"这个问题有疑惑了,而且这用不了多长时间。个人感觉做IOS开发,oc是绕不开的,早晚都要学,或者是了解,因为一不小心就会接触到。另外,从现有的资料来看,swift远没想象的那么”单纯”易学。可以先各学一周感受下,很快就有答案了。最后,别人的看法都是以他们的经验为基础的,参考价值不大。
谢邀。我是从c到oc的,所以感觉上手很容易,swift还没认真看。如果你现在开始学iOS编程的话,感觉还是从oc开始吧,毕竟成熟的多,开发的例子,类库都多。如果iOS/MAC开发都已经很熟了,转到swift也容易,毕竟都是APPLE的东西。
不喜欢 swift 的样子。 不过当初刚用 objective c 的时候, 感觉也差不多。 对程序员是个好事, 有东西不断的学, 才能保证工资水平。 都是简单的东西, 一会就没人要你干活了。OBJ C语言、iOS 系统结构
服务器君一共花费了8.058 ms进行了2次数据库查询,努力地为您提供了这个页面。
试试阅读模式?希望听取您的建议
Objective-C,是扩充C的面向对象编程语言。它主要使用于Mac OS Objective-C,通常写作ObjC和较少用的Objective C或Obj-C,是在C的基础上,加入面向对象特性扩充而成的编程语言。目前,
主要应用于Mac OS X和iOS这两个NeXTSTEP的衍生系统,而在NeXTSTEP和OpenStep中它更是基本语言。Objective-C可以在任何gcc支持的平台上进行编译,因为gcc原生支持Objective-C。
Objective-C的历史
1980年代初,布莱德·确斯(Brad Cox)在其公司Stepstone发明Objective-C,它以一种叫做SmallTalk-80的语言为基础。Objective-C建立在C语言之上,意味着它是在C语言基础上添加了扩展而创造出来的能够创建和操作对象的一门新的程序设计语言。对Objective-C最主要的描述是他1986年出版的《Object-oriented Programming, An Evolutionary Approach》。1988年,NeXT Software公司获得了Objective-C语言的授权,并开发出了Objective-C的语言库和一个名为NEXTSTEP的开发环境。1992年,自由软件基金会的GNU开发环境增加了对Objective-C的支持。1994年,NeXT Computer公司和升阳微系统(Sun Microsystem)联合发布了一个针对NEXTSTEP系统的标准典范,名为OPENSTEP。OPENSTEP在自由软件基金会的实现名称为GNUStep。日,苹果公司宣布收购NeXT Software公司,NEXTSTEP/OPENSTEP环境成为苹果操作系统下一个主要发行版本OS X的基础。这个开发环境的该版本被苹果公司称为Cocoa。
苹果公司最早于日的Macworld大会上公布这个系统,最初是设计给iPhone使用的,后来陆续套用到iPod touch、iPad以及Apple TV等苹果产品上。iOS与苹果的Mac OS X操作系统一样,它也是以Darwin为基础的,因此同样属于类Unix的商业操作系统。原本这个系统名为iPhone OS,直到日WWDC大会上宣布改名为
Objective-C的语法
Objective-C是C语言的严格母集合,意指任何原始的C语言程式都可以通过Objective-C编译器而不需修改,也允许 Objective-C 使用任何原始的C语言代码。Objective-C 形容自己为覆盖于C语言上的一层薄纱,这是因为Objective-C的原意就是在原始C语言主体上加入面向对象的特性。Objective-C的面向对象语法源于Smalltalk讯息传递风格。所有其他非面向对象的语法,包括变量型别,前处理器(preprocessing),流程控制,函数声明与调用皆与C语言完全一致。
Hello World
咱们看看Hello
World实例。
新版本的Xcode 4.3.1下的helloworld例子可以这么写:
#import &Foundation/Foundation.h>
int main(int argc, char *argv[]){
@autoreleasepool{
NSLog(@"Hello World!");
那 autoreleasepool这个是做什么用的呢?
简单的说,每次事件处理时候开始的时候,ios会为我们自动生成一个autorelesepool,结束的时候释放掉。对于每一个Runloop, 系统会隐式创建一个Autorelease pool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的Autorelease pool会被销毁,这样这个pool里的每个Object会被release。
那什么是一个Runloop呢? 一个UI事件,Timer call, delegate call, 都会是一个新的Runloop。Autorelease是保证一个method安全的,对于method中的函数调用也适用。
旧版本的hellowold如下:
#import &Foundation/Foundation.h>
int main(int argc, char *argv[]){
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Hello World!");
[pool drain];
IOS的系统结构
系统结构,从底层到最顶层分为四层:核心操作系统层,Core OS,核心服务层 Core Services,媒体层 Media、Cocoa Touch层。
iOS 系统结构(点击查看大图)
本文地址:,欢迎访问原出处。
不打个分吗?
转载随意,但请带上本文地址:
如果你认为这篇文章值得更多人阅读,欢迎使用下面的分享功能。
小提示:您可以按快捷键 Ctrl + D,或点此 。
大家都在看
现代魔法研究协会欢迎你
阅读一百本计算机著作吧,少年
亨特(Andrew Hunt) (作者), 托马斯(David Thomas) (作者), 马维达 (译者)
《程序员修炼之道:从小工到专家》内容简介:《程序员修炼之道》由一系列独立的部分组成,涵盖的主题从个人责任、职业发展,知道用于使代码保持灵活、并且易于改编和复用的各种架构技术,利用许多富有娱乐性的奇闻轶事、有思想性的例子及有趣的类比,全面阐释了软件开发的许多不同方面的最佳实践和重大陷阱。无论你是初学者,是有经验的程序员,还是软件项目经理,《程序员修炼之道:从小工到专家》都适合你阅读。
扫一扫,在手机上阅读
栏目最新博文
9,489 views
栏目博文推荐
9,489 views
正因为难,所以才超凡脱俗。
关于网站与作者
互联网信息太多太杂,各互联网公司不断推送娱乐花边新闻,SNS,微博不断转移我们的注意力。但是,我们的时间和精力却是有限的。这里是互联网浩瀚的海洋中的一座宁静与美丽的小岛,供开发者歇息与静心潜心修炼(愿景)。
“Veda”的本义是知识、启示,希望这里能为开发者提供充足的技术资料。
我的电子邮件gonnsai(,腾讯微博:,欢迎与我联系。Objective-C开发编码规范 - IOS - 伯乐在线
& Objective-C开发编码规范
& 873 阅读
Objective-C编码规范,内容来自苹果、谷歌的文档翻译,自己的编码经验和对其它资料的总结。
转载请注明出处。
Objective-C是一门面向对象的动态编程语言,主要用于编写iOS和Mac应用程序。关于Objective-C的编码规范,苹果和谷歌都已经有很好的总结:
本文主要整合了对上述文档的翻译、作者自己的编程经验和其他的相关资料,为公司总结出一份通用的编码规范。
使用空格而不是制表符Tab
不要在工程里使用Tab键,使用空格来进行缩进。在Xcode & Preferences & Text Editing将Tab和自动缩进都设置为4个空格。(Google的标准是使用两个空格来缩进,但这里还是推荐使用Xcode默认的设置。)
每一行的最大长度
同样的,在Xcode & Preferences & Text Editing & Page guide at column:中将最大行长设置为80,过长的一行代码将会导致可读性问题。
函数的书写
一个典型的Objective-C函数应该是这样的:
Objective-C
- (void)writeVideoFrameWithData:(NSData *)frameData timeStamp:(int)timeStamp {
- (void)writeVideoFrameWithData:(NSData *)frameData timeStamp:(int)timeStamp {&&&&...}
在-和(void)之间应该有一个空格,第一个大括号{的位置在函数所在行的末尾,同样应该有一个空格。(我司的C语言规范要求是第一个大括号单独占一行,但考虑到OC较长的函数名和苹果SDK代码的风格,还是将大括号放在行末。)
如果一个函数有特别多的参数或者名称很长,应该将其按照:来对齐分行显示:
Objective-C
-(id)initWithModel:(IPCModle)model
ConnectType:(IPCConnectType)connectType
Resolution:(IPCResolution)resolution
AuthName:(NSString *)authName
Password:(NSString *)password
MAC:(NSString *)mac
AzIp:(NSString *)az_ip
AzDns:(NSString *)az_dns
Token:(NSString *)token
Email:(NSString *)email
Delegate:(id&IPCConnectHandlerDelegate&)
1234567891011
-(id)initWithModel:(IPCModle)model&&&&&& ConnectType:(IPCConnectType)connectType&&&&&&&&Resolution:(IPCResolution)resolution&&&&&&&&&&AuthName:(NSString *)authName&&&&&&&&&&Password:(NSString *)password&&&&&&&&&&&&&& MAC:(NSString *)mac&&&&&&&&&&&&&&AzIp:(NSString *)az_ip&&&&&&&&&&&& AzDns:(NSString *)az_dns&&&&&&&&&&&& Token:(NSString *)token&&&&&&&&&&&& Email:(NSString *)email&&&&&&&&&&Delegate:(id<IPCConnectHandlerDelegate>)delegate;
在分行时,如果第一段名称过短,后续名称可以以Tab的长度(4个空格)为单位进行缩进:
Objective-C
- (void)short:(GTMFoo *)theFoo
longKeyword:(NSRect)theRect
evenLongerKeyword:(float)theInterval
error:(NSError **)theError {
- (void)short:(GTMFoo *)theFoo&&&&&&&&longKeyword:(NSRect)theRect&&evenLongerKeyword:(float)theInterval&&&&&&&&&&&&&&error:(NSError **)theError {&&&&...}
函数调用的格式和书写差不多,可以按照函数的长短来选择写在一行或者分成多行:
Objective-C
//写在一行
[myObject doFooWith:arg1 name:arg2 error:arg3];
//分行写,按照':'对齐
[myObject doFooWith:arg1
error:arg3];
//第一段名称过短的话后续可以进行缩进
[myObj short:arg1
longKeyword:arg2
evenLongerKeyword:arg3
error:arg4];
12345678910111213
//写在一行[myObject doFooWith:arg1 name:arg2 error:arg3];&//分行写,按照':'对齐[myObject doFooWith:arg1&&&&&&&&&&&&&& name:arg2&&&&&&&&&&&&&&error:arg3];&//第一段名称过短的话后续可以进行缩进[myObj short:arg1&&&&&&&&&&longKeyword:arg2&&&&evenLongerKeyword:arg3&&&&&&&&&&&&&&&&error:arg4];
以下写法是错误的:
Objective-C
//错误,要么写在一行,要么全部分行
[myObject doFooWith:arg1 name:arg2
error:arg3];
[myObject doFooWith:arg1
name:arg2 error:arg3];
//错误,按照':'来对齐,而不是关键字
[myObject doFooWith:arg1
error:arg3];
12345678910
//错误,要么写在一行,要么全部分行[myObject doFooWith:arg1 name:arg2&&&&&&&&&&&&&&error:arg3];[myObject doFooWith:arg1&&&&&&&&&&&&&& name:arg2 error:arg3];&//错误,按照':'来对齐,而不是关键字[myObject doFooWith:arg1&&&&&&&&&&name:arg2&&&&&&&&&&error:arg3];
@public和@private标记符
@public和@private标记符应该以一个空格来进行缩进:
Objective-C
@interface MyClass : NSObject {
@interface MyClass : NSObject { @public&&... @private&&...}@end
协议(Protocols)
在书写协议的时候注意用&&括起来的协议和类型名之间是没有空格的,比如IPCConnectHandler()&IPCPreconnectorDelegate&,这个规则适用所有书写协议的地方,包括函数声明、类声明、实例变量等等:
Objective-C
@interface MyProtocoledClass : NSObject&NSWindowDelegate& {
id&MyFancyDelegate& _
- (void)setDelegate:(id&MyFancyDelegate&)aD
@interface MyProtocoledClass : NSObject<NSWindowDelegate> { @private&&&&id<MyFancyDelegate> _delegate;}&- (void)setDelegate:(id<MyFancyDelegate>)aDelegate;@end
闭包(Blocks)
根据block的长度,有不同的书写规则:
较短的block可以写在一行内。
如果分行显示的话,block的右括号}应该和调用block那行代码的第一个非空字符对齐。
block内的代码采用4个空格的缩进。
如果block过于庞大,应该单独声明成一个变量来使用。
^和(之间,^和{之间都没有空格,参数列表的右括号)和{之间有一个空格。
Objective-C
//较短的block写在一行内
[operation setCompletionBlock:^{ [self onOperationDone]; }];
//分行书写的block,内部使用4空格缩进
[operation setCompletionBlock:^{
[self.delegate newDataAvailable];
//使用C语言API调用的block遵循同样的书写规则
dispatch_async(_fileIOQueue, ^{
NSString* path = [self sessionFilePath];
if (path) {
//较长的block关键字可以缩进后在新行书写,注意block的右括号'}'和调用block那行代码的第一个非空字符对齐
[[SessionService sharedService]
loadWindowWithCompletionBlock:^(SessionWindow *window) {
if (window) {
[self windowDidLoad:window];
[self errorLoadingWindow];
//较长的block参数列表同样可以缩进后在新行书写
[[SessionService sharedService]
loadWindowWithCompletionBlock:
^(SessionWindow *window) {
if (window) {
[self windowDidLoad:window];
[self errorLoadingWindow];
//庞大的block应该单独定义成变量使用
void (^largeBlock)(void) = ^{
[_operationQueue addOperationWithBlock:largeBlock];
//在一个调用中使用多个block,注意到他们不是像函数那样通过':'对齐的,而是同时进行了4个空格的缩进
[myObject doSomethingWith:arg1
firstBlock:^(Foo *a) {
secondBlock:^(Bar *b) {
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
//较短的block写在一行内[operation setCompletionBlock:^{ [self onOperationDone]; }];&//分行书写的block,内部使用4空格缩进[operation setCompletionBlock:^{&&&&[self.delegate newDataAvailable];}];&//使用C语言API调用的block遵循同样的书写规则dispatch_async(_fileIOQueue, ^{&&&&NSString* path = [self sessionFilePath];&&&&if (path) {&&&&&&// ...&&&&}});&//较长的block关键字可以缩进后在新行书写,注意block的右括号'}'和调用block那行代码的第一个非空字符对齐[[SessionService sharedService]&&&&loadWindowWithCompletionBlock:^(SessionWindow *window) {&&&&&&&&if (window) {&&&&&&&&&&[self windowDidLoad:window];&&&&&&&&} else {&&&&&&&&&&[self errorLoadingWindow];&&&&&&&&}&&&&}];&//较长的block参数列表同样可以缩进后在新行书写[[SessionService sharedService]&&&&loadWindowWithCompletionBlock:&&&&&&&&^(SessionWindow *window) {&&&&&&&&&&&&if (window) {&&&&&&&&&&&&&&[self windowDidLoad:window];&&&&&&&&&&&&} else {&&&&&&&&&&&&&&[self errorLoadingWindow];&&&&&&&&&&&&}&&&&&&&&}];&//庞大的block应该单独定义成变量使用void (^largeBlock)(void) = ^{&&&&// ...};[_operationQueue addOperationWithBlock:largeBlock];&//在一个调用中使用多个block,注意到他们不是像函数那样通过':'对齐的,而是同时进行了4个空格的缩进[myObject doSomethingWith:arg1&&&&firstBlock:^(Foo *a) {&&&&&&&&// ...&&&&}&&&&secondBlock:^(Bar *b) {&&&&&&&&// ...&&&&}];
数据结构的语法糖
应该使用可读性更好的语法糖来构造NSArray,NSDictionary等数据结构,避免使用冗长的alloc,init方法。
如果构造代码写在一行,需要在括号两端留有一个空格,使得被构造的元素于与构造语法区分开来:
Objective-C
//正确,在语法糖的&[]&或者&{}&两端留有空格
NSArray *array = @[ [foo description], @&Another String&, [bar description] ];
NSDictionary *dict = @{ NSForegroundColorAttributeName : [NSColor redColor] };
//不正确,不留有空格降低了可读性
NSArray* array = @[[foo description], [bar description]];
NSDictionary* dict = @{NSForegroundColorAttributeName: [NSColor redColor]};
//正确,在语法糖的&[]&或者&{}&两端留有空格NSArray *array = @[ [foo description], @"Another String", [bar description] ];NSDictionary *dict = @{ NSForegroundColorAttributeName : [NSColor redColor] };&//不正确,不留有空格降低了可读性NSArray* array = @[[foo description], [bar description]];NSDictionary* dict = @{NSForegroundColorAttributeName: [NSColor redColor]};
如果构造代码不写在一行内,构造元素需要使用两个空格来进行缩进,右括号]或者}写在新的一行,并且与调用语法糖那行代码的第一个非空字符对齐:
Objective-C
NSArray *array = @[
NSDictionary *dictionary = @{
NSFontAttributeName : [NSFont fontWithName:@&Helvetica-Bold& size:12],
NSForegroundColorAttributeName : fontColor
1234567891011
NSArray *array = @[&&@"This",&&@"is",&&@"an",&&@"array"];&NSDictionary *dictionary = @{&&NSFontAttributeName : [NSFont fontWithName:@"Helvetica-Bold" size:12],&&NSForegroundColorAttributeName : fontColor};
构造字典时,字典的Key和Value与中间的冒号:都要留有一个空格,多行书写时,也可以将Value对齐:
Objective-C
//正确,冒号':'前后留有一个空格
NSDictionary *option1 = @{
NSFontAttributeName : [NSFont fontWithName:@&Helvetica-Bold& size:12],
NSForegroundColorAttributeName : fontColor
//正确,按照Value来对齐
NSDictionary *option2 = @{
NSFontAttributeName :
[NSFont fontWithName:@&Arial& size:12],
NSForegroundColorAttributeName : fontColor
//错误,冒号前应该有一个空格
NSDictionary *wrong = @{
BLongerKey: @&c&,
//错误,每一个元素要么单独成为一行,要么全部写在一行内
NSDictionary *alsoWrong= @{ AKey : @&a&,
BLongerKey : @&b& };
//错误,在冒号前只能有一个空格,冒号后才可以考虑按照Value对齐
NSDictionary *stillWrong = @{
BLongerKey : @&c&,
123456789101112131415161718192021222324252627
//正确,冒号':'前后留有一个空格NSDictionary *option1 = @{&&NSFontAttributeName : [NSFont fontWithName:@"Helvetica-Bold" size:12],&&NSForegroundColorAttributeName : fontColor};&//正确,按照Value来对齐NSDictionary *option2 = @{&&NSFontAttributeName :&&&&&&&&&&&&[NSFont fontWithName:@"Arial" size:12],&&NSForegroundColorAttributeName : fontColor};&//错误,冒号前应该有一个空格NSDictionary *wrong = @{&&AKey:&&&&&& @"b",&&BLongerKey: @"c",};&//错误,每一个元素要么单独成为一行,要么全部写在一行内NSDictionary *alsoWrong= @{ AKey : @"a",&&&&&&&&&&&&&&&&&&&&&&&&&&&&BLongerKey : @"b" };&//错误,在冒号前只能有一个空格,冒号后才可以考虑按照Value对齐NSDictionary *stillWrong = @{&&AKey&&&&&& : @"b",&&BLongerKey : @"c",};
命名应该尽可能的清晰和简洁,但在Objective-C中,清晰比简洁更重要。由于Xcode强大的自动补全功能,我们不必担心名称过长的问题。
Objective-C
insertObject:atIndex:
//不清晰,insert的对象类型和at的位置属性没有说明
insert:at:
removeObjectAtIndex:
//不清晰,remove的对象类型没有说明,参数的作用没有说明
1234567891011
//清晰insertObject:atIndex:&//不清晰,insert的对象类型和at的位置属性没有说明insert:at:&//清晰removeObjectAtIndex:&//不清晰,remove的对象类型没有说明,参数的作用没有说明remove:
不要使用单词的简写,拼写出完整的单词:
Objective-C
destinationSelection
setBackgroundColor:
//不清晰,不要使用简写
setBkgdColor:
//清晰destinationSelectionsetBackgroundColor:&//不清晰,不要使用简写destSelsetBkgdColor:
然而,有部分单词简写在Objective-C编码过程中是非常常用的,以至于成为了一种规范,这些简写可以在代码中直接使用,下面列举了部分:
Objective-C
== Allocate
== Maximum
== Alternate
== Minimum
== Application
== Message
== Calculate
== Interface Builder archive
dealloc == Deallocate
pboard == Pasteboard
== Function
== Rectangle
== Horizontal
== Representation (used in class name such as NSBitmapImageRep).
== Information
== Temporary
== Initialize
== Vertical
== Integer
12345678910
alloc&& == Allocate&&&&&&&&&&&&&&&& max&&&&== Maximumalt&&&& == Alternate&&&&&&&&&&&&&&&&min&&&&== Minimumapp&&&& == Application&&&&&&&&&&&&&&msg&&&&== Messagecalc&&&&== Calculate&&&&&&&&&&&&&&&&nib&&&&== Interface Builder archivedealloc == Deallocate&&&&&&&&&&&&&& pboard == Pasteboardfunc&&&&== Function&&&&&&&&&&&&&&&& rect&& == Rectanglehoriz&& == Horizontal&&&&&&&&&&&&&& Rep&&&&== Representation (used in class name such as NSBitmapImageRep).info&&&&== Information&&&&&&&&&&&&&&temp&& == Temporaryinit&&&&== Initialize&&&&&&&&&&&&&& vert&& == Verticalint&&&& == Integer
命名方法或者函数时要避免歧义
Objective-C
//有歧义,是返回sendPort还是send一个Port?
//有歧义,是返回一个名字属性的值还是display一个name的动作?
displayName
//有歧义,是返回sendPort还是send一个Port?sendPort&//有歧义,是返回一个名字属性的值还是display一个name的动作?displayName
整个工程的命名风格要保持一致性,最好和苹果SDK的代码保持统一。不同类中完成相似功能的方法应该叫一样的名字,比如我们总是用count来返回集合的个数,不能在A类中使用count而在B类中使用getNumber。
如果代码需要打包成Framework给别的工程使用,或者工程项目非常庞大,需要拆分成不同的模块,使用命名前缀是非常有用的。
前缀由大写的字母缩写组成,比如Cocoa中NS前缀代表Founation框架中的类,IB则代表Interface Builder框架。
可以在为类、协议、函数、常量以及typedef宏命名的时候使用前缀,但注意不要为成员变量或者方法使用前缀,因为他们本身就包含在类的命名空间内。
命名前缀的时候不要和苹果SDK框架冲突。
命名类和协议(Class&Protocol)
类名以大写字母开头,应该包含一个名词来表示它代表的对象类型,同时可以加上必要的前缀,比如NSString, NSDate, NSScanner, NSApplication等等。
而协议名称应该清晰地表示它所执行的行为,而且要和类名区别开来,所以通常使用ing词尾来命名一个协议,比如NSCopying,NSLocking。
有些协议本身包含了很多不相关的功能,主要用来为某一特定类服务,这时候可以直接用类名来命名这个协议,比如NSObject协议,它包含了id对象在生存周期内的一系列方法。
命名头文件(Headers)
源码的头文件名应该清晰地暗示它的功能和包含的内容:
如果头文件内只定义了单个类或者协议,直接用类名或者协议名来命名头文件,比如NSLocale.h定义了NSLocale类。
如果头文件内定义了一系列的类、协议、类别,使用其中最主要的类名来命名头文件,比如NSString.h定义了NSString和NSMutableString。
每一个Framework都应该有一个和框架同名的头文件,包含了框架中所有公共类头文件的引用,比如Foundation.h
Framework中有时候会实现在别的框架中类的类别扩展,这样的文件通常使用被扩展的框架名+Additions的方式来命名,比如NSBundleAdditions.h。
命名方法(Methods)
Objective-C的方法名通常都比较长,这是为了让程序有更好地可读性,按苹果的说法“好的方法名应当可以以一个句子的形式朗读出来”。
方法一般以小写字母打头,每一个后续的单词首字母大写,方法名中不应该有标点符号(包括下划线),有两个例外:
可以用一些通用的大写字母缩写打头方法,比如PDF,TIFF等。
可以用带下划线的前缀来命名私有方法或者类别中的方法。
如果方法表示让对象执行一个动作,使用动词打头来命名,注意不要使用do,does这种多余的关键字,动词本身的暗示就足够了:
Objective-C
//动词打头的方法表示让对象执行一个动作
- (void)invokeWithTarget:(id)
- (void)selectTabViewItem:(NSTabViewItem *)tabViewI
//动词打头的方法表示让对象执行一个动作- (void)invokeWithTarget:(id)target;- (void)selectTabViewItem:(NSTabViewItem *)tabViewItem;
如果方法是为了获取对象的一个属性值,直接用属性名称来命名这个方法,注意不要添加get或者其他的动词前缀:
Objective-C
//正确,使用属性名来命名方法
- (NSSize)cellS
//错误,添加了多余的动词前缀
- (NSSize)calcCellS
- (NSSize)getCellS
//正确,使用属性名来命名方法- (NSSize)cellSize;&//错误,添加了多余的动词前缀- (NSSize)calcCellSize;- (NSSize)getCellSize;
对于有多个参数的方法,务必在每一个参数前都添加关键词,关键词应当清晰说明参数的作用:
Objective-C
//正确,保证每个参数都有关键词修饰
- (void)sendAction:(SEL)aSelector toObject:(id)anObject forAllCells:(BOOL)
//错误,遗漏关键词
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)
- (id)viewWithTag:(NSInteger)aT
//错误,关键词的作用不清晰
- (id)taggedView:(int)aT
1234567891011
//正确,保证每个参数都有关键词修饰- (void)sendAction:(SEL)aSelector toObject:(id)anObject forAllCells:(BOOL)flag;&//错误,遗漏关键词- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;&//正确- (id)viewWithTag:(NSInteger)aTag;&//错误,关键词的作用不清晰- (id)taggedView:(int)aTag;
不要用and来连接两个参数,通常and用来表示方法执行了两个相对独立的操作(从设计上来说,这时候应该拆分成两个独立的方法):
Objective-C
//错误,不要使用&and&来连接参数
- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileT
//正确,使用&and&来表示两个相对独立的操作
- (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)
//错误,不要使用&and&来连接参数- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;&//正确,使用&and&来表示两个相对独立的操作- (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag;
方法的参数命名也有一些需要注意的地方:
和方法名类似,参数的第一个字母小写,后面的每一个单词首字母大写
不要再方法名中使用类似pointer,ptr这样的字眼去表示指针,参数本身的类型足以说明
不要使用只有一两个字母的参数名
不要使用简写,拼出完整的单词
下面列举了一些常用参数名:
Objective-C
...action:(SEL)aSelector
...alignment:(int)mode
...atIndex:(int)index
...content:(NSRect)aRect
...doubleValue:(double)aDouble
...floatValue:(float)aFloat
...font:(NSFont *)fontObj
...frame:(NSRect)frameRect
...intValue:(int)anInt
...keyEquivalent:(NSString *)charCode
...length:(int)numBytes
...point:(NSPoint)aPoint
...stringValue:(NSString *)aString
...tag:(int)anInt
...target:(id)anObject
...title:(NSString *)aString
12345678910111213141516
...action:(SEL)aSelector...alignment:(int)mode...atIndex:(int)index...content:(NSRect)aRect...doubleValue:(double)aDouble...floatValue:(float)aFloat...font:(NSFont *)fontObj...frame:(NSRect)frameRect...intValue:(int)anInt...keyEquivalent:(NSString *)charCode...length:(int)numBytes...point:(NSPoint)aPoint...stringValue:(NSString *)aString...tag:(int)anInt...target:(id)anObject...title:(NSString *)aString
存取方法(Accessor Methods)
存取方法是指用来获取和设置类属性值的方法,属性的不同类型,对应着不同的存取方法规范:
Objective-C
//属性是一个名词时的存取方法范式
- (void)setNoun:(type)aN
- (NSString *)
- (void)setTitle:(NSString *)aT
//属性是一个形容词时存取方法的范式
- (BOOL)isA
- (void)setAdjective:(BOOL)
- (BOOL)isE
- (void)setEditable:(BOOL)
//属性是一个动词时存取方法的范式
- (BOOL)verbO
- (void)setVerbObject:(BOOL)
- (BOOL)showsA
- (void)setShowsAlpha:(BOOL)
1234567891011121314151617181920
//属性是一个名词时的存取方法范式- (type)noun;- (void)setNoun:(type)aNoun;//栗子- (NSString *)title;- (void)setTitle:(NSString *)aTitle;&//属性是一个形容词时存取方法的范式- (BOOL)isAdjective;- (void)setAdjective:(BOOL)flag;//栗子- (BOOL)isEditable;- (void)setEditable:(BOOL)flag;&//属性是一个动词时存取方法的范式- (BOOL)verbObject;- (void)setVerbObject:(BOOL)flag;//栗子- (BOOL)showsAlpha;- (void)setShowsAlpha:(BOOL)flag;
命名存取方法时不要将动词转化为被动形式来使用:
Objective-C
- (void)setAcceptsGlyphInfo:(BOOL)
- (BOOL)acceptsGlyphI
//错误,不要使用动词的被动形式
- (void)setGlyphInfoAccepted:(BOOL)
- (BOOL)glyphInfoA
//正确- (void)setAcceptsGlyphInfo:(BOOL)flag;- (BOOL)acceptsGlyphInfo;&//错误,不要使用动词的被动形式- (void)setGlyphInfoAccepted:(BOOL)flag;- (BOOL)glyphInfoAccepted;
可以使用can,should,will等词来协助表达存取方法的意思,但不要使用do,和does:
Objective-C
- (void)setCanHide:(BOOL)
- (BOOL)canH
- (void)setShouldCloseDocument:(BOOL)
- (BOOL)shouldCloseD
//错误,不要使用&do&或者&does&
- (void)setDoesAcceptGlyphInfo:(BOOL)
- (BOOL)doesAcceptGlyphI
//正确- (void)setCanHide:(BOOL)flag;- (BOOL)canHide;- (void)setShouldCloseDocument:(BOOL)flag;- (BOOL)shouldCloseDocument;&//错误,不要使用&do&或者&does&- (void)setDoesAcceptGlyphInfo:(BOOL)flag;- (BOOL)doesAcceptGlyphInfo;
为什么Objective-C中不适用get前缀来表示属性获取方法?因为get在Objective-C中通常只用来表示从函数指针返回值的函数:
Objective-C
//三个参数都是作为函数的返回值来使用的,这样的函数名可以使用&get&前缀
- (void)getLineDash:(float *)pattern count:(int *)count phase:(float *)
//三个参数都是作为函数的返回值来使用的,这样的函数名可以使用&get&前缀- (void)getLineDash:(float *)pattern count:(int *)count phase:(float *)phase;
命名委托(Delegate)
当特定的事件发生时,对象会触发它注册的委托方法。委托是Objective-C中常用的传递消息的方式。委托有它固定的命名范式。
一个委托方法的第一个参数是触发它的对象,第一个关键词是触发对象的类名,除非委托方法只有一个名为sender的参数:
Objective-C
//第一个关键词为触发委托的类名
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)
//当只有一个&sender&参数时可以省略类名
- (BOOL)applicationOpenUntitledFile:(NSApplication *)
//第一个关键词为触发委托的类名- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row;- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;&//当只有一个&sender&参数时可以省略类名- (BOOL)applicationOpenUntitledFile:(NSApplication *)sender;
根据委托方法触发的时机和目的,使用should,will,did等关键词
Objective-C
- (void)browserDidScroll:(NSBrowser *)
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)、
- (BOOL)windowShouldClose:(id)
- (void)browserDidScroll:(NSBrowser *)sender;&- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window;、&- (BOOL)windowShouldClose:(id)sender;
集合操作类方法(Collection Methods)
有些对象管理着一系列其它对象或者元素的集合,需要使用类似“增删查改”的方法来对集合进行操作,这些方法的命名范式一般为:
Objective-C
//集合操作范式
- (void)addElement:(elementType)anO
- (void)removeElement:(elementType)anO
- (NSArray *)
- (void)addLayoutManager:(NSLayoutManager *)
- (void)removeLayoutManager:(NSLayoutManager *)
- (NSArray *)layoutM
//集合操作范式- (void)addElement:(elementType)anObj;- (void)removeElement:(elementType)anObj;- (NSArray *)elements;&//栗子- (void)addLayoutManager:(NSLayoutManager *)obj;- (void)removeLayoutManager:(NSLayoutManager *)obj;- (NSArray *)layoutManagers;
注意,如果返回的集合是无序的,使用NSSet来代替NSArray。如果需要将元素插入到特定的位置,使用类似于这样的命名:
Objective-C
- (void)insertLayoutManager:(NSLayoutManager *)obj atIndex:(int)
- (void)removeLayoutManagerAtIndex:(int)
- (void)insertLayoutManager:(NSLayoutManager *)obj atIndex:(int)index;- (void)removeLayoutManagerAtIndex:(int)index;
如果管理的集合元素中有指向管理对象的指针,要设置成weak类型以防止引用循环。
下面是SDK中NSWindow类的集合操作方法:
Objective-C
- (void)addChildWindow:(NSWindow *)childWin ordered:(NSWindowOrderingMode)
- (void)removeChildWindow:(NSWindow *)childW
- (NSArray *)childW
- (NSWindow *)parentW
- (void)setParentWindow:(NSWindow *)
- (void)addChildWindow:(NSWindow *)childWin ordered:(NSWindowOrderingMode)place;- (void)removeChildWindow:(NSWindow *)childWin;- (NSArray *)childWindows;- (NSWindow *)parentWindow;- (void)setParentWindow:(NSWindow *)window;
命名函数(Functions)
在很多场合仍然需要用到函数,比如说如果一个对象是一个单例,那么应该使用函数来代替类方法执行相关操作。
函数的命名和方法有一些不同,主要是:
函数名称一般带有缩写前缀,表示方法所在的框架。
前缀后的单词以“驼峰”表示法显示,第一个单词首字母大写。
函数名的第一个单词通常是一个动词,表示方法执行的操作:
Objective-C
NSHighlightRect
NSDeallocateObject
NSHighlightRectNSDeallocateObject
如果函数返回其参数的某个属性,省略动词:
Objective-C
unsigned int NSEventMaskFromType(NSEventType type)
float NSHeight(NSRect aRect)
unsigned int NSEventMaskFromType(NSEventType type)float NSHeight(NSRect aRect)
如果函数通过指针参数来返回值,需要在函数名中使用Get:
Objective-C
const char *NSGetSizeAndAlignment(const char *typePtr, unsigned int *sizep, unsigned int *alignp)
const char *NSGetSizeAndAlignment(const char *typePtr, unsigned int *sizep, unsigned int *alignp)
函数的返回类型是BOOL时的命名:
Objective-C
BOOL NSDecimalIsNotANumber(const NSDecimal *decimal)
BOOL NSDecimalIsNotANumber(const NSDecimal *decimal)
命名属性和实例变量(Properties&Instance Variables)
属性和对象的存取方法相关联,属性的第一个字母小写,后续单词首字母大写,不必添加前缀。属性按功能命名成名词或者动词:
Objective-C
//名词属性
@property (strong) NSString *
//动词属性
@property (assign) BOOL showsA
//名词属性@property (strong) NSString *title;&//动词属性@property (assign) BOOL showsAlpha;
属性也可以命名成形容词,这时候通常会指定一个带有is前缀的get方法来提高可读性:
Objective-C
@property (assign, getter=isEditable) BOOL
@property (assign, getter=isEditable) BOOL editable;
命名实例变量,在变量名前加上_前缀(有些有历史的代码会将_放在后面),其它和命名属性一样:
Objective-C
@implementation MyClass {
BOOL _showsT
@implementation MyClass {&&&&BOOL _showsTitle;}
一般来说,类需要对使用者隐藏数据存储的细节,所以不要将实例方法定义成公共可访问的接口,可以使用@private,@protected前缀。
按苹果的说法,不建议在除了init和dealloc方法以外的地方直接访问实例变量,但很多人认为直接访问会让代码更加清晰可读,只在需要计算或者执行操作的时候才使用存取方法访问,我就是这种习惯,所以这里不作要求。
命名常量(Constants)
如果要定义一组相关的常量,尽量使用枚举类型(enumerations),枚举类型的命名规则和函数的命名规则相同。 建议使用 NS_ENUM 和 NS_OPTIONS 宏来定义枚举类型,参见官方的
Objective-C
//定义一个枚举
typedef NS_ENUM(NSInteger, NSMatrixMode) {
NSRadioModeMatrix,
NSHighlightModeMatrix,
NSListModeMatrix,
NSTrackModeMatrix
//定义一个枚举typedef NS_ENUM(NSInteger, NSMatrixMode) {&&&&NSRadioModeMatrix,&&&&NSHighlightModeMatrix,&&&&NSListModeMatrix,&&&&NSTrackModeMatrix};
定义bit map:
Objective-C
typedef NS_OPTIONS(NSUInteger, NSWindowMask) {
NSBorderlessWindowMask
NSTitledWindowMask
NSClosableWindowMask
NSMiniaturizableWindowMask
NSResizableWindowMask
typedef NS_OPTIONS(NSUInteger, NSWindowMask) {&&&&NSBorderlessWindowMask&&&&&&= 0,&&&&NSTitledWindowMask&&&&&&&&&&= 1 << 0,&&&&NSClosableWindowMask&&&&&&&&= 1 << 1,&&&&NSMiniaturizableWindowMask&&= 1 << 2,&&&&NSResizableWindowMask&&&&&& = 1 << 3};
使用const定义浮点型或者单个的整数型常量,如果要定义一组相关的整数常量,应该优先使用枚举。常量的命名规范和函数相同:
Objective-C
const float NSLightG
const float NSLightGray;
不要使用#define宏来定义常量,如果是整型常量,尽量使用枚举,浮点型常量,使用const定义。#define通常用来给编译器决定是否编译某块代码,比如常用的:
Objective-C
#ifdef DEBUG
#ifdef DEBUG
注意到一般由编译器定义的宏会在前后都有一个__,比如__MACH__。
命名通知(Notifications)
通知常用于在模块间传递消息,所以通知要尽可能地表示出发生的事件,通知的命名范式是:
Objective-C
&code&[触发通知的类名] + [Did | Will] + [动作] + Notification
<code>[触发通知的类名] + [Did | Will] + [动作] + Notification</code>
Objective-C
NSApplicationDidBecomeActiveNotification
NSWindowDidMiniaturizeNotification
NSTextViewDidChangeSelectionNotification
NSColorPanelColorDidChangeNotification
NSApplicationDidBecomeActiveNotificationNSWindowDidMiniaturizeNotificationNSTextViewDidChangeSelectionNotificationNSColorPanelColorDidChangeNotification
读没有注释代码的痛苦你我都体会过,好的注释不仅能让人轻松读懂你的程序,还能提升代码的逼格。注意注释是为了让别人看懂,而不是仅仅你自己。
每一个文件都必须写文件注释,文件注释通常包含
文件所在模块
历史版本信息
文件包含的内容,作用
一段良好文件注释的栗子:
Objective-C
/*******************************************************************************
Copyright (C), , Andrew Min Chang
File name:
AMCCommonLib.h
Andrew Chang (Zhang Min)
Description:
This file provide some covenient tool in calling library tools. One can easily include
library headers he wants by declaring the corresponding macros.
I hope this file is not only a header, but also a useful Linux library note.
2012-??-??: On about come date around middle of Year 2012, file created as &commonLib.h&
: Add s add message queue.
: Add socket library (local)
: Add math library
: Add socket library (internet)
: Add daemon function
: Change file name as &AMCCommonLib.h&
: Add UDP support in AMC socket library
: Add basic data type such as &sint8_t&
: Add CFG_LIB_STR_NUM.
: Add CFG_LIB_TIMER.
: Remove CFG_LIB_DATA_TYPE because there is already AMCDataTypes.h
Copyright information:
This file was intended to be under GPL protocol. However, I may use this library
in my work as I am an employee. And my company may require me to keep it secret.
Therefore, this file is neither open source nor under GPL control.
********************************************************************************/
1234567891011121314151617181920212223242526272829303132
/*******************************************************************************&&&&Copyright (C), , Andrew Min Chang&&&&&File name:&&AMCCommonLib.h&&&&Author:&&&& Andrew Chang (Zhang Min) &&&&E-mail:&&&& &&&&&Description:&&&&&&&&&&&&&&&&This file provide some covenient tool in calling library tools. One can easily include &&&&&&&&library headers he wants by declaring the corresponding macros. &&&&&&&&&&&&I hope this file is not only a header, but also a useful Linux library note.&&&&&History:&&&&&&&&2012-??-??: On about come date around middle of Year 2012, file created as &commonLib.h&&&&&&&&&: Add s add message queue.&&&&&&&&: Add socket library (local)&&&&&&&&: Add math library&&&&&&&&: Add socket library (internet)&&&&&&&&: Add daemon function&&&&&&&&: Change file name as &AMCCommonLib.h&&&&&&&&&: Add UDP support in AMC socket library&&&&&&&&: Add basic data type such as &sint8_t&&&&&&&&&: Add CFG_LIB_STR_NUM.&&&&&&&&: Add CFG_LIB_TIMER.&&&&&&&&: Remove CFG_LIB_DATA_TYPE because there is already AMCDataTypes.h&&&&&Copyright information: &&&&&&&&&&&&This file was intended to be under GPL protocol. However, I may use this library&&&&&&&&in my work as I am an employee. And my company may require me to keep it secret. &&&&&&&&Therefore, this file is neither open source nor under GPL control. &********************************************************************************/
文件注释的格式通常不作要求,能清晰易读就可以了,但在整个工程中风格要统一。
好的代码应该是“自解释”(self-documenting)的,但仍然需要详细的注释来说明参数的意义、返回值、功能以及可能的副作用。
方法、函数、类、协议、类别的定义都需要注释,推荐采用Apple的标准注释风格,好处是可以在引用的地方alt+点击自动弹出注释,非常方便。
有很多可以自动生成注释格式的插件,推荐使用:
一些良好的注释:
Objective-C
Create a new preconnector to replace the old one with given mac address.
NOTICE: We DO NOT stop the old preconnector, so handle it by yourself.
@param type
Connect type the preconnector use.
@param macAddress Preconnector's mac address.
- (void)refreshConnectorWithConnectType:(IPCConnectType)type
Mac:(NSString *)macA
Stop current preconnecting when application is going to background.
-(void)stopR
Get the COPY of cloud device with a given mac address.
@param macAddress Mac address of the device.
@return Instance of IPCCloudDevice.
-(IPCCloudDevice *)getCloudDeviceWithMac:(NSString *)macA
// A delegate for NSApplication to handle notifications about app
// launch and shutdown. Owned by the main app controller.
@interface MyAppDelegate : NSObject {
1234567891011121314151617181920212223242526272829
/** *&&Create a new preconnector to replace the old one with given mac address. *&&NOTICE: We DO NOT stop the old preconnector, so handle it by yourself. * *&&@param type&&&&&& Connect type the preconnector use. *&&@param macAddress Preconnector's mac address. */- (void)refreshConnectorWithConnectType:(IPCConnectType)type&&Mac:(NSString *)macAddress;&/** *&&Stop current preconnecting when application is going to background. */-(void)stopRunning;&/** *&&Get the COPY of cloud device with a given mac address. * *&&@param macAddress Mac address of the device. * *&&@return Instance of IPCCloudDevice. */-(IPCCloudDevice *)getCloudDeviceWithMac:(NSString *)macAddress;&// A delegate for NSApplication to handle notifications about app// launch and shutdown. Owned by the main app controller.@interface MyAppDelegate : NSObject {&&...}@end
协议、委托的注释要明确说明其被触发的条件:
Objective-C
/** Delegate - Sent when failed to init connection, like p2p failed. */
-(void)initConnectionDidFailed:(IPCConnectHandler *)
/** Delegate - Sent when failed to init connection, like p2p failed. */-(void)initConnectionDidFailed:(IPCConnectHandler *)handler;
如果在注释中要引用参数名或者方法函数名,使用||将参数或者方法括起来以避免歧义:
Objective-C
// Sometimes we need |count| to be less than zero.
// Remember to call |StringWithoutSpaces(&foo bar baz&)|
// Sometimes we need |count| to be less than zero.&// Remember to call |StringWithoutSpaces(&foo bar baz&)|
定义在头文件里的接口方法、属性必须要有注释!
每个人都有自己的编码风格,这里总结了一些比较好的Cocoa编程风格和注意点。
不要使用new方法
尽管很多时候能用new代替alloc init方法,但这可能会导致调试内存时出现不可预料的问题。Cocoa的规范就是使用alloc init方法,使用new会让一些读者困惑。
Public API要尽量简洁
共有接口要设计的简洁,满足核心的功能需求就可以了。不要设计很少会被用到,但是参数极其复杂的API。如果要定义复杂的方法,使用类别或者类扩展。
#import和#include
#import是Cocoa中常用的引用头文件的方式,它能自动防止重复引用文件,什么时候使用#import,什么时候使用#include呢?
当引用的是一个Objective-C或者Objective-C++的头文件时,使用#import
当引用的是一个C或者C++的头文件时,使用#include,这时必须要保证被引用的文件提供了保护域(#define guard)。
Objective-C
#import &Cocoa/Cocoa.h&
#include &CoreFoundation/CoreFoundation.h&
#import &GTMFoo.h&
#include &base/basictypes.h&
#import &Cocoa/Cocoa.h&#include &CoreFoundation/CoreFoundation.h&#import &GTMFoo.h&#include &base/basictypes.h&
为什么不全部使用#import呢?主要是为了保证代码在不同平台间共享时不出现问题。
引用框架的根头文件
上面提到过,每一个框架都会有一个和框架同名的头文件,它包含了框架内接口的所有引用,在使用框架的时候,应该直接引用这个根头文件,而不是其它子模块的头文件,即使是你只用到了其中的一小部分,编译器会自动完成优化的。
Objective-C
//正确,引用根头文件
#import &Foundation/Foundation.h&
//错误,不要单独引用框架内的其它头文件
#import &Foundation/NSArray.h&
#import &Foundation/NSString.h&
//正确,引用根头文件#import &Foundation/Foundation.h&&//错误,不要单独引用框架内的其它头文件#import &Foundation/NSArray.h&#import &Foundation/NSString.h&
BOOL的使用
BOOL在Objective-C中被定义为signed char类型,这意味着一个BOOL类型的变量不仅仅可以表示YES(1)和NO(0)两个值,所以永远不要将BOOL类型变量直接和YES比较:
Objective-C
//错误,无法确定|great|的值是否是YES(1),不要将BOOL值直接与YES比较
BOOL great = [foo isGreat];
if (great == YES)
// ...be great!
BOOL great = [foo isGreat];
if (great)
// ...be great!
//错误,无法确定|great|的值是否是YES(1),不要将BOOL值直接与YES比较BOOL great = [foo isGreat];if (great == YES)&&// ...be great!&//正确BOOL great = [foo isGreat];if (great)&&// ...be great!
同样的,也不要将其它类型的值作为BOOL来返回,这种情况下,BOOL变量只会取值的最后一个字节来赋值,这样很可能会取到0(NO)。但是,一些逻辑操作符比如&&,||,!的返回是可以直接赋给BOOL的:
Objective-C
//错误,不要将其它类型转化为BOOL返回
- (BOOL)isBold {
return [self fontTraits] & NSFontBoldT
- (BOOL)isValid {
return [self stringValue];
- (BOOL)isBold {
return ([self fontTraits] & NSFontBoldTrait) ? YES : NO;
//正确,逻辑操作符可以直接转化为BOOL
- (BOOL)isValid {
return [self stringValue] !=
- (BOOL)isEnabled {
return [self isValid] && [self isBold];
1234567891011121314151617181920
//错误,不要将其它类型转化为BOOL返回- (BOOL)isBold {&&return [self fontTraits] & NSFontBoldTrait;}- (BOOL)isValid {&&return [self stringValue];}&//正确- (BOOL)isBold {&&return ([self fontTraits] & NSFontBoldTrait) ? YES : NO;}&//正确,逻辑操作符可以直接转化为BOOL- (BOOL)isValid {&&return [self stringValue] != nil;}- (BOOL)isEnabled {&&return [self isValid] && [self isBold];}
另外BOOL类型可以和_Bool,bool相互转化,但是不能和Boolean转化。
除非想要兼容一些古董级的机器和操作系统,我们没有理由放弃使用ARC。在最新版的Xcode(6.2)中,ARC是自动打开的,所以直接使用就好了。
在init和dealloc中不要用存取方法访问实例变量
当initdealloc方法被执行时,类的运行时环境不是处于正常状态的,使用存取方法访问变量可能会导致不可预料的结果,因此应当在这两个方法内直接访问实例变量。
Objective-C
//正确,直接访问实例变量
- (instancetype)init {
self = [super init];
if (self) {
_bar = [[NSMutableString alloc] init];
- (void)dealloc {
[_bar release];
[super dealloc];
//错误,不要通过存取方法访问
- (instancetype)init {
self = [super init];
if (self) {
self.bar = [NSMutableString string];
- (void)dealloc {
self.bar =
[super dealloc];
12345678910111213141516171819202122232425
//正确,直接访问实例变量- (instancetype)init {&&self = [super init];&&if (self) {&&&&_bar = [[NSMutableString alloc] init];&&}&&return self;}- (void)dealloc {&&[_bar release];&&[super dealloc];}&//错误,不要通过存取方法访问- (instancetype)init {&&self = [super init];&&if (self) {&&&&self.bar = [NSMutableString string];&&}&&return self;}- (void)dealloc {&&self.bar = nil;&&[super dealloc];}
按照定义的顺序释放资源
在类或者Controller的生命周期结束时,往往需要做一些扫尾工作,比如释放资源,停止线程等,这些扫尾工作的释放顺序应当与它们的初始化或者定义的顺序保持一致。这样做是为了方便调试时寻找错误,也能防止遗漏。
保证NSString在赋值时被复制
NSString非常常用,在它被传递或者赋值时应当保证是以复制(copy)的方式进行的,这样可以防止在不知情的情况下String的值被其它对象修改。
Objective-C
- (void)setFoo:(NSString *)aFoo {
_foo = [aFoo copy];
- (void)setFoo:(NSString *)aFoo {&&_foo = [aFoo copy];}
使用NSNumber的语法糖
使用带有@符号的语法糖来生成NSNumber对象能使代码更简洁:
Objective-C
NSNumber *fortyTwo = @42;
NSNumber *piOverTwo = @(M_PI / 2);
kMyEnum = 2;
NSNumber *myEnum = @(kMyEnum);
NSNumber *fortyTwo = @42;NSNumber *piOverTwo = @(M_PI / 2);enum {&&kMyEnum = 2;};NSNumber *myEnum = @(kMyEnum);
因为在Objective-C中向nil对象发送命令是不会抛出异常或者导致崩溃的,只是完全的“什么都不干”,所以,只在程序中使用nil来做逻辑上的检查。
另外,不要使用诸如nil == Object或者Object == nil的形式来判断。
Objective-C
//正确,直接判断
if (!objc) {
//错误,不要使用nil == Object的形式
if (nil == objc) {
//正确,直接判断if (!objc) {&&&&... }&//错误,不要使用nil == Object的形式if (nil == objc) {&&&&... }
属性的线程安全
定义一个属性时,编译器会自动生成线程安全的存取方法(Atomic),但这样会大大降低性能,特别是对于那些需要频繁存取的属性来说,是极大的浪费。所以如果定义的属性不需要线程保护,记得手动添加属性关键字nonatomic来取消编译器的优化。
点分语法的使用
不要用点分语法来调用方法,只用来访问属性。这样是为了防止代码可读性问题。
Objective-C
//正确,使用点分语法访问属性
NSString *oldName = myObject.
myObject.name = @&Alice&;
//错误,不要用点分语法调用方法
NSArray *array = [NSArray arrayWithObject:@&hello&];
NSUInteger numberOfItems = array.
//正确,使用点分语法访问属性NSString *oldName = myObject.name;myObject.name = @"Alice";&//错误,不要用点分语法调用方法NSArray *array = [NSArray arrayWithObject:@"hello"];NSUInteger numberOfItems = array.count;array.release;
Delegate要使用弱引用
一个类的Delegate对象通常还引用着类本身,这样很容易造成引用循环的问题,所以类的Delegate属性要设置为弱引用。
Objective-C
/** delegate */
@property (nonatomic, weak) id &IPCConnectHandlerDelegate&
/** delegate */@property (nonatomic, weak) id <IPCConnectHandlerDelegate> delegate;
&&& iOS频道微信号:iOSHub, 扫描加关注,碎片时间提升iOS开发技能!
可能感兴趣的话题
关于伯乐在线-iOS频道
iOS频道分享iOS和Swift开发,应用设计和推广,iOS相关的行业动态。欢迎通过和微信【 微信号: iOSHub 】关注。
欢迎关注更多频道
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选博客文章
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
(加好友请注明来意)
网站使用问题
请在询问或者反馈
& 2015 伯乐在线
赞助云主机}

我要回帖

更多关于 ios c语言编译器 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信