NerdyUI 使用小技巧

前言

本文列出了一些 NerdyUI 在实际项目中可能会用到的一些小技巧,以及一些注意事项,希望能对您有所帮助。如果您还不知道 NerdyUI 是什么,请先查看这里

Str

  1. .a() 可用来拼接字符串,.ap() 可用来拼接路径。它们能接受的参数跟 Str() 一样。传 nil 的话则什么事都不做,很适合用来拼接多个字符串。

     @"1".a(@"2").a(3).a(nil).a(4.0f).a(@5).a(@"%d", 6); //@"123456"
     Str(province).a(city).a(district).a(address);         //不用担心有的变量可能为 nil
    
  2. .subFrom().subTo() 用来截取子串,你可以传一个索引或子串。

     @"hello".subFrom(2);         //"llo"
     @"hello".subFrom(@"l");   //"llo"
     @"hello".subTo(2);         //"he"
     @"hello".subTo(@"ll");     //"he"
     @"hello [world]".subFrom(@"[").subTo(@"]");  //"world"
    
  3. .subMatch().subReplace() 可用正则表达式来查找和替换子串。

     @"pi: 3.13".subMatch(@"[0-9.]+");              //"3.13"
     @"pi: 3.13".subReplace(@"[0-9.]+", @"3.14");    //"pi: 3.14"
    

AttStr

  1. AttStr() 可以把多个 NSString、NSAttributedString 和 UIImage 拼接成一个 NSAttributedString。后面设置的属性默认会覆盖前面设置的相同属性,可以使用 .ifNotExists 来避免这种情况。

     .color(@"red").color(@"blue");              //蓝色
     .color(@"red").ifNotExists.color(@"blue");  //红色
    
     AttStr(
           @"small text, ",
           AttStr(@"large text, ").fnt(@40),
           AttStr(@"red small text, ").color(@"red"),
           Img(@"moose"),
           @"small text"
           ).ifNotExists.fnt(20);
    
  2. NSAttributedString 里能包含图片这个事实打开了无限的可能,很多之前要用用多个 Label 和 ImageView 才能实现的 UI 用 AttStr 可以很轻易的搞定。

     AttStr(@"A hat ", Img(@"hat"), @" and a moose", Img(@"moose"));
    
  3. AttStr 的属性默认会应用到整个字符串,你可以用 .range().match().matchNumber.matchURL.matchHashTag.matchNameTag 等来缩小范围。

     id str = @"Hello @Tim_123";
     
     AttStr(str).color(@"blue");               //整个字符串都为蓝色
     AttStr(str).range(0, 5).color(@"blue");   //"Hello" 为蓝色
     AttStr(str).match(@"Tim").color(@"blue");   //"Tim" 为蓝色
     AttStr(str).matchNumber.color(@"blue");   //"123" 为蓝色
     AttStr(str).matchNameTag.color(@"blue");     //"@Time_123" 为蓝色
     
     AttStr(str).range(0, 3).range(-3, 3).match(@"@").color(@"blue");
     //"Hel", "@", "123" 为蓝色
    

    .match() 可以使用正则表达式,负数的 range 表示从尾部往前数。.range().match() 可连续使用,表示同时选取多个子串。

  4. 使用 .lineGap() 可以设置行间距。但你应该很少会用到,因为 Label 也有一个 .lineGap() 快捷属性。.linkForLabel 只适用于 Label,不适用于其他视图。

Img

  1. Img() 传色值的话会返回一个 1x1 大小的图片,这在大部分情况下貌似都没什么用。除了 Button 的 .bgImg().highBgImg(),因为 Button 的 backgroundImage 会自动拉伸占满整个视图。

     Img(@"red").resize(100, 100);       //100x100 大小的红色图片
    
  2. .stretchable 会返回一个可拉伸的图片,拉伸位置在图片中心点。如果你想更具体的控制可拉伸区域,可以使用 .tileInsets().stretchInsets()

     Img(@"button-bg").stretchable;  //等于 Img(@"#button-bg");
     Img(@"pattern").tileInsets(0);  //平铺图片
    
  3. .templates 和 UIView 的 .tint() 配合可以用来给图片上色。

    ImageView.img(Img(@"moose").templates).tint(@"red");

