iOS_ 经验分享

数据存储:

在 iOS 开发中数据的存储可以归纳为两类:一类是存储为文件,另一类是存储为数据库.

存储为文件:

Document 目录:保存应用程序运行时生成的需要持久化的数据.应用自己的数据(比如:游戏进度存档,软件的一些个人设置等).会备份,此目录下保存的相对重要的数据.

temp 目录:程序运行时所需的临时数据,不会备份,系统管理

Library/Cachas 目录:保存从网络下载的数据(听歌,图片的缓存),程序员管理清除数据.不会备份,主要保存程序运行时生成的需要持久化的数据,一般存储体积大,不需要备份的非重要数据.

偏好设置:  Library/Preference 目录:保存通过"偏好设置"写入的数据. iOS 的 settings 应用会在该目录中查找应用的设置信息,会备份,系统管理,通常用来储存一些基本的软件配置信息,比如记住密码,自动登录等.NSUserDefaults被设计用来存储设备和应用的配置信息,它通过一个工厂方法返回默认的、也是最常用到的实例对象。这个对象中储存了系统中用户的配置信息,开发者可以通过这个实例对象对这些已有的信息进行修改,也可以按照自己的需求创建新的配置项。用来保存应用程序设置和属性、用户保存的数据。

NSKeyedArchiver(归档):把内存数据转移到闪存中进行持久化的操作称成为归档。内存存储是临时的,运行时有效的,但效率高,而闪存则是一种持久化存储,但产生I/O消耗,效率相对低.NSKeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法。前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码。缺点:归档的形式来保存数据,只能一次性归档保存以及一次性解压。所以只能针对小量数据,而且对数据操作比较笨拙,即如果想改动数据的某一小部分,还是需要解压整个数据或者归档整个数据。

存储为数据库:

SQLite3:iOS的SDK里预置了SQLite的库,开发者可以自建SQLite数据库。SQLite每次写入数据都会产生IO消耗,把数据归档到相应的文件。

SQLite擅长处理的数据类型其实与NSUserDefaults差不多,也是基础类型的小数据,只是从组织形式上不同。开发者可以以关系型数据库的方式组织数据,使用SQL DML来管理数据。 一般来说应用中的格式化的文本类数据可以存放在数据库中,尤其是类似聊天记录、Timeline等这些具有条件查询和排序需求的数据。

无论你采用系统自带的还是用的SQLight第三方库的数据存储本质都数据库存储,没必要再另外分类。数据存储稍微麻烦,并且存储的速度较慢,只有真正需要用到的地方才采用这种方式,如:聊天记录,地图地理信息查询。

Core Data(对 SQLite 的封装):

一个支持持久化的,对象图和生命周期的自动化管理方案。严格意义上说CoreData是一个管理方案,他的持久化可以通过SQLite、XML或二进制文件储存。如官方定义所说,CoreData的作用远远不止储存数据这么简单,它可以把整个应用中的对象建模并进行自动化的管理。他和微软的MFC::CArchive实现对象的持久化和反持久化一样只能支持具有序列化的函数,把对象分解成基本数据类型的持久化,如字符串,整形数字,浮点型数据,字符。由于持久化的对象数据都在一个对象中,所以他利于数据管理。所以采用CoreData存储数据就不需要采用NSUserDefaults数据存储数据了。

KVO 和 KVC

KVC:

Key-value coding,它是一种使用字符串标识符,间接访问对象属性的机制,而不是直接调用getter 和 setter方法。通常我们使用valueForKey 来替代getter 方法,setValue:forKey来代替setter方法。一般是用在 JSON 数据的序列化.字典转模型.

KVO:(是基于 KVC 实现的)

即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。

使用方法:

系统框架已经支持KVO,所以程序员在使用的时候非常简单。

1. 注册,指定被观察者的属性,

2. 实现回调方法

3. 移除观察

MVC:

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

代理和通知:

代理:一般控件用的比较多,其实也可以用block实现,如果实现的接口比较多的话,建议用代理,代理是一对一,可以有返回值.

通知:这东西是全局的,而且是同步的,如果你要全局发送消息,并且做的事情时间不长,不会阻塞线程的话,建议使用。可以一对多,多对多.

kvo:  kvo是建立在kvc的基础之上的,它通过 key path 观察对象的值,当值发生变化的时候会收到通知。比 如,你需要监听UITableview的contentoffset那么当,tableview滑动的时候,就会不停的收到contentoffset point值。你要监听某一对象的值的时候,建议使用。

