iOS 关于copy与mutableCopy浅析

君不见,高堂明镜悲白发,朝如青丝暮成雪

前记

最近在项目中,用到了关于copy的问题,当我对自己定义的模型进行拷贝的时候,居然没有实现想要的深拷贝,于是出了点小问题,让我有点小郁闷,所以决定好好深入研究下copymutableCopyNSDictionaryNSArraymodel之间的小事~

copy 、mutableCopy

先来看看这两个的区别吧

在分析区别之前,我们先上一段简单的代码

    //非集合类测试copy 和 mutablecopy
    NSString *string = @"abc";
    NSString *copyString = [string copy];
    //mutableCopy 后位动态string
    NSString *mutableCopyString = [string mutableCopy];
    
    NSString *mutableCopy_copy_String = [mutableCopyString copy];
    NSMutableString *mutableCopy_mutable_copy_String = [mutableCopyString mutableCopy];
    
    NSLog(@" 打印信息:%p---%p---%p---%p---%p",string,copyString,mutableCopyString,mutableCopy_copy_String,mutableCopy_mutable_copy_String);
    
    
    //集合类型测试copy 和 mutablecopy
    NSDictionary *_dic = @{@"key1":@"abc",@"key2":@"cde"};
    NSDictionary *copyDic = [_dic copy];

    NSMutableDictionary *mutableCopyDic = [_dic mutableCopy];
    [mutableCopyDic setValue:@"efg" forKey:@"key3"];
    
    NSMutableDictionary *mutableCopy_copy_Dic = [mutableCopyDic copy];
    NSMutableDictionary *mutableCopy_mutableCopy_Dic = [mutableCopyDic mutableCopy];
    
    NSLog(@" 打印信息字典拷贝:%p---%p---%p---%p---%p",_dic,copyDic,mutableCopyDic,mutableCopy_copy_Dic,mutableCopy_mutableCopy_Dic);
    
    
    //打印结果
    2017-08-17 15:06:33.277 GLDeepCopy[27242:8168435]  打印信息:0x10b30c0e8---0x10b30c0e8---0x608000074e00---0xa000000006362613---0x608000074e40    
    2017-08-17 15:06:33.278 GLDeepCopy[27242:8168435]  打印信息字典拷贝:0x600000072800---0x600000072800---0x60000005c8c0---0x600000072840---0x60000005cb30

顺便插个图片

copy.png
  • copy:对我们的对象进行拷贝,返回一个非动态的对象
  • mutableCopy:对我们的对象进行拷贝,返回一个动态的对象

通过上图,我们可以看到,虽然我们用的是NSString来接收[string mutableCopy],但是实际上得到的却是一个NSMutableString类型的对象,这里不得不说一个比较严重的问题,就是如果我们在定义一个动态类型为@property (nonatomic,copy)属性后,一定不能执行copy操作,否则在你执行修改动态类型内容的时候,一定会crash,因为当你copy后,你的动态类型已经变成了一个不可变类型

下面我们来看上面贴的代码,从代码分析,我们可以看到,非集合类型和集合类型中的非动态类型,在copy后,地址还是一样的,没有变化,而除此之外,地址都发生了变化,我们可以得到下面的结论

  • 非集合类型和集合类型非动态类型在copy后,执行的是浅拷贝(即对指针进行拷贝)
  • 非集合类型和集合类型非动态类型在mutableCopy后,执行的是深拷贝(即对对象进行拷贝),且返回动态类型
  • 非集合类型和集合类型动态类型在copy后,执行的是深拷贝
  • 非集合类型和集合类型动态类型在mutableCopy后,执行的是深拷贝,且返回动态类型

上面的结论也不是那么准确,怎么说呢?容我慢慢分析

对于此处的深拷贝,我想大家一定想的是完完全全的拷贝吧,是的,我一开始也是这么想的,但是有没有想过测试下,当我们的集合有很多层的情况呢?下面就举个例子来说明吧

代码走起

@interface PersonModel : NSObject<NSCopying>