Color

  1. 你可以用 .opacity() 来修改 Color 的 alpha 值:

     Color(@"red").opacity(0.5);     //等于 Color(@"red,0.5");
    
  2. 你可以用 .brighten().darken().saturate().desaturate().hueOffset() 等来修改颜色。

     View.wh(100, 100).bgColor(@"#289DCE").onClick(^(UIView *v) {
         v.bgColor(v.backgroundColor.darken(0.2));   //模拟点击变暗效果
     });
    

Screen

  1. 你可以用 Screen.size, Screen.widthScreen.height 来访问屏幕大小。Screen 还有一个比较有用的属性是 Screen.onePixel, 它始终返回一个像素的大小而不管是在什么设备上。比如设计师可能要求 App 里的分割线都是一个像素的大小,那么你就可以这么用:

     Style(@"separator").wh(Screen.width, Screen.onePixel).bgColor(@"#d9d9d9");
     ...
     id s1 = View.styles(@"separator");
     id s2 = View.styles(@"separator").x(15).w(Screen.width - 30);
    

View

  1. 如果你想设置一个视图的大小,可以用.wh(50, 50)。但如果你想让一个它的等于另一个视图的大小呢,你可以这么写 .wh(otherView.w, otherView.h), 或者更简单一点 .wh(otherView.wh), 这是因为 .wh() 既可以接受两个 CGFloat, 也可以接受一个 CGSize。.xy().cxy().maxXY().xywh() 也与此类似,比如 .cxy(otherView.center).xywh(otherView.frame).xywh(otherView.xy, 50, 50)等等。

  2. 当你想给一个视图设置 border 时,你可只传一个宽度 .border(2), 或者同时带上一个颜色 .border(2, @"red")。如果你已经有一个 UIColor 对象,那么也可以直接传这个对象 .border(2, borderColor),这对于 .tint().color().bgColor() 等也适用。

  3. 使用 .borderRadius() 会自动把 masksToBounds 设为 YES(如果没有设置阴影的话)。shadow() 默认向下投影,它有几种形式:

     .shadow(0.6);           //shadowOpacity
     .shadow(0.6, 2);         //shadowOpacity + shadowRadius
     .shadow(0.3, 3, 3, 3);   //shadowOpacity + shadowRadius + shadowOffsetXY
    
  4. .onClick() 可以用来给任意视图添加一个单击手势,如果这个视图是一个 UIButton,则它使用的是 Button 的 UIControlEventTouchUpInside 事件。使用 onClick 时还会自动把 userInteractionEnabled 设为 YES,毕竟当你给一个 UILabel 或者 UIImageView 添加单击事件时,你想让它们可以点击。

    你可以传一个 block 来作为回调方法,最简单的形式就是 .onClick(^{ ... })。 onClick 已经自动对 self 做了 weakify 处理,虽然标准做法是要在 block 里对 self再做个强引用,防止它提前释放。但大部分情况下你都不需要这么做,因为很多时候 self 对应的都是当前视图的父视图或者它所在的 ViewController,而它们是不会提前释放的。如果你还是不放心,那么你可以这么写:

     .onClick(^{ typeof(self) strongSelf = self; ... });
    

    如果需要在 block 里访问当前视图,你不能这么写:

     UIView *box = View.onClick(^{
         box.bgColor(@"blue");   //box为nil,因为此时onClick还没返回
     });   
    

正确写法应该是:

    UIView *box = View.onClick(^(UIView *box) {
        box.bgColor(@"blue");   //使用的是 block 参数
    });

