IOS-靜態(tài)庫(.a迎吵、framewrok)躲撰、動態(tài)庫(.tbd、framework)击费、Bundle制作(適用于靜態(tài)庫的)研究

技 術 文 章 / 超 人


關于庫思維導圖:


概念

什么是庫
庫是共享程序代碼的方式拢蛋。庫從本質(zhì)上來說是一種可執(zhí)行代碼的二進制格式,可以被載入內(nèi)存中執(zhí)行荡灾。在開發(fā)過程中瓤狐,一些核心技術或者常用框架,出于安全性和穩(wěn)定性的考慮批幌,不想被外界知道础锐,所以會把核心代碼打包成庫,只暴露出頭文件以供使用荧缘。庫分靜態(tài)庫和動態(tài)庫兩種皆警。
庫的分類

  • 靜態(tài)庫
    對于靜態(tài)庫而言,類似于一個編譯好的 .o的集合截粗。在build的過程中信姓,只會參與鏈接的操作,鏈接器會將靜態(tài)庫中被使用的部分合并到可執(zhí)行文件中去绸罗,用函數(shù)的實際地址來代替函數(shù)引用意推。

存在 .a.framework兩種形式。 .a要有.h文件以及資源文件配合
1. .a是一個純二進制文件
2. .framework中除了有二進制文件之外還有資源文件珊蟀。 .framework
文件可以直接使用菊值。
總的來說.a + .h + sourceFile= .framework。所以創(chuàng)建靜態(tài)庫最好還是用.framework的形式腻窒。
鏈接流程如下圖:

  • 動態(tài)庫
    存在.framework和.tbd兩種形式昵宇。

iOS8 之前,蘋果不允許第三方框架使用動態(tài)方式加載儿子,從 iOS8 開始允許開發(fā)者有條件地創(chuàng)建和使用動態(tài)框架瓦哎,這種框架叫做 Cocoa Touch Framework。雖然同樣是動態(tài)框架柔逼,但是和系統(tǒng) framework 不同蒋譬,app 中的使用的 Cocoa Touch Framework 在打包和提交 app 時會被放到 app bundle 中,運行在沙盒里愉适,而不是系統(tǒng)中羡铲。也就是說,不同的 app 就算使用了同樣的 framework儡毕,但還是會有多份的框架被分別簽名,打包和加載扑媚。不過iOS8 上開放了App Extension 功能腰湾,可以為一個應用創(chuàng)建插件,這樣主app和插件之間共享動態(tài)庫還是可行的疆股。

動態(tài)鏈接是使用了 Procedure Linkage Table (PLT)费坊。首先這個 PLT 列出了程序中每一個函數(shù)的調(diào)用,當程序開始運行旬痹,如果動態(tài)庫被加載到內(nèi)存中附井,PLT 會去尋找動態(tài)的地址并記錄下來,如果函數(shù)被調(diào)用過的話两残,下一次調(diào)用就可以通過 PLT 直接跳轉(zhuǎn)了永毅。

  • 優(yōu)劣
    1. 靜態(tài)庫,在鏈接時會被完整地復制到可執(zhí)行文件中人弓,被多次使用就有多份冗余拷貝沼死,靜態(tài)庫還有一個較重要的缺點,多個靜態(tài)庫之間文件名和靜態(tài)變量名字不能重復崔赌,否則編譯會報錯或者找錯對象意蛀。好處很明顯,編譯完成之后健芭,庫文件實際上就沒有作用了县钥。目標程序沒有外部依賴,直接就可以運行慈迈。當然其缺點也很明顯若贮,就是會使用目標程序的體積增大
    2. 動態(tài)庫,與靜態(tài)庫相反兜看,動態(tài)庫在編譯時并不會被拷貝到目標程序中锥咸,目標程序中只會存儲指向動態(tài)庫的引用。等到程序運行時细移,動態(tài)庫才會被真正加載進來搏予。系統(tǒng)的動態(tài)庫不需要拷貝到目標程序中,自建的動態(tài)庫可以由工程內(nèi)的多個庫共享弧轧,因此可以減小目標程序的體積雪侥。但是,由于其把靜態(tài)鏈接做的事情都搬到運行時來做精绎,程序的啟動會變慢速缨。