@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) NSUInteger age;

@end

@implementation PersonModel
- (id)copyWithZone:(NSZone *)zone{
    PersonModel *copy = [[PersonModel alloc] init];
    
    if (copy) {
        
        copy.name = [self.name copyWithZone:zone];
        copy.age = self.age;
        copy.array = [self.array copyWithZone:zone];
    }
    return copy;
}

@end



{
    //测试加入数组中  对数组进行拷贝
    PersonModel *new_PersonModel = [[PersonModel alloc] init];
    new_PersonModel.name = @"gaogaogao";
    new_PersonModel.age = 20;
    
    NSLog(@" 打印信息修改后 personModel :%@\n new_PersonModel:%@",personModel,new_PersonModel);
    
    
    NSArray *array = [NSArray arrayWithObject:new_PersonModel];
    NSArray *copyArray = [array copy];
    NSMutableArray *mutableCopyArray = [array mutableCopy];
    
    NSLog(@" 打印信息array:%p+%@\ncopyArray:%p+%@\nmutableCopyArray:%p+%@",array,array,copyArray,copyArray,mutableCopyArray,mutableCopyArray);
    
    //修改数组中的内容
    PersonModel *personModel_array = array[0];
    personModel_array.name = @"gao_array";
    personModel_array.age = 24;

    
    NSLog(@" 打印信息修改后array:%p+%@\ncopyArray:%p+%@\nmutableCopyArray:%p+%@",array,array,copyArray,copyArray,mutableCopyArray,mutableCopyArray);
    
}

//打印结果
2017-08-17 15:31:31.136 GLDeepCopy[27447:8197824]  打印信息array:0x608000017590+(
    "{\n    age = 20;\n    name = gaogaogao;\n}"
)
copyArray:0x608000017590+(
    "{\n    age = 20;\n    name = gaogaogao;\n}"
)
mutableCopyArray:0x608000243570+(
    "{\n    age = 20;\n    name = gaogaogao;\n}"
)
2017-08-17 15:31:31.164 GLDeepCopy[27447:8197824]  打印信息修改后array:0x608000017590+(
    "{\n    age = 24;\n    name = \"gao_array\";\n}"
)
copyArray:0x608000017590+(
    "{\n    age = 24;\n    name = \"gao_array\";\n}"
)
mutableCopyArray:0x608000243570+(
    "{\n    age = 24;\n    name = \"gao_array\";\n}"
)

从上面的打印信息中,我们看mutableCopyArray的地址,可以发现,地址是发生了改变的,说明我们现在是执行了深拷贝的,但是看打印信息修改后array这个位置,你会发现,后面的内容在修改后,居然变成一样的了,但是我们明明修改的是array[0]中的对象的值啊,什么鬼👻,是不是有点郁闷,那么下面我修改下打印信息,再来看看

 
 NSLog(@" 打印信息array:%p+%@ + %p\ncopyArray:%p+%@ + %p\nmutableCopyArray:%p+%@ + %p",array,array,array[0],copyArray,copyArray,copyArray[0],mutableCopyArray,mutableCopyArray,mutableCopyArray[0]);
 
 //打印信息
 2017-08-17 15:43:51.018 GLDeepCopy[27521:8211644]  打印信息array:0x6080000089f0+(
    "{\n    age = 20;\n    name = gaogaogao;\n}"
) + 0x6000000352e0
copyArray:0x6080000089f0+(
    "{\n    age = 20;\n    name = gaogaogao;\n}"
) + 0x6000000352e0
mutableCopyArray:0x60800005bdb0+(
    "{\n    age = 20;\n    name = gaogaogao;\n}"
) + 0x6000000352e0

是的,可以看到,三个数组里面的对象是同一个对象,也就是,数组虽然进行了深拷贝,但是并没有对里面的内容进行深拷贝,而是执行的指针拷贝,瞬间有种懵逼的感觉,特么搞了这么久,还是不能执行完全的深拷贝。所以,上面我们总结的4点中关于集合类型深拷贝不能算是真正意义上的深拷贝,只能说是一种单层的深拷贝,即至少有一层是执行了深拷贝的,但是在实际中,我们往往需要的是完完全全的完全深拷贝,那么针对集合类型,我们又该怎么来实现完全深拷贝呢?

