标签:
前言
做iOS开发的童鞋都应该会纠结一个问题,那就是在做开发的时候是使用StoryBoard还是使用Nibs又或者是Code(纯代码流)呢?笔者也非常纠结这个问题,今天碰巧在raywenderlich上面看到了几个大神之间的撕逼,哦不,讨论之后,感觉收获良多,于是就将他们讨论的内容整理翻译了一下,如有不当之处,还请多多包涵,原视频请戳这里
http://t.cn/zRAb4NF
讨论
Ray Wenderlich
Ok!现在我们都在线,感谢各位的到来,今天我们会有一个讨论关于iOS开发的讨论,是选择Storyboards、Nib还是Code,我们有三个志愿者,Cesare Rocchi代表的是“Code爱好者”,Tammy Coron 代表的是“Nib爱好者”,Felipe Laso Marsetti代表的是“StoryBoard爱好者”,我们将从Cesare Rocchi开始
Cesare Rocchi
首先,code是非常清晰直观的,你可以直接看着代码,你不需要打开愚蠢的Nib文件,并且不用深入研究然后找出一些复杂元素到底关联了还是没有关联,这些都很傻;当你在开发一个大型项目的时候这种方式非常的有用;当我从一个crazy guy那里接手一个项目,这个项目是用StoryBoard或者Nibs做的,最后我会用code重写所用的东西,你可以在StoryBoard或者Nibs设置好所有东西,但是最后你可以用代码重写所有的状态;比如你在一个nib文件里面设置了一个lable,当你运行这个app的时候这个lable看起来与你设置的不太一样,这是因为另外一个人在之后添加了一行代码改变了那个lable的属性
Tammy Coron
当听到他(Cesare Rocchi)如此贬低Nib的时候让我怒不可遏,我作为一个程序媛有很长一段时间了,我见过非常多的程序猿喜欢使用code的方式来开发的;但就我个人而言,我是一个非常依赖于视觉的人,我喜欢通过可视化的方式来进行编程,所以我选择使用Nibs;你可能会说使用StoryBoard可以比使用Nibs看到更多的东西,但是对我来说,我并不喜欢StoryBoard,因为StoryBoard能做的很有限,特别是当你在写一个大型项目的时候或者你与其他的人合作的时候,如果使用StoryBoard你将会把所有的UI都集中在一个文件里面,这会导致合作变得非常困难,合并上也会有很多的麻烦;StoryBoard上还有一个很大的问题就是,它不允许你操作太多的属性,特别是在不同的View里面使用TableViewCells的时候,你不可以在StoryBoard里面重用它们,你可能可以做到但是会比较麻烦,而Nib要做起这个会更加的简单;并且你不要想去在StoryBoard里自定义Controller或者是View,无论何时想要做到这些你最好去使用Nib
对于code,我同意如果使用code要做很多的工作,必须要去理解Nib背后的代码,但是使用Nib你可以快速看到自己对元素操作的效果,如果使用code,你写好所有的元素,设置好它们的属性,再将它们添加到视图里面,你必须要在运行app之后才能够看到具体的效果,这是非常重要的事情,没有人在意代码到底长什么样,他们只会关心app看起来怎么样, 最好的观察方式就是使用Nib来做
So,我可能有点小激动,等我冷静下来我会说得更好,XD
Raywenderlich
非常不错的观点,现在轮到最后一个人发言了,Felipe该你上了
Felipe Laso Marsetti
So,Cesare你就是个混蛋;Tammy并没有让我感到不悦,因为她很重视可视化,而可视化就是未来,虽然code很酷,但是可视化将会是未来,不错,Nib或许更加的酷更加的自由,但是未来一定是StoryBoard的天下,它可以让你做到一些Nib与code做不到的事情,当你在合并代码或者合并Nib的时候你仍然会遇到冲突,每当你触碰Nibs,Xcode就会毫无理由的认为你改变了它,所以你要描述这样的改变,因为Xcode认为它改变了,仅仅因为你看了它一眼
StoryBoard更好,不用再像Nib或者code那样工作,如果你使用code,你需要运行你的app,看布局是否合理,然后回去更改布局属性,再运行app来看效果,不断的重复,这样效率非常的低,或许使用Nib会有所好转,但是当你在做一个大型项目的时候,你会有三四十个ViewController,这样你可能就会有四五十个Nib文件,这会非常的烦人,因为你要非常小心的做一些修改
然而StoryBoard不仅可以让你避免写一大堆无聊的代码,甚至是避免那些要在Nib下写的代码,比如使用segue和unwind segue,你可以通过一系列的delegate方法来传输数据,你可以设置转场动画,你甚至可以自定义动画
大家都认为我们只能在一个StoryBoard上面工作,但是实际上我们可以在不止一个StoryBoard上面工作;当我们在开发企业级客户端的时候,我们通常都是3-5个人的团队,我们会有10个StoryBoard,这很美妙,因为你可以将各个模块分开,比如about模块、反馈模块或者社交模块,你可以看到可视化的layout,为了避免别人说StoryBoard变得越来越大,越来越慢,你可以试着打开它,然后,boom~~,你可以清楚地知道什么连接着什么,什么要去哪里,你可以命名你的segue,你可以拥有很多的自定义,所有的这一切都预示着StoryBoard将会是未来
当然,Nibs和code是很有用的,而且我也建议在必要的时候去使用Nibs和code,但是我想说在Xcode中使用StoryBoard是非常方便的,这是苹果在用的东西,他们为StoryBoard做了非常多的工作,它就是未来,并没有足够的证据来证明StroyBoard很慢很臃肿或者其他,没有足够有力的证据来证明这一些;我强烈建议使用StoryBoard,当必要的时候你可以使用code或者nibs,但是我建议你尽量避免去使用,因为StoryBoard才是王道
Raywenderlich
Awsome!非常棒的观点!So,接下来每个人都有一个机会为自己的观点进行辩解,那么,Cesare你有什么要说的吗?
Cesare Rocchi
额,首先,如果当你想要合并Nib或者StoryBoard的时候,那简直就是噩梦,毫无意义,然后code要做到这个是非常轻松的,作为一个项目经理,我可以清楚地看到昨天代码都做了哪些修改,但是像Nib或者StoryBoard,我无法把握它到底做了什么,到底是修复了bug还是实现了某一个功能
还有就是,你在某些时候可能会使用Xcode的beta版本来进行工作,你知道Xcode在管理Nibs或者StoryBoard上面并没有那么的智能,当我打开项目的时候,beta版的Xcode修改了某些文件,导致了所有东西都消失了,这就意味着你打开StoryBoard之后什么都没有了,所以整个项目就完全崩溃了
第三点就是使用Nibs或者StoryBoard会减低我的工作效率,当我在coding的时候,我喜欢保持我的手放在键盘上面,而不用去打开一个nib文件然后去做一些关联,然后又将手放回键盘继续coding,这样会降低我的工作效率;还有一点要提的就是,不止一次,特别是在开始的时候,我会盯着屏幕,尝试着找出是谁TMD给这个属性设置了值,谁设置了x或者y,在哪里或者是如何设置的等等,That’s all!
Raywenderlich
So,Cesare说使用code会让他的工作效率更高,Tammy你有什么要说的吗?
Tammy Coron
额,当你看着nib文件的时候,你并不需要过多的去关心那么多的属性,它们是怎么设置的以及它们如何的关联,当你使用nib工作的时候,你只需要将你的psd文件处理之后放到nib文件里面,这样你直接就可以看到效果,然后你再去关联代码,我想说的是使用nib一切都非常的快速
我可以在app完成之后深入到framework里面,在非常有限的时间里面,在这里面没有代码,只有可视化的元素,这样就可以快速的深入到screen里,去看你的app是如何连接的,然后再去处理自己的代码;但是如果你把一切都用代码来做将会非常的繁琐,要去设置这样那样的属性,oh my god,简直无聊死了,根本就是在浪费时间;我讨厌使用StoryBoard,使用StoryBoard的人就像是僵尸一样,一个big boy不应该去使用StoryBoard,额,反正我就是不喜欢XD
Raywenderlich
So,Felipe你是这里最年轻的成员,你也非常喜欢僵尸,你有什么观点?
Felipe Laso Marsetti
额,我就是一个僵尸StoryBoard用户,我强烈建议使用StoryBoard,code是非常有必要的,有时候你不得不去写一些代码来完成那些可视化完成不了的工作,比如自定义UI,但是那些都不是常用的,大部分时候使用StoryBoard就可以满足需求了;使用StoryBoard你可以非常方便的去设置元素属性,而不用去理会背后繁琐的代码;这所有的一切都意味着StoryBoard是未来,这是苹果在用的东西
最后我想说,越少的代码就意味着越少的机会将bug引入到你的app里面,就好像有500行自定义UI的代码,你可以将它们减少到100行,这样你就可以避免掉400行没有必要的代码,这样可以减少bug,而且这样更加容易的去维护你的代码,如果你是独立开发,那么使用code或许对你影响不大,但是如果你从别人那里接手项目,你就不得不深入研究这些代码到底做了什么,是如何设置view的,什么继承了什么,以及在nib里面有什么,你甚至不能使用nib去创建一个有着static prototype cells的tableview,你必须去创建一个tableview的子类,新建.h、.m、以及nib文件,然后再去创建cell的子类,再新建.h、.m、以及nib文件,然后这些cells在tableview当中是独立的,这样你就不得不去新建一个又一个的cell;然而在StroyBoard里面,只需要一个tableview,20个cells,然后boom~~,太美妙了,节省时间,让客户端更简单,更少的bug,而且一切都是在可视化下完成的,你不用去不停的stop、run、stop、run,然后去看你的nib文件以及你的代码,僵尸赢了
Raywenderlich
不错的论证,有一点我不断听到的就是,使用可视化的User Interface Designer,你可以避免更多的代码,可以减少bug,你们怎么看待这个观点?
Cesare Rocchi
额,在autolayout出现之前我会同意这个观点,如果让我对Interface Builder进行打分(10分制),在过去我会给6分,当autolayout出现之后就只有3分了,我特别害怕在Xcode4.6上面进行工作,autolayout尝试着将所有的东西混合在一起,造成的情况就是你在界面上面没有问题,但是在通常情况下这不是你想要的,你可能是想要让你的视图更小或者是其他;我不得不承认autolayout在Xcode5之后有所改善,但我对此并不是很感兴趣
Raywenderlich
Tammy,Cesare很反感autolayout,你有什么想说的吗?
Tammy Coron
我同样也不是autolayout的狂热粉丝,我会尽可能的将autolayout关闭掉,我在一些项目上面用过autolayout,但我对autolayout提不起兴趣,你仍然可以使用Nib而不去使用autolayout,所以我认为他的论证是无效的,抱歉XD
Raywenderlich
那么Felipe你是怎么看待autolayout的呢?
Felipe Laso Marsetti
无论你喜不喜欢,autolayout会始终存在着,我们将会有不同尺寸的设备需要去适配,iPad mini、iPhone4、4s、iPad retina,autolayout可以帮助我们去完成这些适配,Nin与StoryBoard都可以让你可视化的去使用autolayout,你可以非常直观的在屏幕上进行布局,但是如果去使用code,这将会是一件非常麻烦的事情
使用StoryBoard在debug的时候你可以非常直观的看到,在Xcode5上,你可以预览自己的布局,一旦你更改布局约束,改变设备的尺寸,你可以立刻就看到结果,如果你使用code,你就不得不debug、run、debug、run,非常的麻烦;就个人而言,我也不是非常的喜欢autolayout,虽然在Xcode5与iOS7之后有所改善,但仍然不是很好用,这个我们无能为力,但是不管怎样,使用Interface Builder会好过使用code
Raywenderlich
OK!不错的论证,接下来会持续进行半个小时的讨论,Cesare从你开始
Cesare Rocchi
code是非常清晰直观的,你可以写完之后立刻运行,然后得出运行结果,你不需要深入到6个不同的属性编辑器当中,来搞清楚这些变量属性等等是如何被设置的
最后一点我想要说的是,Interface Builder背后的理念是非常不错的,这个理念是想要让设计师使用来设计UI,不管是Nibs还是StoryBoard都会让你直观的看到你的app长什么样子,就像在有些时候,你不需要有一个填充着数据的tableview,作为一个设计师,根本就不会需要一个填充着真实数据的tableview,设计师只想要知道app看起来怎样,这不仅是一个给设计师的工具,更多的是给那些不想写太多代码的coder,That’s all
Raywenderlich
OK!And Tammy?
Tammy Coron
总的来说,我认为Nibs是最好的方案,特别是对于有创造力的人,知道Nibs背后的代码原理是必要的,但是你为什么要去浪费时间去跟代码较劲,Nibs非常的强大;至于Story Board,我无法像看待VB那样看待它,它就像僵尸一样(可能是异类的意思)(Tammy后面说了一个僵尸吃大脑的笑话,听得不是很懂就没翻译了)
Raywenderlich
Awsome!Felipe?
Felipe Laso Marsetti
额,StoryBoard就是未来,就像block,就像ARC,就像一代又一代的Xcode与iOS一样,苹果现在把精力都放在了StoryBoard上面,他们没有在Nibs上面更新太多的东西,他们没有再加新功能进去,你可以坚持使用Nibs或者是code,但是使用StoryBoard你可以节省大量的时间,你可以在StoryBoard上做出非常复杂的UI,segues、unwind segues、custom segues,你甚至可以让StoryBoard与Nibs和code一起工作,更少的bug,你应该去尝试一下
然而你们很多人还是在使用code和Nibs,因为你们很顽固,你们喜欢老的方法,害怕改变,说实话,我在日常工作当中总是在使用StoryBoard,我们在大型的合作项目中使用它,它总是最趁手的工具
在大多数情况下,就我的经验而言,我或许是一个年轻的僵尸,StoryBoard就是我的工具,StoryBoard可以做到的事你是可以用Nibs和code做到,但是记住,这是在苹果在WWDC上面提出来的东西,把StoryBoard和Nibs混合起来会工作的很好,这就是苹果在做的事情,StoryBoard就是最好的工具,所以,请别阻止你自己去尝试这一项美好的新技术,你可能仅仅只是害怕做出改变,你只需要花一点小小的时间,你就会感受到StoryBoard的美好之处
Raywenderlich
Awsome!感谢各位的发言,那么各位有什么问题想问的吗?
Matthijs Hollemans
如果你把所有的东西都放在StoryBoard里面,你就需要一次性的弄清楚这一大堆的东西,我认为像Nibs那么被分割会更好,允许你使用segue来连接任何东西,你应该每次只处理一个屏幕,这样更兼容你的Xcode窗口大小,然而StoryBoard占用了太大的空间
司机
我们都知道使用StoryBoard可以非常容易的做出一个简单的应用,在AppStore当中80%的应用都是属于简单应用,有许多的开发者都是业余的,包括我也是,我只是想出了非常好的idea,但不一定要做出非常棒的app,我想StoryBoard就是为这些人准备的
Chris Wagner
这是很好的一点
Tammy Coron
你可以仅仅是nibs来构建一个StoryBoard,就像你如何整理自己的项目一样,但是我无法想象自己能够像使用Nibs那样去使用StoryBoard,说实话其实我并没有怎么使用过StoryBoard,所以我对于StoryBoard的大部分观点都很牵强XD
Matthijs Hollemans
我同样也是一个依赖视觉的人,同样我也喜欢在可视化的角度去做事,Xcode可以变得比现在更加的可视化,不仅仅是在组织Nibs和StoryBoard上面,Xcode还可以可视化的做很多的事情,举个栗子,可视化的操控UI元素,我更喜欢在Nibs下做这些事情,我不认为这种方式(使用Nibs)会被淡化,因为我认为苹果并没有花太多的心思在自己的开发工具上,它可能只给了开发需要用到的最少功能,特别在与其他的IDE比较起来的时候,我期待Xcode在未来会变得更加的可视化
Felipe Laso Marsetti
等一下!你居然说苹果没有花心思在开发工具上?╰(‵□′)╯
Matthijs Hollemans
额,确实,这一块对他们而言并不是很重要,他们虽然给了开发者appstore,但是如果他们真的很重视这一块,他们应该会给我们更多更有用的工具
Felipe Laso Marsetti
这是一个值得讨论的地方,核心的问题是,不管你喜不喜欢,autolayout与StoryBoard都会持续存在,明年WWDC,苹果公布iOS8,我们将会看到苹果在StoryBoard以及Interface Builder上面做的工作,可视化将会变得更加的强大,有一点我需要考虑的就是是否要在大型项目中选择使用Nibs,StoryBoard是以ViewController为基础元素的,而Nibs是以View为基础元素的,一个nib就是一个view,这样在开始使用的时候会有点不适应,因为你想要创建一个自定义的view,但是你又不能够在直接在StoryBoard里面做到
另外关于苹果专注于appstore等问题,这些是事实,但是记住,苹果也确定了整套UI、开发了StoryBoard、Interface Builder,他们打造这一整个生态链;另外关于StoryBoard,你可以用来创建非常简单的app,遇到复杂的app,你可能会去选择Nibs,我觉得这是错误的,你仍然会在合并的时候遇到冲突;我想说的是,尝试一下,如果你需要帮助,来我这里,你知道在哪里可以找到我;使用StoryBoard,你确实可以做出非常复杂的项目,性能问题根本无需去担心,在现在的5与5s上面就更加没有必要去担心这个问题了
Tammy Coron
StoryBoard让我感到麻烦的是,你不得不在自己的app上面创建自定义views,为什么我要浪费时间去使用StoryBoard,我用Nibs就可以完全搞定了
Felipe Laso Marsetti
因为StoryBoard可以更好的管理你的视图,当用户在app里进入视图与返回视图,你的控制器就是一个scene,所以你可以更加可视化的看待这些,你可以清楚的知道自己会被带到那里去,自定义的view是独立的部分,你可以使用一个nib创建一个自定义的view,然后重用非常多次,同样要记住,StoryBoard允许你重用你的控制器而不用在StoryBoard里面重复的去创建这些,你甚至可以使用code来创建,你不应该被限制到这里面去,当你结合nibs去使用StoryBoard的时候会更加的美妙
Tammy Coron
我也可以通过看着项目的导航部分来管理自己的项目,这是我的第一个视图,这是我的第二个视图,等等,我需要找到一个很好的理由让我去使用StoryBoard,我同意关于StoryBoard就是未来的看法,不管我们喜不喜欢,autolayout就是未来的趋势,但是我真的很难喜欢上StoryBoard
Felipe Laso Marsetti
这里有一个很好的例子,我去年接手了一个项目,包含了五六十个ViewController,并且有一大堆的nibs,在我开始贡献代码之前我不得不去深入其中去研究这些东西,因为这个项目不是我写的,这个项目已经做了1-2年了,在刚开始的几个月我完全迷失在这个项目里面,我不得不去搞清楚这些nib文件之间的关系,这实在是非常困难
但是如果我有一个StoryBoard,那么一切都将会清晰明了,这会节省很多的时间;所以你应该至少使用StoryBoard来创建app的布局,然后再去具体的制作一些自定义的酷炫UI,采用任意一种你喜欢的方法;当你接手一个大型项目的时候StoryBoard确实会帮你大忙
红衣大叔
我参与的项目有着百万行的代码,几百个视图,我不知道我们是否需要去使用StoryBoard,不过我会去尝试一下,你说的很不错
Cesare Rocchi
额,我已经有两三年没有去做大型项目了,当我仍然记得那时候的痛苦,比如去处理各种各样的结构体,就算完全使用code来做的项目,要去处理这样那样的结构体也是一件非常困难的事情,其实我也同样是一个依赖于视觉的人,但是我并不想在Xcode上面以可视化的形式来做项目,我更喜欢在PhotoShop或者Sketch上面去做这些事情,做一个优秀的coder,你必须要知道各种东西,这是一个view这是一个button,这个是否更加的灵活等等,这就是为什么我打开Xcode的时候,我希望我的第一个视图是一个空白的模板
在我的上一个项目当中,我在一个很小的部分使用了NavigationController,但是我添加的是我自定义的一个NavigationController,这是一个自定义度很高的一个app,在这个项目里面,我完全看不出哪里可以使用StoryBoard,我都是用代码把一切搞定,非常的简单,而且可以很好的重用它们,我做的都是自定义度很高的app,唯一一个使用到的视图模板就只有tableview
红衣大叔
在我的经验看来,客户经常会给我Photoshop文件,告诉我这就是app要看起来的样子,然后你开始写代码,可能还有其他的方式,但是我觉得写代码是一种轻松的方式
Felipe Laso Marsetti
从我的经验无法知道在客户端合作开发的时候会发生什么,但是你得到一个Photoshop文件,你得到一个需求文档,然后对你说这就是app要看起来的样子,然后视图A到视图B是如何的,视图B到视图C又是如何的,把这些做出来,告诉你期限,然后拜拜
额,你使用code或者Nibs来做会很酷,但是你可以使用StoryBoard来做这些东西,就算是非常复杂的UI也可以做到;在我的公司里面,经常会有自定义UI的需求,我们可能需要用到非常多的工具,包括code甚至是PaintCode,以及其他可以生成可视化的UI的工具,Nibs或者是StoryBoard,能够使用StroyBoard我会非常的快乐,可以看到自己使用了StoryBoard完成了一个有一个的任务
Brian Moakley
我们讨论了autolayout,讨论了StoryBoard,并且现在认为它们就是未来,但是,一年之后,我们可能又会说其他的东西是未来,所以,我们应该重新思考我们的app到底是如何运作的,知道这些新技术确实很不错,可以提高我们的工作效率,但是我想,懂得如何使用code来完成所有事情是很明智的
Felipe Laso Marsetti
iOS7给了大家各种各样的机会去尝试StoryBoard,甚至是Nibs,如果你拒绝使用StoryBoard,可能因为你现在会使用一种完全不同于与以往的方式来创建app;既然你现在有一个机会来摆脱原来那么繁琐的开发过程并且尝试新的工具以及使用iOS7带来的全新UI,为什么不试一下呢?
红衣大叔
一个很好的尝试StoryBoard的理由就是使用StoryBoard可以动态调节尺寸来适应不同的设备,而autolayout将会是最好的解决方案
Cesare Rocchi
我并不喜欢StoryBoard或者是Nibs,但是我不得不去了解它们,特别是我在教学的时候,不管是教autolayout还是Nibs,我都会建议你去学习如何使用代码来做到这一切,Nibs或者是StoryBoard做了很多的工作,你信任着这些工具,但是却不知道它们背后的代码原理是什么,它们在背后做了什么事情,这很糟糕;如果你想要成为一名专业的iOS开发者,我想你最好知道各种各样的开发方法,无论是StoryBoard、Nibs还是code
Felipe Laso Marsetti
这里有一个很好的例子来说明知道code的方式很重要,有很多人经常会问一些问题就是为什么我的视图无法切换、为什么dataSource不起作用等等,知道如何使用code会很好的帮助你解决这些问题,一旦你知道如何使用code,那你使用StoryBoard或者是Nibs将会是如鱼得水,知道code确实非常的重要
Matthijs Hollemans
在Nibs或者是StoryBoard中使用autolayout是非常好理解的,使用code来写约束很简单,但是大部分时候都没有意义,但是如果你在Interface Builder里面做这些,它会告诉你怎样的约束是有意义的,它会告诉你哪里应该加约束,哪里不应该加;在Nibs或者StoryBoard里面做这些要比使用code更好
Felipe Laso Marsetti
知道code确实很有必要,大部分人在做iOS开发的时候不知道语言背后的一些原理,这可能会造成一些错误,或是内存泄露等等,同样的情况也会在使用StoryBoard或者是Nibs的时候发生,虽然使用这些工具开发起来会非常的方便,但是如果你不知道背后的代码原理,你可能会在debug的时候遇到困难
Raywenderlich
那么接下来是投票环节了,Nibs、StoryBoard、code,你会选择哪一个?
Brian Moakley
StoryBoard
Cesare Rocchi
Code
Matthijs Hollemans
StoryBoard
红衣大叔
StoryBoard
Felipe Laso Marsetti
没有必要问我
Chris Wagner
StoryBoard
Raywenderlich
我也同样是StoryBoard
Tammy Coron
我TMD要说StoryBoard吗?这样我不是很搞笑(其他人大笑);额,我非常喜欢Nibs,所以我会选择Nibs,但是如果要我在Nibs和code间做一个选择,我会选择code,因为code可以做任何事情
Raywenderlich
OK!看来各位大部分都是选择了StoryBoard,╮(╯▽╰)╭
总结
就笔者个人而言,三种方式我都尝试过,个人更偏爱使用code,当然根据不同的场景我会结合各自的优点进行开发;如上所述,StoryBoard是未来,虽然还有不够完善的地方,但是相信苹果会将其做的越来越好, StoryBorad也会逐渐展现出它的魅力
拓展阅读
代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧
http://t.cn/8kdcjt6
Storyboards vs NIB vs Code 大辩论
标签:
原文地址:http://www.cnblogs.com/fengmin/p/5801479.html