庫的創(chuàng)建


.a靜態(tài)庫的創(chuàng)建

創(chuàng)建一個 .a
靜態(tài)庫項目,如下圖所示:

image.png

靜態(tài)庫的文件列表如下代乃,在 products 文件夾內(nèi)的就是要生成的靜態(tài)庫旬牲。此刻是紅色的,等到靜態(tài)庫編譯成功就會變成黑色搁吓。


現(xiàn)在新建自己的類PrintString.h
原茅,聲明和實現(xiàn)一個第三方庫的方法。


現(xiàn)在可以打包這個靜態(tài)庫了堕仔。由于模擬器和真機架構(gòu)不同擂橘,需要選擇該包將運行在哪個環(huán)境下,如下圖所示摩骨,選擇運行在真機上:


打包生成了靜態(tài)庫在 products 文件夾內(nèi):


打開 products 文件夾通贞, 但是此時暴露出來的頭文件并沒有PrintString.h
。需要對暴露的頭文件進行設置恼五。


如下圖昌罩,在 Build Phase ,的 Copy Files 目錄下加入想要公開的頭文件:


現(xiàn)在再 run 一次唤冈,就得到了正確的靜態(tài)庫峡迷。


現(xiàn)在,可以測試一下這個靜態(tài)庫你虹』娓悖可以再創(chuàng)建一個工程,把庫拖進去傅物。不過更推薦如下圖所示夯辖,新建一個 target :


先要在工程和庫間建立關聯(lián)。如下圖所示董饰,在 Link Binary With Libraries中添加庫:

在 ViewController.m
中調(diào)用庫的方法:


現(xiàn)在可以運行了蒿褂,不過運行前要選擇對 target :


可以在控制臺看到庫中的方法被調(diào)用了:



.framework的創(chuàng)建

動態(tài)framework
創(chuàng)建一個framework:

image.png

創(chuàng)建后的文件列表如下圆米,可以看到只有一個 framework.h
頭文件。通過注釋啄栓,我們可以理解娄帖,這個頭文件是所有 public 頭文件的集合:


將前面創(chuàng)建的 PrintString.h 和 PrintString.m導入,并且 import 到 framework.h 中去:


設置需要暴露的頭文件昙楚,頭文件默認在 project header 中近速,將需要暴露出來的拖到 public header 中去。


我們可以看到此處有三種頭文件堪旧,分別是 project header 削葱, public header , private header 淳梦。區(qū)別如下:

Public: The interface is finalized and meant to be used by your product’s clients. A public header is included in the product as readable source code without restriction.
Private: The interface isn’t intended for your clients or it’s in early stages of development. A private header is included in the product, but it’s marked “private”. Thus the symbols are visible to all clients, but clients should understand that they're not supposed to use them.
Project: The interface is for use only by implementation files in the current project. A project header is not included in the target, except in object code. The symbols are not visible to clients at all, only to you.

生成的 framework 文件目錄如下:


將生成的 framework 放入工程中測試析砸,編譯通過,運行時出現(xiàn)如下錯誤:


需要將動態(tài)庫嵌入工程的 bundle 中爆袍。因此首繁,需要在 General 中的 Embedded Binary 一項中加入相應動態(tài)庫:



現(xiàn)在就可以正確運行了


動態(tài)framework

靜態(tài)framework和動態(tài)framework創(chuàng)建的基本流程一致,唯一的區(qū)別需要設置 Mach-O Type 為 Static Library