如果回调代码比较多,或者你更喜欢传统的 target-action 方式,那么你可以这么用:

    .onClick(@"boxDidTap")      //target 默认为 self,action 为字符串,请小心拼写
    .onClick(@"boxDidTap:")    //如果你需要当前视图作为参数的话   
这里提到的 `.onClick()` 的用法同样适用于 `.onChange()`、`.onFinish()` 和 `.onLink()`等。
  1. 把一个视图添加到另一个视图里有三种方式:

     parentView.addChild(view1, view2, view3, ...);  //使用 addChild 添加多个子视图
     view1.addTo(parentView);    //使用 addTo 加到父视图里
     view1.embedIn(parentView);  //使用 embedIn 加到父视图里,会同时添加上下左右的约束
    

    .embedIn() 可以有额外的参数,用来设置距离父视图上下左右的偏移量:

     .embedIn(parentView, 10, 20, 30, 40);   //上:10, 左:20, 下:30, 右:40
     .embedIn(parentView, 10, 20, 30);       //上:10,左右:20,下:30
     .embedIn(parentView, 10, 20);           //上下:10, 左右:20
     .embedIn(parentView, 10);               //上下左右:10
     .embedIn(parentView);                   //上下左右:0
    

    这个用法跟 HTML 里的 Margin 和 Padding 类似。如果有某些方向你不想加约束的话,你可以用 NERNull 代替:

     .embedIn(parentView, 10, 20, NERNull, NERNull); //上:10,左:20
     .embedIn(parentView, 10, NERNull);               //上下:10
    

    .embedIn()这种可变参数的用法同时也适用于 .insets(),后面会说到。

  2. 如果你习惯于手动布局,那么你可能会经常用到 .fitSize.fitWidth.fitHeight 来改变视图的大小,用 .flexibleLeft.flexibleRight ... .flexibleWH等来设置 autoresizingMask。

    如果你习惯使用 AutoLayout, 则 .fixWidth().fixHeight().fixWH().makeCons()remakeCons()updateCons() 等会是你的好朋友。.fixWidth() 等3个内部使用了 .remakeCons() 来设置宽高约束,所以你可以重复使用它们而不用担心会引起约束冲突。

Label

  1. 你可以用 .str() 来设置 text 或者 attributedText。同时你还可以直接传基本类型,省去了转换为字符串的过程:.str(1024)

  2. .fnt().color() 可以直接传 UIFont 或 UIColor 对象。

  3. .highColor() 可以用来设置 highlighted 状态下的字体颜色,比如 Cell 被选中时。

  4. 允许多行可以用 .lines(0) 或者 .multiline

  5. Label 链接的默认颜色是蓝色,你可以改成其他颜色:

     AttStr(@"hello world").match(@"world").linkForLabel.color(@"red");  //红色链接
    

    链接选中的样式也可以修改:

     //修改单个 Label 的样式
     label.nerLinkSelectedBorderRadius = 0;
     label.nerLinkSelectedColor = [UIColor blueColor];
     //全局修改
     [UILabel setDefaultLinkSelectedBackgroundColor:[UIColor blueColor] corderRadius:0];
    

    因为 UILabel 默认是不接受事件的,你必须使用 .touchEnabled 或者 .onLink() 才能点击链接。因为 .onLink() 也会把 userInteractionEnabled 设为 YES。

ImageView

  1. .img() 会自动把当前视图的大小设置为图片的大小(如果你没设置过 frame 的话)。

     id iv1 = ImageView.img(@"cat");             //iv1 的大小等于图片的大小
     id iv2 = ImageView.wh(50,50).img(@"cat");     //iv2 的大小等于(50,50)
    

    .img().highImg() 还可以接受图片数组。

  2. 你可以用 .aspectFit.aspectFill.centerMode 来设置 contentMode。