实现单例的几种方式:

单例模式:保证一个类中,有且只有一个实例存在并提供一个访问点供全局访问,该实例可以被所有的程序来访问。

一般有在,在这种情况下用:

1、当要用一个类时,又要用该类中的一个实例;

2、new 来创建实例时会给程序造成资源的浪费,而且实例越多也不好控制。

3、不同的线程调用时,可能会引起不同步的现象。

+ (AccountManager *)sharedManager {

static AccountManager *sharedAccountManagerInstance = nil;

static dispatch_once_t predicate;

dispatch_once(&predicate, ^{

sharedAccountManagerInstance = [[self alloc] init];

});

return sharedAccountManagerInstance;

}

runTime 和 runLoop

runLoop:基本作用:

保持程序的持续运行

处理App中的各类事件(触摸事件、定时器事件、Selector事件)

节省CPU资源,提高程序性能:没有事件时就进行睡眠状态

内部实现:

do-while循环,在这个循环内部不断地处理各种任务(Source\Timeer\Observer)

注意点:

一个线程对应一个RunLoop(采用字典存储,线程号为key,RunLoop为value)

主线程的RunLoop默认已经启动,子线程的RunLoop需要手动启动

RunLoop只能选择一个Mode启动,如果当前Mode没有任何Source、Timer、Observer,那么就不会进入RunLoop

RunLoop的主要函数调用顺序为:CFRunLoopRun->CFRunLoopRunSpecific->__CFRunLoopRun

runTime:

Objective-C是基于C语言加入了面向对象特性消息转发机制的动态语言,这意味着它不仅需要一个编译器,还需要Runtime系统来动态创建类和对象,进行消息发送和转发。

内存管理机制:

1>堆和栈的区别

管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。

申请大小:

栈是向低地址扩展的数据结构,是一块连续的内存的区域,栈顶的地址和栈的最大容量是系统预先规定好的,能从栈获得的空间较小。

堆是向高地址扩展的数据结构,是不连续的内存区域,因为系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存,因此堆获得的空间比较灵活,也比较大。

碎片问题:

对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出

分配方式:

堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

分配效率:

栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。

APP 主流框架的搭建:

用 UITabBarController管理 UINavigationController.  然后 UINavigationController 再管理子控制器

GCD 和 NSOperation 多线程技术:

GCD是纯C语言的API,NSOperationQueue是基于GCD的OC版本封装

提供给 GCD 队列的是代码块.

GCD 暂停   dispatch_suspend

dispatch_resume   恢复一个队列

3.2> GCD仅仅支持FIFO(先进先出)队列,只可以设置队列的优先级,而NSOperationQueue中的每一个任务都可以被重新设置优先级(setQueuePriority:),从而实现不同操作的执行顺序调整

3.3> GCD不支持异步操作之间的依赖关系设置。如果某个操作的依赖另一个操作的数据,使用NSOperationQueue能够设置依赖按照正确的顺序执行操作(addDependency:)。GCD则没有内建的依赖关系支持(只能通过Barrior和同步任务手动实现)。

3.4> NSOperationQueue方便停止队列中的任务(cancelAllOperations, suspended),GCD不方便停止队列中的任务.

3.5> NSOperationQueue支持KVO,可以监测operation是否正在执行(isExecuted)、是否结束(isFinished),是否取消(isCanceld)

3.6> GCD的执行速度比NSOperationQueue快

3.7> NSOperationQueue可设置最大并发数量(节电),GCD具有dispatch_once(只执行一次,单例)和dispatch_after(延迟执行)功能

get/post 请求:

Get:

1>get一般是获取服务器上的数据

2>get请求的数据一般在url中可以看到(用户名和密码)

3>请求的数据在URL上,不安全

4>get请求的数据能够被服务器缓存

5>get请求的url一般不超过1kb

6>一般向服务器发送比较小的文件

POST:

1>post一般是往服务器提交数据,并获取服务器返回的结果

2>post方式通过请求体传输数据,效率低

3>请求的数据用户看不到,相对安全

4>post请求不能被浏览器缓存

5>post请求体没有大小的限制!

6>一般向服务器发送比较大的数据(通过请求体向服务器发送数据,没有大小限制)

线程间通信:

线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信

线程间通信的体现

1个线程传递数据给另1个线程

在1个线程中执行完特定任务后,转到另1个线程继续执行任务