集合的完全深拷贝

关于集合的完全深拷贝,这里有两种方法

  • 通过归档的方式来实现(后面会讲到)
  • 通过使用集合自带的方法来实现(并不完美)

先来讲讲 这个并不完美的方法吧

以上面的例子来将,我们可以使用NSArray中的

- (instancetype)initWithArray:(NSArray<ObjectType> *)array copyItems:(BOOL)flag;

flag参数设置为YES的时候,集合里的每个对象都会去执行copyWithZone方法,当然这就必须要求我们的对象必须遵循 NSCopying协议,并且实现copyWithZone方法,此时对象就会被深复制到新的集合。如果对象没有遵循 NSCopying 协议,而用这种方法进行深拷贝,就会在运行时出错

来实现,当然NSDictionaryNSSet也有对应的方法

- (instancetype)initWithDictionary:(NSDictionary<KeyType, ObjectType> *)otherDictionary copyItems:(BOOL)flag;
- (instancetype)initWithSet:(NSSet<ObjectType> *)set copyItems:(BOOL)flag;

先看修改后的

{
  //测试加入数组中  对数组进行拷贝
    PersonModel *new_PersonModel = [[PersonModel alloc] init];
    new_PersonModel.name = @"gaogaogao";
    new_PersonModel.age = 20;
    
    NSLog(@" 打印信息修改后 personModel :%@\n new_PersonModel:%@",personModel,new_PersonModel);
    
    
    NSArray *array = [NSArray arrayWithObject:new_PersonModel];
    NSArray *copyArray = [array copy];
    NSMutableArray *mutableCopyArray = [[NSMutableArray alloc] initWithArray:array copyItems:YES];//[array mutableCopy];
    
    NSLog(@" 打印信息array:%p+%@ + %p\ncopyArray:%p+%@ + %p\nmutableCopyArray:%p+%@ + %p",array,array,array[0],copyArray,copyArray,copyArray[0],mutableCopyArray,mutableCopyArray,mutableCopyArray[0]);
    
    //修改数组中的内容
    PersonModel *personModel_array = array[0];
    personModel_array.name = @"gao_array";
    personModel_array.age = 24;

    NSLog(@" 打印信息修改后array:%p+%@\ncopyArray:%p+%@\nmutableCopyArray:%p+%@",array,array,copyArray,copyArray,mutableCopyArray,mutableCopyArray);

}

//打印结果
2017-08-17 16:03:48.954 GLDeepCopy[27694:8234722]  打印信息array:0x6080000030f0+(
    "{\n    age = 20;\n    name = gaogaogao;\n}"
) + 0x6080000284c0
copyArray:0x6080000030f0+(
    "{\n    age = 20;\n    name = gaogaogao;\n}"
) + 0x6080000284c0
mutableCopyArray:0x60800004cae0+(
    "{\n    age = 20;\n    name = gaogaogao;\n}"
) + 0x608000028420
2017-08-17 16:03:48.955 GLDeepCopy[27694:8234722]  打印信息修改后array:0x6080000030f0+(
    "{\n    age = 24;\n    name = \"gao_array\";\n}"
)
copyArray:0x6080000030f0+(
    "{\n    age = 24;\n    name = \"gao_array\";\n}"
)
mutableCopyArray:0x60800004cae0+(
    "{\n    age = 20;\n    name = gaogaogao;\n}"
)

从上面的结果,我们可以看出,最终实现了我们想要的效果,对数组实现了完全深拷贝,从这里看上去,还是挺完美的嘛,然而在实际中,你知道的,肯定不止这么多层,下面我们再改造下,在PersonModel中增加一个array,并且新增一个类Anima

@interface Anima : NSObject<NSCopying>

@property (nonatomic,copy) NSString *address;

@end

@implementation Anima