Button

  1. Button 标题默认为一行,可以使用 .multiline 来让它支持多行显示。

     Button.str(@"hello\nhow are you").multiline;
    
  2. Button 的 .bgImg().highBgImg() 非常的灵活和好用。

     .bgImg(@"btn-normal").highBgImg(@"btn-high");     //使用图片
     .bgImg(@"#btn-normal").highBgImg(@"#btn-high"); //使用可拉伸的图片
     .bgImg(@"red").highBgImg(@"blue");  //使用颜色
    

之所以用 .bgImg() 而不是 .bgColor() 来设置按钮背景颜色是因为后者在 Cell 选中时会被清空。.bgImg().img() 一样会把当前视图的大小设置为图片的大小(如果你没设置过 frame 的话)。

  1. 因为 UIButton 里带有一个 UILabel 和 一个 UIImageView,很适合用来创建这样的 UI:“一个图标后面跟着一段文字” 或者 “一段文字后面跟着一个图标”,并且图标和文字都可点击。

     //评论图标后跟着评论数
     .img(@"comment_icon").str(commentCount).gap(10);
     //"查看更多"后跟着向右箭头
     .img(@"disclosure_arrow").str(@"查看更多").gap(10).reversed;
    

    使用 .gap() 可在 image 和 title 之间加上一些间隙。使用 .reversed 可以调换 image 和 title 的位置。

  2. 如果想在文字上面或下面加上图标,则可以使用 AttStr。
    Button.multiline.str(AttStr(Img(@"someIcon"), "\nIcon above Text"));
    Button.multiline.str(AttStr("Icon below Text\n", Img(@"someIcon")).lineGap(10));

  3. 有的时候你可能想在按钮内容和边框之间留一点空间,那么可以使用 .insets()

     .str(@"Done").insets(5, 10).fitSize;          //宽高跟着 title 的变化而变化
     .str(@"Done").insets(5, 10);                  //autolayout version
     .str(@"Done").h(45).insets(0, 10).fitWidth;   //高度固定,宽度变化
     .str(@"Done").fixHeight(45).insets(0, 10);  //autolayout version
    

    .insets() 还有一个妙用就是当按钮的背景图片带有阴影时,title 的显示位置会不太对,这时候就可以用 .insets() 来调整。 它能接受的参数跟 .embedIn() 的可变参数一样。

  4. 组合的使用 .borderRadius().border().color().highColor().bgImg().highBgImg().insets() 以及 AttStr() 等,可以创建出各种各样的按钮。

Constarints

  1. 一个完整的 NSLayoutConstraint 必须包含这个公式里的全部要素:

     view1.attr1 [= , >= , <=] view2.attr2 * multiplier + constant;
    

所以当您使用 .makeCons() 来创建约束时,也必须包含这些要素:

    //让当前视图的左边和上边等于父视图的左边和上边
    make.left.equal.view(superview).left.multipliers(1).constants(0);
    make.top.equal.view(superview).top.multipliers(1).constants(0);
    
    //让当前视图的大小等于 view2 的大小
    make.width.equal.view(view2).width.multipliers(1).constants(0);
    make.height.equal.view(view2).height.multipliers(1).constants(0);

可以看到要写不少代码,幸好这里面很多属性都有默认值,我们可以一步步的精简它们:

    //1. 如果有多个约束同时涉及到 view1 和 view2,则可以把它们合并在一起
    make.left.top.equal.view(superview).left.top.multipliers(1, 1).constants(0, 0);
    make.width.height.equal.view(view2).width.height.multipliers(1, 1).constants(0, 0);
    
    //2. 如果 multipliers 和 constants 的参数都是一样的,则可以把它们合并成一个
    make.left.top.equal.view(superview).left.top.multipliers(1).constants(0);
    make.width.height.equal.view(view2).width.height.multipliers(1).constants(0);
    
    //3. 如果 attr1 和 attr2 是一样的,则可以省略 attr2
    make.left.top.equal.view(superview).multipliers(1).constants(0);
    make.width.height.equal.view(view2).multipliers(1).constants(0);
    
    //4. multipliers 的默认值是 1, constants 的默认值是 0,所以它们也可以省略掉
    make.left.top.equal.view(superview);
    make.width.height.equal.view(view2);
    
    //5. 同时设置 width 和 height 的话可以用 size 来表示
    make.left.top.equal.view(superview);
    make.size.equal.view(view2);
    
    //6. relation 默认为 equal,所以也可以省略掉(坏处是可读性会降低)
    make.left.top.view(superview);
    make.size.view(view2);
    
    //7. 如果没指定 view2,则默认为父视图
    make.left.top;  //虽然很奇怪,但你可以这么写。不过这时候会有警告,因为我们没用到返回值。
    make.size.view(view2);
    
    //8. 为了消除警告,可以使用 End() 结尾
    make.left.top.End();
    make.size.view(view2);
    
    //或者用 And 把它们拼接在一起
    make.left.top.And.size.view(view2);