靜態(tài)庫與動態(tài)庫的引用
一個庫的開發(fā)經(jīng)常會需要用到其他的庫(如 AFNetWorking
)的配合陨囊,因此蛮瞄,需要在庫中嵌入其他的庫。如何在自己的靜態(tài)/動態(tài)庫中集成第三方的靜態(tài)/動態(tài)庫是我比較困惑的點谆扎。
網(wǎng)上沒有找到相關教程,以下是我不斷嘗試后得出的結(jié)論芹助,如果有錯誤還請指正堂湖。
動態(tài)庫引用靜態(tài)庫
創(chuàng)建一個動態(tài)庫 DynamicWithStatic

使用 cocoapods 的方式為動態(tài)庫引入靜態(tài)庫状土。在工程目錄下新建 podfile
,寫入:

target 'DynamicWithStatic' do
pod 'SVProgressHUD'
end

這里引入SVProgressHUD
无蜂,因為調(diào)試起來比較簡單。
在執(zhí)行完 pod install
后蒙谓,打開 Frameworks.xcworkspace
,在其中添加SVProgress
類〕饧荆現(xiàn)在的工程目錄如下:

SVProgress.h
中添加代碼:

typedef void(^SVProgresshud)();
#import <Foundation/Foundation.h>
@interface SVProgress : NSObject
+ (SVProgresshud)getBlock;
@end

SVProgress.m
中添加代碼:

#import "SVProgress.h"
#import "SVProgressHUD.h"
@implementation SVProgress
+(SVProgresshud)getBlock{
    return ^(){
        [SVProgressHUD showSuccessWithStatus:@"成功!"];   
   };
}@end

SVProgress
類的目的是提供一個 block 以供調(diào)用累驮。將 SVProgress.h
頭文件暴露出來后酣倾, run 生成動態(tài)庫。
動態(tài)庫內(nèi)引用靜態(tài)庫相當于直接把代碼寫入動態(tài)庫中谤专,非常的簡單≡晡現(xiàn)在思考一個問題,如果工程中引用了這個動態(tài)庫置侍,并且工程本身也用到了 SVProgressHUD
庫映之,那么會發(fā)生什么拦焚?嘗試一下,在 Pod 中為 FrameworkTest
添加 SVProgressHUD
,會產(chǎn)生如下的警告:

重復實現(xiàn)

SVProgressHUD
庫中的各個類在工程和庫中都進行了實現(xiàn)杠输,但是沒有指明使用哪一個實現(xiàn)赎败。不過這個警告,并不影響運行蠢甲,非強迫癥可以選擇無視僵刮,那么對于強迫癥患者,如何消除掉這些警告呢峡钓?修改庫中 SVProgressHUD
中各個類的命名妓笙。有兩種方式:手動和自動,將在下面介紹能岩。
動態(tài)庫引用動態(tài)庫
這次被引用的動態(tài)庫還是 SVProgressHUD庫寞宫。先用 pod 下載 SVProgressHUD的源碼,然后打包成動態(tài)庫拉鹃,這里就不多做說明了辈赋。將動態(tài)庫 SVProgressHUD拖入工程中,新建 DynamicWithDynamic動態(tài)庫膏燕。將上面的 SVProgress.hSVProgress.m拖入 DynamicWithDynamic中钥屈,設置暴露出 SVProgress.h
記得注意一定要在 DynamicWithDynamic
中引入 SVProgressHUD
,如下圖所示:

現(xiàn)在 run 一下坝辫,就可以成功生成了篷就。下面在 FrameworkTest中測試,使其 embed DynamicWithDynamic近忙。微調(diào)下 ViewController.m使其引入目標庫竭业,運行。在運行中出現(xiàn)如下錯誤:

這個錯誤上面也提到過了及舍,是因為必要的動態(tài)庫沒有 embed 進工程中未辆。但是明明已經(jīng)將 DynamicWithDynamicembed了啊。好吧锯玛,由于 SVProgressHUD現(xiàn)在是動態(tài)庫了咐柜,還需要將 SVProgressHUD庫 embed 進 FrameworkTest中。
動態(tài)庫引入動態(tài)庫攘残,不會將要引入的動態(tài)庫打包到自身中拙友,即只是 link 產(chǎn)生關聯(lián),而不是 embed 嵌入歼郭。 需要在外部使用該動態(tài)庫時献宫,手動 embed 動態(tài)庫內(nèi)要使用的動態(tài)庫。這樣的做法很麻煩实撒,那么有什么意義呢姊途?正如動態(tài)庫本身的作用涉瘾,如果工程本身也要用到該 ·SVProgressHUD·
動態(tài)庫時,那么僅需導入一份捷兰,就不會產(chǎn)生重復代碼了立叛。


靜態(tài)庫引用靜態(tài)庫

新建一個 target
命名為 StaticWithStatic,使用 cocoapods 管理 SVProgressHUD贡茅∶厣撸基本方法和上面一樣,唯一需要改變的地方是 Mach-O 需要改為 Static Library 顶考,運行赁还。
然而運行失敗,報錯如下:

大概意思是在對 ViewController.h
進行鏈接的時候沒有找到 SVProgressHUD.m
驹沿。這就很奇怪了艘策,明明已經(jīng)在 StaticWithStatic
中通過 cocoapods 管理了,怎么會沒有 SVProgressHUD.m
呢渊季?我想可能是因為cocoapods只是起到 Link 作用朋蔫,并沒有把第三方庫也打進去,那么為什么動態(tài)庫引入靜態(tài)庫的時候是可行的呢却汉?這就不太清楚了驯妄。雖然不知道原因,但是解決方法是有的合砂。需要在工程里青扔,即 FrameworkTest
cocoapods 中添加 SVProgressHUD

target 'DynamicWithStatic' do
pod 'SVProgressHUD'
end


target 'StaticWithStatic' do
pod 'SVProgressHUD'
end


target 'FrameworksTest' do   
 pod 'SVProgressHUD'
end


target 'DynamicWithDynamic' do
end

再次 build ,錯誤消除翩伪,可以使用赎懦。


靜態(tài)庫引用動態(tài)庫
靜態(tài)庫貌似不能引用動態(tài)庫。如果嘗試一下幻工,會發(fā)現(xiàn),即使將動態(tài)庫 Link Binary With Libraries 入靜態(tài)庫黎茎,也是找不到 SVProgressHUD.h頭文件的囊颅。一些需要知道的點debugrelease

  • 庫分為 debugrelease 兩種版本。一般來說, 我們應該發(fā)布的是 release 版本傅瞻。
  • debug:調(diào)試版本, 系統(tǒng)本身也會有一些調(diào)試代碼. 此版本體積會稍大, 運行會稍慢踢代。
  • release : 發(fā)布版本, 系統(tǒng)會去除調(diào)試代碼, 體積變小, 運行速度變快. 對用戶來說沒有明顯的感覺。

debugrelease 的設置方式如下圖:

對于別人給的庫嗅骄,貌似并不能區(qū)分是 debug 還是 release 版本的胳挎。


多架構(gòu)編譯
庫不僅按 debugrelease 分類,還會因為運行系統(tǒng)的不同而編譯出不同框架的版本溺森。上面的例子都是在真機下的編譯慕爬,為 arm64 版本窑眯,在其他的框架下不能正確運行。

框架分類:
模擬器架構(gòu):

  • i386 : 32位架構(gòu) 4S ~ 5
  • x86_64 : 64位架構(gòu) 5S ~ 現(xiàn)在的機型

真機架構(gòu):

  • arm7: 在最老的支持iOS7的設備上使用
  • arm7s: 在iPhone5和5C上使用
  • arm64: 運行于iPhone5S的64位 ARM 處理器 上

修改框架的方式如下圖:


debug 項默認為 YES 磅甩,表示僅生成當前選擇的框架的庫; release 項默認為 NO 姥卢,表示生成支持所有模擬器或真機的庫卷要。生成的庫將會保存在 products 目錄下的不同分類目錄內(nèi):