线程间通信常用方法

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:

(BOOL)wait;

线程间数据共享:

资源共享

1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源

比如多个线程访问同一个对象、同一个变量、同一个文件

当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题

互斥锁的优缺点

优点:能有效防止因多线程抢夺资源造成的数据安全问题

缺点:需要消耗大量的CPU资源

互斥锁的使用前提:多条线程抢夺同一块资源

相关专业术语:线程同步,多条线程按顺序地执行任务

互斥锁,就是使用了线程同步技术

原子和非原子属性的选择

nonatomic和atomic对比

atomic:线程安全,需要消耗大量的资源

nonatomic:非线程安全,适合内存小的移动设备

iOS开发的建议

所有属性都声明为nonatomic

尽量避免多线程抢夺同一块资源

尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力

AFNetWorking实现原理:

1>实现原理

AFN的直接操作对象AFHTTPClient不同于ASI,是一个实现了NSCoding和NSCopying协议的NSObject子类。 AFHTTPClient是一个封装了一系列操作方法的“工具类”,处理请求的操作类是一系列单独的,基于NSOperation封装 的,AFURLConnectionOperation的子类。AFN的示例代码中通过一个静态方法,使用dispatch_once()的方式创建 AFHTTPClient的共享实例,这也是官方建议的使用方法。在创建AFHTTPClient的初始化方法中,创建了OperationQueue并 设置一系列参数默认值。在getPath:parameters:success:failure方法中创建NSURLRequest,以 NSURLRequest对象实例作为参数,创建一个NSOperation,并加入在初始化发方中创建的NSOperationQueue。以上操作都 是在主线程中完成的。在NSOperation的start方法中,以此前创建的NSURLRequest对象为参数创建NSURLConnection 并开启连结。

SDWebImage 实现原理:

下载图片,先判断内存中是否有图片,有就直接返回.

如果没有,根据资源定位符从沙盒中去找,有就将图片保存在内存中,以便下次读取,因为从内存中加载图片的速度要比沙盒块的多,然后将图片返回.

如果沙盒中没有图片,此时就创建一个下载操作,发送get异步请求,如果下载成功,就将图片的二进制数据写入沙盒,同时保存在内存中,并且将下载操作保存在下载操作缓存池中,目的是为了避免用户上下拉动屏幕再次显示此图片时因为网络慢的缘故多次下载同一张图片,所以要对下载操作做一个判断,之后在返回图片.

并且SDWebImage有专门的SDWebImageDecoder类处理图片,根据图片的16进制判断图片的类型,然后进行相应的处理,还有一个类是用来读取磁盘数据与将数据写入磁盘的.加载磁盘数据与性能优化做的都非常的好.

JSON 和 XML 解析:

1)解码难度: json的解码难度基本为零,xml需要考虑子节点和父节点

2)数据体积&传输速度: json相对于xml来讲,数据体积小,json的速度远远快于xml

3)数据交互: json与JavaScript的交互更加方面,更容易解析处理,更好的数据交互

4)数据描述: xml对数据描述性比较好

TCP/UDP:

TCP 和 UDP都是传输层协议.

TCP(传输控制协议)

TCP协议提供的是一种可靠的、通过“三次握手”来连接的数据传输服务,

"三次握手":

主机A向主机B发出连接请求数据包:“我想给你发数据,可以吗?”,这是第一次对话;

主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你什么时候发?”,这是第二次对话;

主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。

通过"四次拜拜"来断开连接.

TCP需要建立连接,一对一,适用于大量数据的传输,速度比较慢.

UDP(用户数据报协议)

UDP协议提供的则是一种相对来说不可靠的传输协议、无连接的数据传输服务,可以一对多

UDP协议适用于传输少量的数据,速度快.

SVN 和 git 第三方源代码管理工具:

之前公司使用的是 SVN:

检出checkout(co)

svn co ${url}

更新update(up)

svn up

提交commit(ci)

svn ci -m " 修改xxx 问题"

查看当前目录最近5 次提交记录

svn log -l 5

查看当前工作拷贝信息

svn info

查看当前未提交的文件status(st)

svn st

这个命令输出每个添加、修改、删除过的目录和文件,前面的C 表示冲突,要特别注意。linux 下也可以用svn st | grep ^C 来查看冲突项。

查看当前修改内容

svn diff

撤销当前修改,覆盖为资源库最新版本

svn revert path/filename