可以看到到最后变得非常的精简,但可读性也变得很差了。这就需要各位自己权衡了。
  1. 前面说过如果没有指定 view2, 则默认为父视图。这其实有一个例外,就是涉及到 width 和 height 时:

     make.size.equal.constants(100, 200);
     
     make.width.constants(100);
     make.height.equal.width.End();  //这里的 equal 不能省略,否则就意义不明了
    

    这里设置的都是当前视图的大小。如果想让它们相对于其他视图,则需要显示的指定:

     make.width.height.equal.view(view2).height.width.multipliers(0.5);
    
  2. .priority() 可用来设置优先级。.identifier() 可用来设置标识。

  3. 使用 .makeCons().remakeCons().updateCons() 前必须把当前视图加到父视图里。

     .addTo(superView).makeCons(^{});
    

TextField / TextView

  1. 你可以用 .hint() 来设置 placeholder, .maxLength() 来限制输入长度。这两个对 UITextField 和 UITextView 来说几乎是标配,奇怪的是系统默认只支持设置 UITextField 的 placeholder。

     .hint(@"Enter your name");      //使用默认的大小和颜色
     
     id att = AttStr(@"Enter your name").fnt(15).color(@"#999");
     .hint(att);                 //使用自定义的大小和颜色
    
  2. .onChange() 会在文本改变时回调,.onFinish() 会在点击键盘上的 return button 时回调。.insets() 的用法跟 UIButton 一样。UITextView 一个不一样的地方在于它默认是有 insets 的,如果你不想要,可以用 .insets(0) 来清空。

  3. 你可以用 .becomeFocus 来获取输入焦点。

HorStack / VerStack

  1. HorStack() 默认的对齐方式是 centerAlignment,VerStack() 默认的对齐方式是 leftAlignment。它们的用法类似于 UIStackView 及 Android 的 LinearLayout。

  2. 如果你设置了 Stack 的宽高约束,那么当 Stack 里子视图的宽度总和或高度总和小于 Stack 本身的宽或高时,有个子视图将会被拉伸。当 Stack 里子视图的宽度总和或高度总和大于 Stack 本身的宽或高时,有个子视图将会被压缩。对于使用 intrinsicContentSize 的子视图来说,你可以通过 .horHugging().verHugging()horResistance().verResistance().lowHugging.lowResistance 等来修改 contentHuggingPriority 和 contentCompressionResistancePriority 的值,进而控制哪个子视图可以被拉伸或压缩。对于第一种情况,你还可以使用 NERSpring, 它相当于一个弹簧,会占用尽可能多的空间,这样所有的子视图都不会被拉伸。

  3. 如果你没有设置 StackView 的宽高约束,那么它的大小会跟随着子视图的变化而变化。一般只有最外层的 StackView 我们会设置它的宽或高(不管是直接或者间接,比如 .embedIn 可能会间接的影响它的宽高)。

     //宽度等于父视图宽度,高度跟随子视图变化
     VerStack(view1, view2, view3).centerAlignment.gap(10).embedIn(self.view, 0, 0, NERNull, 0);
     
     //固定宽高,使用 NERSpring 来避免子视图被拉伸
     VerStack(view1, @10, view2, NERSpring, view3, @20, view4).wh(self.view.wh).addTo(self.view);
    

    虽然后一个例子我们设置的是frame,但因为 UIView 的 translatesAutoresizingMaskIntoConstraints 默认为 YES,所以也相当于设置了宽高约束。加到 Stack 里的子视图的 translatesAutoresizingMaskIntoConstraints 会被设为 NO,所以只有最外层的 Stack 可以用设置 frame 的方式来布局。

  4. .gap() 会在每个子视图之间添加相同的间隙。@(n) 会在两个子视图之间添加间隙,这就允许不同的子视图之间有不同的间隙。

  5. 可以通过 -addArrangedSubview:-insertArrangedSubview:atIndex:-removeArrangedSubview:removeArrangedSubviewAtIndex: 来添加或删除子视图。如果想临时隐藏子视图,可以直接设置子视图的 hidden 属性,这是一个非常好用的功能。