lipo
lipo 是個很有用的命令,主要用來查看庫支持的架構(gòu)以及合并拆分庫独榴。


-info
查看剛才編譯的 Framework 庫在 debug 和 release 下支持的框架:
[圖片上傳中僧叉。栋荸。恩袱。(33)]查看庫

可以看到正如上面所說 debug 下不是 fat file ,只支持 arm64 呼巷, release 下是 fat file 掷豺, 支持 arm7arm64捞烟。


-create
上面生成的庫,要么是只支持模擬器的当船,要么是只支持真機的题画,那么如何才能又能兼顧真機和模擬器呢? -create 使用方式:

lipo -create 庫1 庫2 -output 新庫

使用結(jié)果如下圖:



-thin
如果有一個 fat file 但是你不需要支持那么多框架德频,也可以通過拆分苍息,為庫瘦身, -thin 使用方式:

lipo 舊庫 -thin 需拆分框架 -output 新庫

使用結(jié)果如下圖:



bundle

framework 中使用 storyboard/xib 創(chuàng)建的頁面壹置,可以直接訪問 framework 中圖片資源竞思。但是 framework 中通過imageNamed:
方式加載的照片都會丟失。這是因為 imageNamed:
的方法默認是從 mainBundle
中查找資源的钞护,而 framework 中的照片是從 framework 內(nèi)部加載的盖喷,這是的 bundle 并不是 mainBundle
,而是存在于主程序的 docment 文件中的 framework 包难咕,圖片加載的路徑發(fā)生了變化课梳,自然找不到圖片資源,所以需要修改加載圖片的方法余佃!
一般的方法是創(chuàng)建一個 bundle :

image.png

bundle 一般和庫命名相同暮刃。需要注意的是, bundle 并不會被打包進庫中的爆土,而是添加要單獨添加到工程中椭懊,和 framework 相獨立的兩部分。向 bundle 中直接添加圖片:


先在主工程的 Copy Bundle Resources 中添加 bundle 步势,如下圖所示:


現(xiàn)在就可以通過[NSBundle mainBundle]
獲取圖片氧猬,一下兩種方式皆可:

[UIImage imageNamed:[[[NSBundle mainBundle] pathForResource:@"Frameworks" ofType:@"bundle"] stringByAppendingString:@"/Images/author.png"]];
[UIImage imageNamed:@"Frameworks.bundle/Images/author.png"];

修改bundle Setting

  • 修改Architectures中的Base SDK為latest IOS
9109394.png
  • 修改Build OptionsEnable BitcodeNO
image.png
  • 修改signingCode signing identityDon't Code Sign (在提交蘋果審核時背犯,bundle如果有任何簽名都會被拒)
image.png
  • 修改User-DefinedCOMBINE_HIDPI_IMAGES為NO(iOS 創(chuàng)建Bundle時放入的圖片資源(.png)在默認配置下會被轉(zhuǎn)為.tiff格式,使用的時候找不到狂窑。因為在iOS中創(chuàng)建bundle時會用一個“hack”媳板,為了使所有的運行需要更改一個配置。)
image.png

-在靜態(tài)庫中的Build PhasesTarget Dependencies添加Bundle泉哈。這樣以后編譯靜態(tài)庫時蛉幸,bundle會自動編譯。無需單獨再編譯

Target Dependencies Target依賴,某些Target可能依賴某個Target輸出的值,這里設置依賴
Copy Bundle Resources 是指生成的product的.app內(nèi)將包含哪些資源文件
Compile Sources 是指將有哪些源代碼被編譯
Link Binary With Libraries 是指編譯過程中會引用哪些庫文件

image.png

cocoapods打包庫

