摘要: 我最近翻译了Big Nerd Ranch的《iOS编程(第6版)》。我用了大半年时间,尽可能做到通顺易懂。不足之处请大家多多指正。感谢辛苦审校的丁道骏同学。 这本书得过Jolt大奖,原书在美国亚马逊书店排名iOS编程类榜首。前几版反响都不错(第5版也是我翻译的),希望第6版不会叫大家失望。 京东当当 阅读全文
posted @ 2019-08-02 16:00 fengquanwang 阅读(887) 评论(2) 推荐(0) 编辑
摘要: 经常会碰到Watch app和WatchKit extension需要访问同一个文件。比如,使用一个自定义的字体,播放多媒体文件。有两种方法完成这个任务。 设计的时候,每个包放一份文件。它们分别访问自己的文件。 给它们添加同一个共享的App Group。这样它们可以在运行时访问同一个容器了。 Wat 阅读全文
posted @ 2016-04-19 15:18 fengquanwang 阅读(407) 评论(0) 推荐(0) 编辑
摘要: 这篇文章介绍了iOS9开发相关的简介,现在发布的设备都会搭载iOS9。这篇文章也列出了详细描述新特性的文章。iPad多线程增强iOS9使用Slider Over, Split View, Picture in Picture增强了iPad上的多线程用户体验。Slide Over特性可以让用户启动第二... 阅读全文
posted @ 2015-09-17 13:50 fengquanwang 阅读(2102) 评论(0) 推荐(0) 编辑
摘要: 实现app的开始是定义storyboard场景。每个场景定义了app的一部分界面。可以为不同的尺寸自定义场景。 组装storyboard界面 WatchKit app和iOS app的布局模式不同。组装WatchKit app界面时,并不是把元素在一个空间里任意层次结构的摆放,而是把元素添加到场景, 阅读全文
posted @ 2015-05-11 15:08 fengquanwang 阅读(356) 评论(0) 推荐(0) 编辑
摘要: WatchKit extension可以使用iOS app同样的技术,但是由于他是extension,使用有些技术的时候会有限制,有些不推荐使用。下面是一些介绍以及什么时候使用什么技术: 有些需要权限的操作需要在iPhone上同意。有些特殊的技术需要用户允许,比如位置信息。在WatchKit上使用这 阅读全文
posted @ 2015-04-30 15:58 fengquanwang 阅读(391) 评论(0) 推荐(0) 编辑
摘要: WatchKit app和WatchKit extension一起实现了app的界面。当用户在Apple Watch中操作时,WatchKit app从storyboards中选择合适的场景。比如,如果用户查看glance,它就会选择glance场景。在选择场景时,WatchKit通知对应的iPho 阅读全文
posted @ 2015-04-30 13:56 fengquanwang 阅读(571) 评论(0) 推荐(0) 编辑
摘要: WatchKit app需要一个现有的iOS app。在iOS app工程中,添加一个新的WatchKit app target,它包含了WatchKit app和WatchKit extension中需要的资源。他们会和iOS app一起发布到appstore。 WatchKit app targ 阅读全文
posted @ 2015-04-29 19:07 fengquanwang 阅读(673) 评论(0) 推荐(0) 编辑
摘要: 使用Apple Watch,用户可以使用一种不显眼的方式查看信息。不用把iPhone从口袋里拿出来,就可以通过看一下手表快速获得重要信息。 作为Apple Watch的第三方app开发者,应该通过使用最直接的方式提供做重要的信息来支持简短的操作 Apple Watch和它匹配的iPhone Appl 阅读全文
posted @ 2015-04-29 17:59 fengquanwang 阅读(287) 评论(0) 推荐(0) 编辑
摘要: mac中自带了apache服务器, 如果需要在mac上使用apache服务器, 只需要配置并启动服务器即可。mac 10.10 中自带的apache版本是 2.4mac 10.9 中自带的apache版本是2.21. 启动服务器打开Terminal, 输入 sudo apachectl start ... 阅读全文
posted @ 2015-01-08 15:17 fengquanwang 阅读(879) 评论(0) 推荐(0) 编辑
摘要: 这篇文章会介绍iOS8开发相关的主要特性。App 插件通过支持插件,iOS8让我们可以系统指定的区域进行扩展,也就是为用户的特定需求提供自定义的方法。例如:可以通过App插件帮助用户分享他们的内容到社交网站。在用户安装了这个插件后,当他在App中点击分享按钮时就可以选择这个插件了。自定义的插件提供接... 阅读全文
posted @ 2014-09-29 17:32 fengquanwang 阅读(3114) 评论(0) 推荐(0) 编辑
摘要: Run loops是线程相关的一些基本东西。一个run loop是一个处理消息的循环。用来处理计划任务或者收到的事件。run loop的作用是在有事做的时候保持线程繁忙,没事的时候让线程挂起。Run loop的管理并不是完全自动的。你仍然需要设计代码来在合适的时候启动run loop来相应事件。Co... 阅读全文
posted @ 2014-08-05 16:51 fengquanwang 阅读(923) 评论(0) 推荐(0) 编辑
摘要: 线程管理iOS和OS X中每一个进程(或程序)由一个或多个线程组成。程序由一个运行main方法的线程开始,中间可以产生其他线程来执行一些指定的功能。当程序产生一个新线程后,这个线程在程序进程空间内变为一个独立的实体。每个线程有它自己的执行栈。线程可以和其他线程通讯,执行I/O操作,以及其他你想要它做... 阅读全文
posted @ 2014-07-30 15:40 fengquanwang 阅读(1319) 评论(0) 推荐(0) 编辑
摘要: 简介线程是在一个程序中并发的执行代码的方法之一。虽然有一些新的技术(operations, GCD)提供了更先进高效的并发实现,OS X和iOS同时也提供了创建和维护线程的接口。这里将要介绍线程相关的包以及如何使用他们。同时也会介绍程序中多线程代码的同步。关于线程开发多年以来,电脑的最大处理速度受制... 阅读全文
posted @ 2014-05-23 15:04 fengquanwang 阅读(462) 评论(0) 推荐(0) 编辑
摘要: 简介Objective c 语言尽可能的把决定从编译推迟到链接到运行时。只要可能,它就会动态的处理事情。这就意味着它不仅仅需要一个编译器,也需要一个运行时系统来执行变异好的代码。运行时系统就好像是Objective c 的操作系统。它让Objective c能工作。这篇文章主要讲解NSObject类... 阅读全文
posted @ 2014-05-21 16:04 fengquanwang 阅读(383) 评论(0) 推荐(0) 编辑
摘要: iOS7更新了很多引人注目的功能。用户界面完全重新设计了。iOS7为开发2D,2.5D游戏引入了全新的动画系统。加强多线程,点对点连接,以及许多其他重要的功能让iOS7成为有史以来最有意义的一次发布。这边文章总结了iOS7开发相关的特性。这个版本大操作系统可以再目前的iOS设备上运行。另外,关于关键... 阅读全文
posted @ 2014-01-20 23:42 fengquanwang 阅读(765) 评论(0) 推荐(0) 编辑
摘要: 在ActionBar上使用ActionProvider实现一个高效的友好的分享操作在Android 4.0(API等级14)上更容易了。一个ActionProvider,一旦附加到action bar的菜单上了,就会处理外观和行为上的操作,至于ShareActionProvider,你值需要提供分享intent,然后它会完成剩下的事情。注意:ShareActionProvider从API等级14以及更高版本中可用。更新菜单的声明要使用ShareActionProviders,在菜单资源文件中为相应的<item>定义android:actionProviderClass属性:1 &l 阅读全文
posted @ 2013-06-21 17:58 fengquanwang 阅读(834) 评论(0) 推荐(0) 编辑
摘要: 就象程序可以发送数据给其他程序,所以也可以接收其他程序的数据。想一下用户如何和程序交互,以及想从其他程序接收什么样类型的数据。例如,一个社交程序可能对接收其他程序的文字(比如有趣的网址)感兴趣。Google+ 程序可接收文字和单多张图片。用这个app,用户可以和容易的用Android Gallery中的相片在Google+上发布。更新Manifestintent filter会告诉系统程序会打算接收什么。就和前面讲的如何用ACTION_SEND创建intent相似,创建intent filter来接收带有这个操作的intent。在manifest中用<intent-filter>元 阅读全文
posted @ 2013-06-21 16:59 fengquanwang 阅读(3840) 评论(1) 推荐(1) 编辑
摘要: 创建一个intent时,必须要指定intent将要触发的操作。Android定义了很多操作,包括ACTION_SEND,就象可以猜到的一样,表示intent是把数据从一个activity发送给另一个,就算是跨界。要发送数据给其他activity,值需要指定数据和它的类型,系统会识别可兼容的接收activity然后展示给用户(如果有多个选择)或者立刻启动activity(如果只有一个选择)。相似的,也可以通过在manifest中设置来注册你的activity可以接收其他程序的哪些数据类型。用intent在程序之间发送和接收数据是最常用的社会化分享。Intent让用户可以快速的分享信息并且容易的使 阅读全文
posted @ 2013-06-21 16:13 fengquanwang 阅读(4553) 评论(0) 推荐(0) 编辑
摘要: Android程序一个很重要地特性是他们可以相互通讯和交互。为什么要重新开发那些不是你程序的核心而且其他程序已经有的功能呢?这里将要介绍一些使用Intent API和ActionProvider对象来实现的常用的程序之间发送和接收内容的方法。课程给其他APP发送内容学习如何设置程序来用Intent给其他程序发送字符串和二进制数据。接收其他APP的内容学习如何设置程序来从Intent中接收字符串和二进制数据。添加一个简单的分享操作学习如何在action bar中添加分享行为。 阅读全文
posted @ 2013-06-19 17:39 fengquanwang 阅读(372) 评论(0) 推荐(0) 编辑
摘要: 前面的两篇文章主要讲了一个方面:从app中启动其他app。但是如果你的app可以处理对其他app有用的操作,你的app也应该响应其他app的操作请求。例如,如果你创建了一个社交app可以分享信息和图片给用户的朋友,支持ACTION_SENDintent,让用户在其他app初始化分享操作然后启动你的app来执行,是一件很有趣的事情。为了其他app可以启动activity,应该在manifest文件中添加<intent-filter>元素和响应的<activity>元素。当app安装到设备上后,系统会识别intent filter然后把信息加到一个所有安装的app都支持的全 阅读全文
posted @ 2013-06-19 17:18 fengquanwang 阅读(5308) 评论(0) 推荐(0) 编辑
摘要: 启用另一个activity不一定是单向的。也可以启用另一个activity并且获得返回值。要获得返回值的话,调用startActivityForResult()(而不是startActivity())。比如,app可以打开相机然后接收一张照片作为返回值。或者,为了让用户选择一个联系人可以让用户启动联系人相关app,然后收到联系人详情作为结果。当然,这个响应的activity必须设计为有返回值的。当返回的时候,它用Intent对象作为返回值。activity会在onActivityResult()回调方法中收到。注意:用明确的和模糊的intent都可以使用startActivityForResu 阅读全文
posted @ 2013-06-19 14:14 fengquanwang 阅读(3737) 评论(0) 推荐(0) 编辑
摘要: Android的重要功能之一就是app可以根据要执行的操作让用户启动另外一个app。例如,app有一个商业地址然后想要在地图上显示,并不需要在app中加一个显示地图的activity,可以直接用Intent创建一个要显示地址的请求,Android系统会启动一个可以显示地图的app。就像以前讲到的,可以使用Intent在app中的activity之间切换。基本上是使用的明确的Intent,也就是明确定义了要启动的组件的类名。然而,当要启动另外一个app来执行操作时,比如展示地图,就要使用模糊的Intent了。这里将要介绍如何为特定的操作创建模糊的Intent,和如何使用它来启动其他app中的ac 阅读全文
posted @ 2013-06-18 23:30 fengquanwang 阅读(871) 评论(0) 推荐(0) 编辑
摘要: 一个Androidapp通常有好几个activity。每个activity显示一个可以让用户执行特殊操作(例如看地图,照相等)的界面。要让用户从一个activity切换到另一个activity,app必须使用Intent来定义app打算做什么。当用startActivity()把Intent传递给系统时,系统用Intent来识别和开始合适的app组件。使用Intent甚至可以让app启动其他app中的activity。一个Intent可以是明确的,为了开始一个特定的组件(一个特定的Activity实例),也可以是不明确的,为了开始任何可以处理将要执行动作的组件(比如照一张照片)。这里将要介绍如 阅读全文
posted @ 2013-06-18 23:14 fengquanwang 阅读(685) 评论(0) 推荐(0) 编辑
摘要: 对于重复的或结构化的数据,保存到数据库中是很好的选择,比如联系人信息。这里假设你对SQL数据库大体上了解然后帮助你学习Android上的SQLite数据库。在Android数据库上需要用到的API可以在android.database.sqlite包中找到。定义Schema和ContractSQL数据库中一个主要的准测是schema:一个正式的数据库如何组织的声明。这个schema和用来创建数据库的SQL声明是对应的。你会发现创建一个同样的类很有用,叫做contract类,它明确指名了schema在系统中的设计和自己记录的方式。contract类是一个常量(URI的名字,表,列)的容器,con 阅读全文
posted @ 2013-06-18 22:52 fengquanwang 阅读(3217) 评论(0) 推荐(1) 编辑
摘要: Android使用的文件系统和其他平台的基本磁盘的文件系统很相似。这里将要介绍如何使用FileAPI在Android文件系统中读写文件。File对象适合按顺序读写大量的数据。例如,适合图片文件或者其他在网络上交换的东西。这里将要展示基本的文件相关的任务。这里假设你熟悉基本的Linux文件系统和标准的java.io中的输入输出。选择内部或外部存储所有的Android设备由两种存储位置:内部存储和外部存储。这些名字来源于早期的Android,大多数提供内置的不可拆解的存储器(internalstorage),加上一个可移除的存储介质比如microSD卡(externalstorage)。有些设备把 阅读全文
posted @ 2013-06-18 22:45 fengquanwang 阅读(1133) 评论(0) 推荐(0) 编辑
摘要: 如果你有少量的键值数据需要存储,可以使用SharedPreferencesAPI。SharedPreferences对象指向一个包含键值对的文件并且提供了一些简单的方法来读取它们。每个SharedPreferences文件由framework管理而且可以时私有的或者共享的。这里将要介绍如何使用SharedPreferencesAPI来存储和找回数据注意:SharedPreferencesAPI是用来读写键值对的,所以不要和PreferenceAPI弄混了。Perference是用来为app设置创建用户界面的(虽然它们也用SharedPreferences来实现app设置的数据存储)。关于Pre 阅读全文
posted @ 2013-06-18 22:36 fengquanwang 阅读(3060) 评论(0) 推荐(0) 编辑
摘要: 大部分Androidapp需要保存数据,就算只是在onPause()时保存app的状态信息来保证用户进度不丢失。大部分app需要保存用户设置,有些程序可能需要管理文件和数据库中的大量数据。这里将要介绍Android中主要的存储数据的方法,包括:在文件中存储简单的键值对数据类型。在Android文件系统中存储任意的文件。使用SQLite使用和管理数据库课程:存储键值对学习如何用键值对的形式存储少量的信息存储文件学习存储一个基本的文件,比如存储一长串需要按顺序读取的数据在SQL数据库中存储数据学习如何使用SQLite数据库读写结构数据 阅读全文
posted @ 2013-06-18 22:31 fengquanwang 阅读(211) 评论(0) 推荐(0) 编辑
摘要: 为了重用FragmentUI组件,应该把每个都设计为它自有的模块组件并且有自己的布局和行为。一旦定义了这些可重用的Fragment,你可以把它们和一个activity关联然后和程序的逻辑一起实现上层的UI。经常会用到一个Fragment需要和另一个通讯,比如根据用户事件来交换内容。所有的fragment和fragment只见的通讯是通过相关的activity实现的。两个fragment不能直接通讯。定义一个接口为了运行fragment和它的activity通讯,你可以在fragment类中定义一个接口然后在activity中实现它。fragment在onAttach()生命周期方法中捕获到接口 阅读全文
posted @ 2013-06-18 17:09 fengquanwang 阅读(457) 评论(0) 推荐(0) 编辑
摘要: 当设计程序来支持各种不一样的屏幕尺寸时,可以在不同的布局中重用fragment来根据可用的屏幕大小来优化用户体验。例如,在手机上可能使用一个fragment来使用单窗口用户体验比较合适。但是,你可能想在平板上边靠边的设置两个fragment因为有更宽的屏幕向用户展示更多信息。图1.两个fragment,同一个activity在不同的屏幕大小上的不同展现形式。在大屏幕上,两个fragment边靠边,但是在手机设备上,一次只显示一个fragment因此fragment在用户切换的时候替换另一个。为了创建动态的体验,FragmentManager类提供了方法可以在运行时添加,删除,替换activit 阅读全文
posted @ 2013-06-18 17:04 fengquanwang 阅读(3766) 评论(0) 推荐(0) 编辑
摘要: 你可以把fragment当作activity中的一个活动模块,它有自己的生命周期,自己接收输入消息,可以在activity运行的时候添加和删除(就像可以在其他activity中重用的"子activity")。这里会讲述如何用SupportLibrary来扩展Fragment类这样app可以在老版本的系统上运行,就算是Android1.6。注意:如果你因为什么原因把最低APIlevel调整为11或者更高,你就不需要使用SupportLibrary了,可以直接使用Fragment类只待的framework和相关API。只是要意识到这里将要介绍的是使用SupportLibrary 阅读全文
posted @ 2013-06-18 16:56 fengquanwang 阅读(1305) 评论(0) 推荐(0) 编辑
摘要: AndroidSupportLibrary提供了一个带有API库的JAR文件来让你可以在使用最新的AndroidAPI的同时也也已在早期版本的Android上运行。例如,Support Library提供了一个版本的FragmentAPI让你可以使用Android1.6(APIlevel4)以及更高版本。这里将要展示如何设置app来使用SupportLibrary和使用fragments创建动态的appUI。设置带有SupportLibrary的工程为了设置工程:使用SDKManager下载AndroidSupportpackage。在Android工程的根目录下创建libs文件夹找到要使用的 阅读全文
posted @ 2013-06-18 16:52 fengquanwang 阅读(686) 评论(0) 推荐(0) 编辑
摘要: 要在Android上实现动态的多窗口的用户交互界面,需要把UI组建和activity放到modules中,这样才能划进划出activity。可是使用Fragment类来创建modules,它就像一个嵌套的activity它们可以定义自己的布局和管理自己的生命周期。当一个fragment指定它自己的布局后,它可以在activity中和其他的fragment组合来为不同的屏幕大小修改布局(小屏幕可能一次显示一个fragment,但是大屏幕可以一次显示两个或更多)。这里将要展示如何用fragments创造动态的用户体验和为不同屏幕大小的设备优化app的用户体验,这些支持很老的版本一直到运行Andro 阅读全文
posted @ 2013-06-18 16:49 fengquanwang 阅读(272) 评论(0) 推荐(0) 编辑
摘要: 在最新版本的Android为app提供很好的新API时,也应该继续支持旧版本的Android直到大部分设备已经更新了。这里将要介绍如何在使用最新API带来的优点的同时继续支持老版本。DashboardforPlatformVersions会经常更新来展示每个Android版本的活跃设备,是根据访问GooglePlayStore的设备数量统计出来的。整体上,在app支持支持最新的版本同时,支持90%以上的活跃设备是一个很好的体验。提示:为了在多个Android版本中提供最好的特性和功能,应该在app中使用AndroidSupportLibrary,它可以让你在旧版本上可以使用多个最新版本的API 阅读全文
posted @ 2013-06-18 16:38 fengquanwang 阅读(696) 评论(0) 推荐(0) 编辑
摘要: Android整体上按照两大类来分类设备屏幕:尺寸和分辨率。app在设备上运行应该考虑大小和分辨率。同样的,你应该包含不同的资源来让app适应不同的屏幕大小和分辨率。整体上有四种尺寸:小的,正常的,大的,超级大的和四种分辨率:低分辨率(ldpi),中分辨率(mdpi),高分辨率(hdpi),超高分辨率(xhdpi)为了声明不同屏幕的不同的布局和突变,你需要把不同的资源放在不同的文件夹下,和处理不同语言的方法一样。同样要注意到在考虑屏幕大小时也要考虑屏幕的方向(横竖屏),所以很多app需要在每个方向上调整布局来来优化用户体验。创建不同的布局为了在不同的屏幕尺寸上优化用户体验,你应该为每个你要支持 阅读全文
posted @ 2013-06-18 16:30 fengquanwang 阅读(576) 评论(0) 推荐(0) 编辑
摘要: 把app的字符串放到另外一个文件中是一个好习惯。Android用android工程中的资源文件夹让这件事变的很简单。如果使用AndroidSDKTools创建工程,这个工具会在工程的根目录下创建res/文件夹。在res/文件夹下面有各种类型的资源的字文件夹。有一些默认的文件比如res/values/string.xml,它是用来存放字符串的。创建本地文件夹和字符串文件为了支持更多语言,在res/中创建其他的values扩展的文件夹,就是就是在文件夹名后加上一个横线和国家的ISO码。例如,values-es/就是包含代码为"es"的资源文件夹。Android在运行时根据设置加 阅读全文
posted @ 2013-06-18 16:26 fengquanwang 阅读(577) 评论(0) 推荐(0) 编辑
摘要: 世界上有各种不一样形状和大小的Android设备。由于有各种不同类型的设备,你的app可能在各种设备上运行。为了在Android上尽可能的成功,你的app需要使配各种不同的设备。最重要的几点需要考虑的是不同的语言,不同的屏幕大小和不同的Android平台版本。这里将要讲如何用使用平台基本的功能来选择不同的资源和其他特性,这样你的app可以给不同的Android设备提供一致的用户体验,仅仅使用一个简单的程序包(APK)。课程:支持不同的语言学习用不同的字符串资源来支持不同的语言支持不同的屏幕学习为不同的屏幕大小和分辨率优化用户体验支持不同的平台版本学习如何在使用新版本的API的同时支持老版本的A 阅读全文
posted @ 2013-06-18 16:24 fengquanwang 阅读(202) 评论(0) 推荐(0) 编辑
摘要: 按照正常的app行为,很少情况下activity会销毁,只有当用户点击了返回按钮或者activity通过调用finish()发出销毁信号。系统也有可能销毁activity如果它是停止状态并且很久没有使用,或者前台的activity需要更多的资源时系统不得不关掉后台进程来获得内存。当activity销毁了因为用户点击的返回按钮或者自己结束,系统认为这个activity永远的消失了因为这个activity实例不再需要了。但是,如果时因为系统原因销毁了activity(不是app正常的行为),这个时候虽然activity实例不存在了,但是系统会记住它存在过,也就是说当用户回到这个activity时, 阅读全文
posted @ 2013-06-18 15:28 fengquanwang 阅读(1950) 评论(0) 推荐(0) 编辑
摘要: 停止和重启activity在activity的生命周期中很重要,它能让用户感觉你的app总是激活的而且不会丢失他们的进度。activity在下面的这些情况会停止和重启:用户打开常用app窗口然后从你的app切换到其他app。你的app中的activity现在就在后台了而且停止了。如果用户从主屏的启动图标或者最近使用的app窗口返回到你的app,这个activity就会重启。用户在你的程序中执行了一个操作来启动一个新的activity。当前的activity在第二个activity创建时就会停止了。如果用户点击了返回按钮,第一个activity就重启了。用户在使用你的app时接到电话。注意:因为 阅读全文
posted @ 2013-06-18 15:27 fengquanwang 阅读(5142) 评论(0) 推荐(0) 编辑
摘要: 在正常的使用app时,前台的activity有时候会被可见的组件阻塞导致activity暂停。比如,当打开一个半透明的activity(就像打开了一个对话框),之前的activity就会暂停。只要activity仍然部分可见但是没有获得焦点,它会保持在paused状态。但是,一旦一个activity完全被阻塞并且不可见,它就会到Stopped状态(后面会讨论这个)。当activity进入Paused状态,系统会调用activity的onPause()方法,可以让你停止那些不需要继续运行的动作(比如视频)和保存那些需要永久保存的信息来防止用户后面离开的app造成信息丢失。如果用户从Paused状 阅读全文
posted @ 2013-06-18 15:16 fengquanwang 阅读(2548) 评论(0) 推荐(0) 编辑
摘要: 很多程序都是从main()方法开始启动的,和其他程序不同,android是在activity生命周期的特定状态的特定回调方法中初始化代码的。activity启动和销毁的时候都用很多回调方法。这里将要对生命周期中大多数重要的方法进行一个总体介绍以及如何处理生命周期中的第一个回调方法(这个回调方法创建了一个新的activity实例)。理解生命周期回调方法在activity的生命周期中,系统按照像金字塔的顺序调用了一系列的生命周期回调方法。也就是说,activity生命周期中的每个状态就像金字塔的一级。当系统创建一个信的activity实例时,回调方法把activity的状态一步一步调整到顶。金字塔 阅读全文
posted @ 2013-06-18 14:33 fengquanwang 阅读(1962) 评论(0) 推荐(0) 编辑