Alert / ActionSheet

  1. 可以同时有多个 Action 按钮,其中 .action(). destructiveAction() 必须传标题和回调 block, .cancelAction() 可以只传一个标题:

     Alert.action(@"Action1", ^{
     
     }).action(@"Action2", ^{
     
     }).action(@"Action3", ^{
     
     }).destructiveAction(@"Delete", ^{
     
     }).cancelAction(@"Cancel").show();
    
  2. .title().message().action() 有个隐藏的功能是可以传 NSAttributedString,这就表示它们的显示样式是可以修改的。不过这不是官方提供的功能,可能只在某一些版本的系统上有效,不推荐大家使用。

  3. 使用 .tint() 可以改变所有普通按钮的字体颜色,这是系统提供的功能。

  4. 最后必须调用 .show() 才能显示出来。

Style

  1. View(及其子类)、AttStr 和 Style 可同时使用一个或多个 Styles。对 Style 来说,就相当于继承:

     Style(@"headline").fnt(@20).color(@"#333");
     Style(@"round-border").borderRadius(8).border(1, @"red");
     
     AttStr(someString).styles(@"headline");
     Label.styles(@"headline round-border");     //使用空格作为分隔符,就像 CSS 一样
     
     id roundHeadline = Style().styles(@"headline round-border").bgColor(@"lightGray");
     Button.styles(roundHeadline);
    
  2. 全局 Style 一般在程序启动的时候设置,比如 -application:didFinishLaunchingWithOptions: 或者 +load 里。

最后

  1. 链式属性分为两种:一种带参数,比如 .color(@"red"),一种不带参数,比如 .centerAlignment。如果最后一个属性是不带参数的属性,且它的返回值没有赋值给一个变量,那么那么编译器将给出警告。你可以使用 .End() 来消除警告。

     UILabel *someLabel = ...;
     ...
     someLabel.str(newString).fitSize;       //Warning: Property access result unused
     
     someLabel.str(newString).fitSize.End();  //no more warning
    
  2. 尽可能的使用 id,如果后续不需要再访问某个变量的属性,定义为 id 可以减少不少代码。

  3. 多考虑使用 NSAttributedString。因为 AttStr() 的存在,使得创建 NSAttributedString 变得非常简单。并且系统控件早就全面的支持 NSAttributedString 了。

  4. 学会使用 StackView 或 LinearLayout 的方式来思考问题,即同时对几个视图进行布局而不是对每个视图单独进行布局。

  5. 学会使用特殊字符和表情符号,有一些图标乍一看像是图片,但是其实是可以使用特殊字符或表情来表示的。Unicode 提供了非常多的特殊字符,像是 ⚽︎♠︎♣︎☁︎☃☆★⚾︎◼︎▶︎✔︎✖︎♚✎✿✪ 等等,最重要的一点是这些图标就像普通文字一样可以改变大小和颜色。

  6. 如果发现有一些属性没找到,请更新到最新版本。

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

推荐阅读更多精彩内容