好了丛晦,終于到最后一部分了奕纫。前面已經(jīng)介紹了手動創(chuàng)建庫的方式,那么如何自動創(chuàng)建一個庫烫沙?另外一點匹层,前面提到過,在動態(tài)庫內(nèi)引入靜態(tài)庫锌蓄,會和項目本身由 cocoapods 引入的庫同名沖突升筏,如何消除這一沖突?以上問題都可以通過 cocoapods 打包庫實現(xiàn)

創(chuàng)建工程
只需要輸入 pod 的 lib
命令即可完成初始項目的搭建:

pod lib create StaticWithCocoapods

輸出指令后瘸爽,會提示確認五個問題您访,按需求回答即可:


稍等片刻,就會自動生成一個工程剪决。
配置信息
在項目目錄下有一個 xxx.podspec
配置文件灵汪,需要進行修改,摘錄如下:

Pod::Spec.new do |s|  
s.name             = 'StaticWithCocoapods'

s.version          = '0.1.0'  

s.summary          = 'A short description of StaticWithCocoapods.'

# This description is used to generate tags and improve search results.
#   * Think: What does it do? Why did you write it? What is the focus?#   * Try to keep it short, snappy and to the point.
#   * Write the description between the DESC delimiters below.
#   * Finally, don't worry about the indent, CocoaPods strips it!  

s.description      = <<-DESCTODO: Add long description of the pod here.                       DESC  

s.homepage         = 'https://github.com/zhang759740844'
  
s.license          = { :type => 'MIT', :file => 'LICENSE' }  

s.author           = { 'Zachary' => '759740844@qq.com' }  

s.source           = { :git => '/Users/zachary/Desktop/StaticWithCocoapods', :tag => s.version.to_s }  

s.ios.deployment_target = '8.0'  

s.source_files = 'StaticWithCocoapods/Classes/**/*' 

s.resource_bundles = {    'StaticWithCocoapods' => ['StaticWithCocoapods/Assets/*.png']  }  

s.public_header_files = 'StaticWithCocoapods/Classes/**/*.h' 

s.frameworks = 'UIKit', 'MapKit'  s.dependency 'AFNetworking', '~> 2.3'  

s.denpendency 'SVProgressHUD'end

s.version 表示的是當前類庫的版本號
s.source 表示當前類庫源
s.sources_files 表示類庫的源文件存放目錄
s.resource_bundles 表示資源文件存放目錄
s.frameworks 表示類庫依賴的framework
s.dependency 表示依賴的第三方類庫

其中要說明的是:

  • source 可以填寫遠端 git 倉庫柑潦,也可以是像我寫的那樣的本地 git 倉庫享言。
  • 依賴項不僅要包含你自己類庫的依賴,還要包括所有第三方類庫的依賴渗鬼,只有這樣當你的類庫打包成 .a 或 .framework 時才能讓其他項目正常使用览露。
  • source_file 路徑中出現(xiàn)的通配符 *表示匹配任意字符, **表示匹配所有當前文件夾和子文件夾譬胎。
  • source_bundles 中花括號內(nèi)的 'StaticWithCocoapods'
    就表示一個 StaticWithCocoapods
    bundle差牛。

添加文件
sources_filespublic_header_files 以及 resource_bundle 中添加圖片和類文件。在 demo 的文件夾下執(zhí)行 pod install
∫瘢現(xiàn)在打開 demo 工程,可以看到創(chuàng)建的 StaticWithCocoapods
庫的文件結(jié)構(gòu)如下圖:

到這里一切正常累舷,也可以使用 SVProgressHUD
浩考,但是當我想用 [UIImage imageNamed:[[[NSBundle mainBundle] pathForResource:@"StaticWithCocoapods" ofType:@"bundle"] stringByAppendingString:@"/author.png"]];
加載圖片資源文件時,一直返回 nil被盈。

好吧析孽。雖然網(wǎng)上cocoapods打包教程不少搭伤,但是真正試過添加圖片的人應該不多,最后在 Stackoverflow 的一個評論里總算找到了解決方法[Cocoapods]:Resource Bundle not accessbile