递归撤销当前目录修改,覆盖为资源库最新版本。注意新加的文件不会被删除,这时也可以删除工作拷贝,重新checkout

svn revert . --recursive

合并

SVN merge

视频类技术点:

系统自带:

MPMoviePlayerController:

在iOS中播放视频可以使用MPMoviePlayerController类来完成,具备一般的播放器控制功能,例如播放、暂停、停止等。但是MPMediaPlayerController自身并不是一个完整的视图控制器,如果要在UI中展示视频需要将view属性添加到界面中.

MPMoviePlayerController继承于UIViewController,默认是全屏模式展示、弹出后自动播放、作为模态窗口展示时如果点击“Done”按钮会自动退出模态窗口等

AVPlayer:

MPMoviePlayerController足够强大和复。自定义播放器的样式,使用MPMoviePlayerController就不合适了,只能用AVPlayer.

AVPlayer本身并不能显示视频,而且它也不像MPMoviePlayerController有一个view属性。如果AVPlayer要显示必须创建一个播放器层AVPlayerLayer用于展示,播放器层继承于CALayer,有了AVPlayerLayer之添加到控制器视图的layer中即可。

一般点播使用 HTTP; 直播使用RTMP 或私有协议,原因是延迟比较小,RTMP 本身也是为直播设计. (视频流传输协议)

第三方分享、登录:

苹果自带的分享:

支持的分享软件比较少, 所以一般使用第三方 SDK.

集成友盟社会化组件流程:

注册友盟账号.

申请第三方账号.

是否通过审核.

友盟后台绑定的第三方账号.

下载 SDK

集成 SDK

集成 SDK 要注意的问题:

使用第三方登录的时候需要进行签名打包,不然在新浪SSO授权、微信分享会出现异常。

微信登录需要在微信开放平台申请开发者认证获取登录权限,不然无法完成授权

集成支付宝:(集成过程中遇到的一些坑)

下载支付宝 SDK . 现在改名为"移动支付集成开发包".

Ø向支付宝申请,与支付宝签约,获得商户ID(partner)和账号ID(seller)

Ø下载相应的公钥私钥文件(加密签名用)

Ø下载支付宝SDK

Ø生成订单信息,签名加密

Ø调用支付宝客户端,由支付宝客户端跟支付宝安全服务器打交道

Ø支付完毕后,支付宝客户端会自动跳回到原来的应用程序

Ø在原来的应用程序中显示支付结果给用户看

集成支付宝可能遇到的一些问题:

1.要设置好协议头,因为集成支付宝,发送支付请求的时候需要用到.

2.可能会找不到头文件.在需要的类中导入头文件

3.导入支付宝依赖的系统框架.

推送:

上图可以分为三个阶段:

第一阶段:应用程序的服务器端把要发送的消息、目的iPhone的标识打包,发给APNS。

第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。

第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。

极光推送.

XMPP(即时通讯):

XMPP的环境配置非常的麻烦,首先要给电脑配置一个java的环境,配置玩java环境之后,还要安装数据库,一般用的是关系数据库,MYSQL 数据库安装完之后安装服务器openfire.这些装完之后还没完,还要建立数据库与openfire的连接.这些都配置完之后,在使用XMPP的时候要下载XMPPFramework.如果手动导入framework非常麻烦,比如其中拖入点a文件的时候要设置点a文件的路径为required.这样将项目换台电脑的时候不会因为找不到点a文件而报错.一般最简单的方式就是直接用cocoaspod从终端直接下载. 就会省略很多复杂的步骤. 在使用XMPP时先在application中建立长连接,因为XMPP本身就是一种协议,所以要创建一个XMPP流,用来进行实时通讯.同时把流的代理设置成application并将主机域与JID发送给服务器,在代理中验证用户密码是否正确,也在验证密码正确或者是错误的代理中处理事情.  在程序注销激活状态的时候还要断开连接,因为长连接特别的耗服务器资源,在程序激活的时候再重新建立连接.

消息推送:

设置注册的通知类型

请求授权

注册授权请求

注册远程通知

在didRegisterForRemoteNotificationForDeviceToken将deviceToken发送给服务器