- (id)copyWithZone:(NSZone *)zone{
    Anima *copy = [[Anima alloc] init];
    
    if (copy) {
        
        copy.address = [self.address copyWithZone:zone];
    }
    return copy;
}


@end

@interface PersonModel : NSObject<NSCopying,NSMutableCopying>

@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) NSUInteger age;

@property (nonatomic,strong) NSMutableArray *array;

@end
.
.
.

//实现部分
    //测试加入数组中  对数组进行拷贝
    PersonModel *new_PersonModel = [[PersonModel alloc] init];
    new_PersonModel.name = @"gaogaogao";
    new_PersonModel.age = 20;
    Anima *anima = [[Anima alloc] init];
    anima.address = @"成都";
    new_PersonModel.array = [NSMutableArray arrayWithObject:anima];
        
    NSArray *array = [NSArray arrayWithObject:new_PersonModel];
    NSArray *copyArray = [array copy];
    NSMutableArray *mutableCopyArray = [[NSMutableArray alloc] initWithArray:array copyItems:YES];//[array mutableCopy];//
    
    NSLog(@" 打印信息array:%p+%@ + %p\ncopyArray:%p+%@ + %p\nmutableCopyArray:%p+%@ + %p",array,array,array[0],copyArray,copyArray,copyArray[0],mutableCopyArray,mutableCopyArray,mutableCopyArray[0]);
    
    
    
    //修改数组中的内容
    PersonModel *personModel_array = array[0];
    personModel_array.name = @"gao_修改";
    personModel_array.age = 24;
    
    Anima *anima_model = personModel_array.array[0];
    anima_model.address = @"阆中";
    
    //获取深拷贝数组中的model中数组中的model
    PersonModel *personModel_mutable_copy_array = mutableCopyArray[0];
    Anima *anima_model_mutable_copy = personModel_mutable_copy_array.array[0];
    
    NSLog(@" 打印信息获取深拷贝数组中的model中数组中的model地址:%p ++ %p",anima_model,anima_model_mutable_copy);
    
    
    NSLog(@" 打印信息修改后array:%p+%@\ncopyArray:%p+%@\nmutableCopyArray:%p+%@",array,array,copyArray,copyArray,mutableCopyArray,mutableCopyArray);
    
    //打印信息 截取部分说明
    2017-08-18 15:27:32.324 GLDeepCopy[69373:9095757]  打印信息获取深拷贝数组中的model中数组中的model地址:0x608000013100 ++ 0x608000013100

从上面的结果分析,当层次一多,该方法也并不能完成我们想要的完全拷贝,那么我们除了用归档的方式,难道就没有其他方式了么?答案肯定是 还有的,可以这么设想一下,集合无外乎就是装了很多东西,既然是这样,我们何必不针对集合里面的内容层层进行深拷贝呢?是的,我们可以通过遍历的方式来进行,为了方便使用,可以新建一个Category,于是乎就有了下面的代码,我们先以NSArray为例

#import <Foundation/Foundation.h>

@interface NSArray (GLDeepCopy)


/**
 返回当前类型

 @return 返回
 */
- (instancetype)GLDeepCopy;

@end


#import "NSArray+GLDeepCopy.h"

@implementation NSArray (GLDeepCopy)

- (instancetype)GLDeepCopy
{
    NSMutableArray *resultMutableArray = [[NSMutableArray alloc] initWithCapacity:self.count];
    
    for (id object in self) {
        
        //定义一个id类型来接收拷贝后的
        id copyObject = nil;
        
        //如果该对象有该方法 
        if ([object respondsToSelector:@selector(GLDeepCopy)]) {
            copyObject = [object GLDeepCopy];
        //判断该对象是否实现了NSCopying 协议的方法  如果是 则进行copy
        }else if ([object conformsToProtocol:@protocol(NSCopying)]){
            copyObject = [object copy];
        }else if ([object conformsToProtocol:@protocol(NSMutableCopying)]){
            copyObject = [object mutableCopy];
        }else{
            copyObject = object;
        }
        
        [resultMutableArray addObject:copyObject];
    }
    
    if ([self isKindOfClass:[NSArray class]]) {
        return [NSArray arrayWithArray:resultMutableArray];
    }else{
        return resultMutableArray;
    }
}