原先 demo 中 profile 的內(nèi)容如下:

use_frameworks

!target 'StaticWithCocoapods_Example' do
  pod 'StaticW', :path => '../'  

target 'StaticWithCocoapods_Tests' do    
inherit! :search_paths    
pod 'FBSnapshotTestCase'  
end

end

現(xiàn)在要刪除 use_frameworks!
以及其相關內(nèi)容袜瞬,變成這樣:

target 'StaticWithCocoapods_Example' do  
pod 'StaticWithCocoapods', :path => ‘../‘
end

再次嘗試加載圖片怜俐,可以得到正確結(jié)果. _


提交代碼

  • 使用 sourcetree 添加本地倉庫
  • 提交上面的所有改動
  • 為改動添加 tag 為 0.1.0

設置好后如圖:


這里要注意,tag 一定要打上邓尤,版本控制的時候就是以 tag 來辨別的拍鲤。


驗證類庫
開發(fā)完成靜態(tài)類庫之后,需要運行pod lib lint驗證一下類庫是否符合pod的要求汞扎。添加 --allow-warnings
忽略警告:


打包庫

打包庫需要一個 cocoapods 的插件 cocoapods-packager來完成類庫的打包季稳。
在終端執(zhí)行以下命令,安裝插件:

sudo gem install cocoapods-packager

在目標文件夾內(nèi)執(zhí)行以下命令澈魄,完成打包:

pod package StaticWithCocoapods.podspec --force

打包成 .framework景鼠,也可以用--library打包成 .a。不過 cocoapods 之前有過打包成 .a但是沒有暴露出頭文件的bug痹扇,懶得試有沒有修復了铛漓,所以還是都打成 .framework
吧。

現(xiàn)在在目標文件夾下就會多出一個 StaticWithCocoapods-0.2.0
目錄鲫构,里面是打包好的 framework 浓恶。至于如何將打包好的庫添加到 cocoapods的官方庫內(nèi),這個就沒有研究了芬迄,因為问顷,在很長的一段時間內(nèi)我都不會用到。有興趣的可以看看 cocoapods 的官方文檔禀梳,自行研究下杜窄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市算途,隨后出現(xiàn)的幾起案子塞耕,更是在濱河造成了極大的恐慌,老刑警劉巖嘴瓤,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扫外,死亡現(xiàn)場離奇詭異,居然都是意外死亡廓脆,警方通過查閱死者的電腦和手機筛谚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來停忿,“玉大人驾讲,你說我怎么就攤上這事。” “怎么了吮铭?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵时迫,是天一觀的道長。 經(jīng)常有香客問我谓晌,道長掠拳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任纸肉,我火速辦了婚禮溺欧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘毁靶。我一直安慰自己胧奔,他們只是感情好,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布预吆。 她就那樣靜靜地躺著龙填,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拐叉。 梳的紋絲不亂的頭發(fā)上岩遗,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音凤瘦,去河邊找鬼宿礁。 笑死,一個胖子當著我的面吹牛蔬芥,可吹牛的內(nèi)容都是我干的梆靖。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼笔诵,長吁一口氣:“原來是場噩夢啊……” “哼返吻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起乎婿,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤测僵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后谢翎,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捍靠,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年森逮,在試婚紗的時候發(fā)現(xiàn)自己被綠了榨婆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡褒侧,死狀恐怖良风,靈堂內(nèi)的尸體忽然破棺而出颜武,到底是詐尸還是另有隱情,我是刑警寧澤拖吼,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站这吻,受9級特大地震影響吊档,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜唾糯,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一怠硼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧移怯,春花似錦香璃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嵌溢,卻和暖如春眯牧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赖草。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工学少, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秧骑。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓版确,卻偏偏與公主長得像,于是被迫代替她去往敵國和親乎折。 傳聞我的和親對象是個殘疾皇子绒疗,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容