在didReceiveRemotaNotification中接收远程推送的消息没有图片,此时就创建一个下载操作,发送get异步请求,如果下载成功,就将图片的二进制数据写入沙盒,同时保存在内存中,并且将下载操作保存在下载操作缓存池中,目的是为了避免用户上下拉动频幕再次显示此图片时因为网络慢的缘故多次下载同一张图片,所以要对下载操作做一个判断,之后在返回图片.并且SDWebImage有专门的SDWebImageDecoder类处理图片,根据图片的16进制判断图片的类型,然后进行相应的处理,还有一个类是用来读取磁盘数据与将数据写入磁盘的.加载磁盘数据与性能优化做的都非常的好.

访问苹果健康数据:

导入 healthKit 框架;

XMPP:

即时通讯技术-->支持用户在线实时交谈.

它是通讯协议-->用来说明数据在网络中如何传输.

基于XML且开放的可扩展通讯和表示协议(XMPP)协议

XMPP 的核心在网络上分片段发送XML的流协议.这个流协议是XMPP的即时通讯指令的传递基础,也是一个非常重要的可以被进一步利用的网络基础协议,可以说XMPP用TCP传的是XML流

XMPP 的基本结构:典型的 C/S 架构  客户端-->服务器<--客户端.这种方式是简化客户端,把大多数工作都放到服务器端进行.

ImageName:与 imageWithContentsOfFile: 区别

imageName: 会把图片缓存到内存中, 方便下次调用,适合比较小的图片,

imageContentsOfFile: 不会缓存图片,一般用在文件加载次数比较少,图片本身比较大的情况.

加密:

数据安全包括(连接通道加密) 和 (上传数据加密,算法加密, 对称加密, 非对称加密 )

1.对称性加密算法,信息接收双方都需事先知道密匙和加解密算法且其密匙是相同的,之后便是对数据进行 加解密了。2.非对称算法与之不同,发送双方A,B事先均生成一对密匙,然后A将自己的公有密匙发送给B,B将自己的公有密匙发送给A,3.如果A要给B发送消息,则先需要用B的公有密匙进行消息加密,然后发送给B端,此时B端再用自己的私有密匙进行消息解密,

B向A发送消息时为同样的道理。总而言之:公钥与私钥的作用是:用公钥加密的内容只能用私钥解密,用私钥加密的内容只能 用公钥解密。

MD5:加密后不可逆(只能加密不可解密),我们用于加密用户的登录密码

DES:对称加密(服务器和客户端公用同一个秘钥),缺点:一旦被抓包破解了秘钥,就能破解所有的传递信息

RSA:非对称加密(会生成一对秘钥(公钥和私钥)), 通过MAC终端生成两个.pem文件,再用vim打开文件,获取里面的字符串(也就是秘钥),

MD5

由于MD5加密算法具有较好的安全性,而且免费,因此该加密算法被广泛使用

主要运用在数字签名、文件完整性验证以及口令加密等方面

现在的MD5已不再是绝对安全,对此,可以对MD5稍作改进,以增加解密的难度

加盐(Salt):在明文的固定位置插入随机串,然后再进行MD5

先加密,后乱序:先对明文进行MD5,然后对加密得到的MD5串的字符进行乱序

总之宗旨就是:黑客就算攻破了数据库,也无法解密出正确的明文

RSA

iOS中的Security.framework提供了对RSA算法的支持.这种方式需要对密匙对进行处理, 根据public key生成证书, 通过private key生成p12格式的密匙.

除了Secruty.framework, 也可以将openssl库编译到iOS工程中, 这可以提供更灵活的使用方式.

base64

在代码中使用 base64加解密,  封装方法.

网络层,传输层,应用层

IP 网络层, TCP/UDP应用于传输层, HTTP/HTTPS 应用于应用层. 从本质上来讲,三者没有可比性,因为应用于不用的层面

socket则是对TCP/IP协议的封装和应用(程序员层面上)。

也可以说,TPC/IP协议是传输层协议,主要解决数据如何在网络中传输,

HTTP 是应用层协议,主要解决如何包装数据.

HTTPS 是对连接通道的加密.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • 最近一朋友正准备跳槽,就从各处搜索整理一些基础,便于朋友复习,也便于自己复习查看. 1. 回答person的ret...
    smile丽语阅读 1,718评论 0 7
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,118评论 29 470
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,166评论 11 349
  • OC的理解与特性 OC作为一门面向对象的语言,自然具有面向对象的语言特性:封装、继承、多态。它既具有静态语言的特性...
    克鲁德李阅读 444评论 0 0
  • 20170327切片和迭代 当我们使用for循环时,只要作用于一个可迭代对象,for循环就可以正常运行,而我们不太...
    田旭1阅读 235评论 0 0