@end

在上面方法中,我们通过遍历数组中的内容来进行循环拷贝,[object respondsToSelector:@selector(GLDeepCopy)],这一句是如果我们的对象实现了该方法,我们就去调用,比如当前对象是数组,字典,NSSet或者是自定义数据模型,针对自定义数据模型,如果包含集合类型,而且又需要进行完全拷贝的时候,最好实现GLDeepCopy方法,后面有例子。如果没有集合类型,但是需要完全拷贝的话,就可以通过实现NSCopying或者NSMutableCopying协议来实现。

#import <Foundation/Foundation.h>

@interface PersonModel : NSObject<NSCopying,NSMutableCopying>

@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) NSUInteger age;

@property (nonatomic,strong) NSMutableArray *array;

@end

#import "PersonModel.h"
#import "NSArray+GLDeepCopy.h"
#import <objc/runtime.h>

@interface PersonModel()


@end

@implementation PersonModel


/**
 描述信息
 
 @return 返回描述信息  利于我们在debug 的时候方便查看
 */
- (NSString *)description
{
    return [NSString stringWithFormat:@"%@",[self getObjectData:self]];
}


#pragma mark == Copying协议
- (id)copyWithZone:(NSZone *)zone{
    PersonModel *copy = [[PersonModel alloc] init];
    
    if (copy) {
        
        copy.name = [self.name copyWithZone:zone];
        copy.age = self.age;
        copy.array = [self.array copyWithZone:zone];
    }
    return copy;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
    PersonModel *copy = [[PersonModel alloc] init];
    
    if (copy) {
        
        copy.name = [self.name mutableCopyWithZone:zone];
        copy.age = self.age;
        copy.array = [self.array mutableCopyWithZone:zone];
    }
    return copy;
}


#pragma mark == 深拷贝 
//(如果没有集合类型,可以不用执行)
- (id)GLDeepCopy
{
    PersonModel *personModel = [[PersonModel alloc] init];
    personModel.age = self.age;
    personModel.name = [self.name copy];
    personModel.array = [self.array GLDeepCopy];
    
    return personModel;
}

#pragma mark == 转换

/**
 将对象转为NSDictionary
 
 @param obj 对象
 @return 返回的NSDictionary
 */
- (NSDictionary*)getObjectData:(id)obj
{
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    unsigned int propsCount;
    objc_property_t *props = class_copyPropertyList([obj class], &propsCount);
    for(int i = 0;i < propsCount; i++)
    {
        objc_property_t prop = props[i];
        
        NSString *propName = [NSString stringWithUTF8String:property_getName(prop)];
        id value = [obj valueForKey:propName];
        if(value == nil)
        {
            value = [NSNull null];
        }
        else
        {
            value = [self getObjectInternal:value];
        }
        
        [dic setObject:value forKey:propName];
    }
    return dic;
}


/**
 针对对象里面属性的不同属性 进行转换
 
 @param obj 对象
 @return 返回
 */
- (id)getObjectInternal:(id)obj
{
    if([obj isKindOfClass:[NSString class]]
       || [obj isKindOfClass:[NSNumber class]]
       || [obj isKindOfClass:[NSNull class]])
    {
        return obj;
    }
    
    if([obj isKindOfClass:[NSArray class]])
    {
        NSArray *objarr = obj;
        NSMutableArray *arr = [NSMutableArray arrayWithCapacity:objarr.count];
        for(int i = 0;i < objarr.count; i++)
        {
            [arr setObject:[self getObjectInternal:[objarr objectAtIndex:i]] atIndexedSubscript:i];
        }
        return arr;
    }
    
    if([obj isKindOfClass:[NSDictionary class]])
    {
        NSDictionary *objdic = obj;
        NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:[objdic count]];
        for(NSString *key in objdic.allKeys)
        {
            [dic setObject:[self getObjectInternal:[objdic objectForKey:key]] forKey:key];
        }
        return dic;
    }
    return [self getObjectData:obj];
}

在上面的自定义模型中,我们包含NSMutableArray,而且我们希望实现完全拷贝,所以实现了GLDeepCopy,并且针对其中的NSMutableArray调用了Category中的 GLDeepCopy方法,在看另一个模型

#import <Foundation/Foundation.h>

@interface Anima : NSObject<NSCopying>

@property (nonatomic,copy) NSString *address;

@end


#import "Anima.h"

@interface Anima ()



@end

@implementation Anima

- (id)copyWithZone:(NSZone *)zone{
    Anima *copy = [[Anima alloc] init];
    
    if (copy) {
        copy.address = [self.address copyWithZone:zone];
    }
    return copy;
}


@end

由于该模型,没有包含集合类型,所以我只是简单的实现了NSCopying协议,下面来看使用情况

    //测试加入数组中  对数组进行拷贝
    PersonModel *new_PersonModel = [[PersonModel alloc] init];
    new_PersonModel.name = @"gaogaogao";
    new_PersonModel.age = 20;
    Anima *anima = [[Anima alloc] init];
    anima.address = @"成都";
    new_PersonModel.array = [NSMutableArray arrayWithObject:anima];
    [new_PersonModel.array addObject:@[@"1",@"2",@"3"]];
    
        
    NSArray *array = [NSArray arrayWithObject:new_PersonModel];
    NSArray *copyArray = [array copy];
    NSMutableArray *mutableCopyArray = [NSMutableArray arrayWithArray:[array GLDeepCopy]];//[[NSMutableArray alloc] initWithArray:array copyItems:YES];//[array mutableCopy];//
    
    NSLog(@" 打印信息array:%p+%@ + %p\ncopyArray:%p+%@ + %p\nmutableCopyArray:%p+%@ + %p",array,array,array[0],copyArray,copyArray,copyArray[0],mutableCopyArray,mutableCopyArray,mutableCopyArray[0]);
    
    
    
    //修改数组中的内容
    PersonModel *personModel_array = array[0];
    personModel_array.name = @"gao_修改";
    personModel_array.age = 24;
    
    Anima *anima_model = personModel_array.array[0];
    anima_model.address = @"阆中";
    
    //获取深拷贝数组中的model中数组中的model
    PersonModel *personModel_mutable_copy_array = mutableCopyArray[0];
    Anima *anima_model_mutable_copy = personModel_mutable_copy_array.array[0];
    
    NSLog(@" 打印信息获取深拷贝数组中的model中数组中的model地址:\n原数组中的PersonModel中Array中的Anima:%p \n 原数组中的PersonModel中Array中的非Anima对象%p\n++ 深拷贝数组中的PersonModel中Array中的Anima:%p \n 深拷贝数组中的PersonModel:%p \n+ 深拷贝数组中的PersonModel中Array中的非Anima对象%p",anima_model,personModel_array.array[1],anima_model_mutable_copy,personModel_mutable_copy_array,personModel_mutable_copy_array.array[1]);
    
    
    NSLog(@" 打印信息修改后array:%p+%@\ncopyArray:%p+%@\nmutableCopyArray:%p+%@",array,array,copyArray,copyArray,mutableCopyArray,mutableCopyArray);
    

打印信息

完全拷贝.png

打印信息的排版有点乱,这不是重点,通过观察,我们可以发现数组中模型中的数组中的模型都是进行了完全拷贝,看最后一行打印信息,前面两个数组中的address都和第一行中的不一样,因为我们把地址改成了阆中,而最后一个数组中的address却还保持着之前的值,这说明,我们是完成了完全拷贝的

上面我用的是NSArray进行的举例,而其他集合类型NSDictionaryNSSetCategory方法也大同小异

相关代码,请移步demo如果觉得还可以,可以给个star哦,不甚感激~

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

推荐阅读更多精彩内容