前言
本文旨在記錄自制framework的過(guò)程斗忌、碰到的各種問(wèn)題及解決方法
目標(biāo)是制作一個(gè)帶bundle資源的framework,并在新App里能使用這個(gè)framework市栗,所以使用xcode創(chuàng)建項(xiàng)目這里只討論App缀拭、framework和bundle
一、Products目錄索引
不管是創(chuàng)建App還是framework填帽、bundle蛛淋,使用xcode創(chuàng)建會(huì)在根目錄下生成Products索引,編譯后的目標(biāo)文件索引最后都會(huì)出現(xiàn)在這個(gè)Products索引里篡腌,要找到目標(biāo)文件只需要選中索引然后右鍵Show in Finder就可以了褐荷。但是使用Xcode13創(chuàng)建項(xiàng)目卻不顯示Products目錄了,這里記錄一種把Products目錄顯示出來(lái)的方法嘹悼。
使用Xcode13新建了一個(gè)名為CustomProject 的新項(xiàng)目
cd /Users/user/Desktop/MobileProject-Swift/CustomProject? ? ? ? ?//進(jìn)到項(xiàng)目根目錄
open CustomProject.xcodeproj/project.pbxproj? ? ? ? //打開(kāi)project.pbxproj文件
在打開(kāi)的project.pbxproj文件搜索“productRefGroup”關(guān)鍵字叛甫,搜索結(jié)果可能有多個(gè),每個(gè)項(xiàng)目的鍵值不一樣具體看項(xiàng)目杨伙,找到匹配對(duì)象其监,后面跟著“/* Products */”后綴的才是要修改的
把mainGroup等號(hào)右邊的值復(fù)制到productRefGroup等號(hào)右邊限匣,cmd+s保存抖苦,Xcode會(huì)自動(dòng)刷新,Products索引就可以顯示出來(lái)了。
不管是創(chuàng)建App還是framework锌历、bundle贮庞,沒(méi)有Products索引的話都可以通過(guò)這種方法顯示出來(lái),在找目標(biāo)文件時(shí)會(huì)方便很多究西。
PS:??xcode? ?>>>? ?Product? ?>>>? ?Show Build Folder in Finder
二窗慎、制作資源bundle
1、添加bundle
選中項(xiàng)目怔揩,添加bundle捉邢,也可以跟創(chuàng)建項(xiàng)目一樣,另起一個(gè)新項(xiàng)目(快捷鍵shift + cmd + n)創(chuàng)建一個(gè)只有bundle的項(xiàng)目商膊。
2伏伐、修改配置參數(shù)
注意選中的TARGETS是CustomBundle,而不是CustomProject
TARGETS? ? >>>????General????>>>????Deployment Info ????設(shè)置設(shè)備和最低支持版本(Xcode13只有一個(gè)Deployment Target可選)
TARGETS????>>>????Build Settings????>>>????BaseSDK ???? 改成 iOS
TARGETS????>>>????Build Settings????>>>????Supported Platforms ????改成 iOS
TARGETS????>>>????Build Settings????>>>????Enable Bitcode ???? 改成 NO
TARGETS????>>>????Build Settings????>>>????Versioning System? ? ? 改為None(為了去掉構(gòu)建后Bundle里的可執(zhí)行文件exec)
TARGETS????>>>????Build Settings????>>>????COMBINE_HIDPI_IMAGES ???? 改為NO(否則Bundle圖片會(huì)變?yōu)閠iff格式)
3晕拆、添加資源(圖片藐翎、音頻、視頻实幕、xib吝镣、plist等)
把需要的資源拖進(jìn)bundle目錄索引下
Xcode13新建bundle的時(shí)候左側(cè)目錄欄不會(huì)生成目錄索引,資源可以直接拖進(jìn)Build Phases下的Copy Bundle Resources里昆庇,拖進(jìn)去的資源會(huì)直接出現(xiàn)在根目錄索引下末贾,也可以在根目錄下新建一個(gè)目錄索引,把資源都拖進(jìn)去整吆,然后在Copy Bundle Resources把資源添加進(jìn)去拱撵。
不推薦使用Assets或者Image Set,創(chuàng)建的名稱與圖片的真實(shí)名稱可能不一樣表蝙,用的時(shí)候會(huì)找不到目標(biāo)資源
4拴测、編譯生成.bundle文件
編譯前目錄里的CustomBundle索引是紅色的,表示還沒(méi)有生成真正的.bundle文件府蛇,參考上面的圖集索,Scheme選擇CustomBundle,Build選擇Any iOS Device然后cmd + b編譯汇跨,編譯后生成CustomBundle.bundle文件务荆,目錄里的索引變?yōu)楹谏?/p>
選中目錄里的CustomBundle索引,右鍵show in Finder打開(kāi).bundle文件所在目錄穷遂,把CustomBundle.bundle文件拷貝一份放到單獨(dú)的地方蛹含,后續(xù)要把它放到生成的framework里使用
三、制作framework
1塞颁、添加framework
選中項(xiàng)目浦箱,添加framework吸耿,也可以跟創(chuàng)建項(xiàng)目一樣,另起一個(gè)新項(xiàng)目(快捷鍵shift + cmd + n)創(chuàng)建一個(gè)只有framework的項(xiàng)目酷窥。
建議單獨(dú)創(chuàng)建framework項(xiàng)目咽安,原因后面會(huì)說(shuō)到。
2蓬推、修改配置參數(shù)
注意選中的TARGETS是CustomFramework妆棒,而不是CustomProject
TARGETS????>>>????General????>>>????Deployment Info ????設(shè)置設(shè)備和最低支持版本
TARGETS????>>>????Build Settings????>>>????BaseSDK ???? 改成 iOS
TARGETS????>>>????Build Settings????>>>????Supported Platforms ????改成 iOS
TARGETS????>>>????Build Settings????>>>????Build Active Architecture Only ????改成 NO(表示支持所有架構(gòu))
TARGETS????>>>????Build Settings????>>>? ? Architectures? ? ?添加 armv7s (表示支持真機(jī)32位處理器,沒(méi)有特殊要求沸伏,用默認(rèn)即可)
TARGETS????>>>????Build Settings????>>>? ? Excluded? Architectures? ?Debug或Release下添加Any iOS Simulator SDK糕珊,值為arm64(在模擬器下排除arm64架構(gòu),原因后面會(huì)說(shuō)到)??
TARGETS????>>>????Build Settings????>>>????Dead Code Stripping? ? ?改成 NO? 無(wú)效代碼剝離毅糟,是一項(xiàng)優(yōu)化技術(shù)红选,用于在iOS應(yīng)用程序構(gòu)建過(guò)程中刪除未使用的代碼,以減小最終應(yīng)用的大小姆另。但是對(duì)于framework來(lái)說(shuō), 應(yīng)該設(shè)置為NO, 避免代碼喇肋、調(diào)試符號(hào)等被剝離
TARGETS????>>>????Build Settings????>>>????Link With Standard Libraries? ? ?改成 NO
TARGETS????>>>????Build Settings????>>>????Mach-O Type ????改為 Static Library (靜態(tài)庫(kù)的意思,只有系統(tǒng)的framework里有的是動(dòng)態(tài)庫(kù)迹辐,自制的都是靜態(tài)庫(kù))
TARGETS????>>>????Build Settings????>>>????Other Linker Flags ???? 添加-ObjC(如果用了分類加這個(gè)參數(shù))
TARGETS????>>>????Build Settings????>>>????Build Libraries for Distribution? ?改成 YES? 為了確保生成的庫(kù)文件包含必要的接口文件蝶防,以便于向下兼容性。這個(gè)選項(xiàng)告訴編譯器生成 ".swiftinterface" 文件明吩,這對(duì)于將來(lái)使用低版本的 Swift 編譯器加載舊版本庫(kù)非常重要间学。
Other Linker Flags的參數(shù)說(shuō)明:
編譯過(guò)程:從C代碼到可執(zhí)行文件經(jīng)歷的步驟是:源代碼 > 預(yù)處理器 > 編譯器 > 匯編器 > 機(jī)器碼 > 鏈接器 > 可執(zhí)行文件
在最后一步需要把.o文件和C語(yǔ)言運(yùn)行庫(kù)鏈接起來(lái),這時(shí)候需要用到ld命令印荔。源文件經(jīng)過(guò)一系列處理以后菱鸥,會(huì)生成對(duì)應(yīng)的.obj文件,然后一個(gè)項(xiàng)目必然會(huì)有許多.obj文件躏鱼,并且這些文件之間會(huì)有各種各樣的聯(lián)系,例如函數(shù)調(diào)用殷绍。鏈接器做的事就是把這些目標(biāo)文件和所用的一些庫(kù)鏈接在一起形成一個(gè)完整的可執(zhí)行文件染苛。Other linker flags設(shè)置的值實(shí)際上就是ld命令執(zhí)行時(shí)后面所加的參數(shù)
-ObjC:讓鏈接器把靜態(tài)庫(kù)中所有的類和分類都加載到最后的可執(zhí)行文件中,因?yàn)榧虞d了其他的代碼主到,會(huì)導(dǎo)致編譯之后的App變大茶行,但是如果靜態(tài)庫(kù)中有類和分類的話只有加入這個(gè)flag才行。
-all_load:讓鏈接器把靜態(tài)庫(kù)中所有找到的目標(biāo)文件都加載到可執(zhí)行文件中登钥,這個(gè)flag是專門(mén)處理-ObjC的一個(gè)bug的畔师,用了-ObjC以后,如果類庫(kù)中只有分類沒(méi)有類的時(shí)候這些分類還是加載不進(jìn)來(lái)牧牢。變通方法就是加入-all_load或者-force-load看锉。
注意:假如使用了不止一個(gè)靜態(tài)庫(kù)文件姿锭,然后又使用了這個(gè)參數(shù),很有可能會(huì)遇到?ld: duplicate symbol?錯(cuò)誤伯铣,因?yàn)椴煌膸?kù)文件里面可能會(huì)有相同的目標(biāo)文件
-force_load:所做的事情跟-all_load其實(shí)是一樣的呻此,但是需要指定要進(jìn)行全部加載的庫(kù)文件的路徑,這樣只是完全加載了一個(gè)庫(kù)文件腔寡,不影響其余庫(kù)文件的按需加載
3焚鲜、把bundle添加到framework
找到上面生成的CustomBundle.bundle文件,拖入工程并連接到CustomFramework的target中
如果沒(méi)有這一步放前,每次編譯生成的framework里是沒(méi)有.bundle文件的忿磅,需要單獨(dú)添加進(jìn)去,編譯一次就需要添加一次
這樣做的好處是每次重新編譯生成framework時(shí)凭语,.bundle文件都會(huì)被自動(dòng)引入到framework中葱她,無(wú)需關(guān)注是否單獨(dú)添加的問(wèn)題
4、設(shè)置framework頭文件
把功能文件添加到framework里叽粹,如果是OC的文件览效,需要指定外部可以引用的頭文件,兩種方法
方法一:選中需要暴露的頭文件虫几,在Xcode右側(cè)的Target Membership中把Project改為Public
方法二:選中整個(gè)項(xiàng)目,找到TARGETS下的CustomFramework辆脸,選擇Build Phases下的Headers并點(diǎn)開(kāi)但校,選中需要暴露的頭文件直接拖拽到Public選項(xiàng)下
然后在framework的頭文件里引入所有供外部引用文件的頭文件,有幾個(gè)引入幾個(gè)
如果是swift的文件啡氢,需要使用public或open關(guān)鍵字讓需要暴露的類/方法/屬性暴露出來(lái)
關(guān)于public和open的區(qū)別,主要在于能否繼承或override
1倘是、public修飾的class只允許外部模塊調(diào)用亭枷,但是不允許繼承; 而open修飾的class既允許其他模塊調(diào)用搀崭,也允許被子類繼承叨粘。
2、public修飾的成員只允許其他模塊調(diào)用瘤睹,但不能被覆蓋(override)升敲;而open修飾的成員既允許被其他模塊調(diào)用,也允許成員被覆蓋轰传。
3驴党、如果class聲明為public,那么class的成員變量不能為open获茬,因?yàn)閜ublic class已被限定為不可繼承港庄。
4倔既、如果class聲明為open,其他模塊繼承覆蓋(override)父類的成員時(shí)攘轩,也需要把成員聲明為open叉存。
下面的問(wèn)題就是bundle里的資源該如何使用,需要根據(jù)路徑先找到bundle度帮,然后加載bundle實(shí)例歼捏,再使用實(shí)例中需要的資源
5笨篷、編譯framework
首先要明確編譯framework是有Debug和Release兩種模式的瞳秽,切換模式通過(guò)Edit Scheme來(lái)實(shí)現(xiàn)
選中Xcode? ? ?>>>? ? Product? ? >>>? ? Scheme? ? >>>? ? Edit Scheme
或者在Xcode頂部工具欄的Scheme里選擇Edit Scheme
在彈出的面板里先選擇目標(biāo)framework再選左側(cè)的Run,最后選擇Debug還是Release
選擇模式后關(guān)閉面板率翅,回到Xcode练俐,Scheme選擇CustomFramework,Build選擇Any iOS Device然后cmd + b編譯冕臭,編譯后就會(huì)生成CustomFramework.framework文件
到這一步并不算完腺晾,因?yàn)楝F(xiàn)在編譯得到的framework在模擬器下并不能使用,選中CustomFramework右鍵Show in Finder會(huì)發(fā)現(xiàn)辜贵,根據(jù)Scheme選擇Debug和Release兩種模式的不同悯蝉,這一步只會(huì)生成Debug-iphoneos或Release-iphoneos兩種真機(jī)環(huán)境下的framework?
為了使編譯得到的framework能在模擬器和真機(jī)下都能使用,需要分別在模擬器和真機(jī)下編譯托慨,再把得到的framework文件合并鼻由,要達(dá)到目的有兩種方法:
方法一:分別在真機(jī)、模擬器下編譯得到兩個(gè)framework厚棵,然后使用lipo命令合并為一個(gè)
先分別編譯蕉世,編譯后選中CustomFramework右鍵Show in Finder,得到兩個(gè)framework文件婆硬,這里用的Release模式下的文件狠轻,Debug模式下同理。
打開(kāi)終端輸入命令彬犯,注意空格:
?lipo -create 模擬器下framework文件路徑 真機(jī)下framework文件路徑 -output 新的路徑
如果Xcode版本是12以上向楼,到這一步可能會(huì)出錯(cuò):
fatal error: /Library/Developer/CommandLineTools/usr/bin/lipo: 模擬器下framework文件路徑 and 真機(jī)下framework文件路徑 have the same architectures (arm64) and can't be in the same fat output file
這是因?yàn)閒ramework所支持的架構(gòu)沖突導(dǎo)致的,正常打包的framework都會(huì)需要支持i386躏嚎、armv7、x86_64菩貌、arm64等卢佣,Xcode12以后模擬器編譯生成的framework中也會(huì)包含arm64,因此在合并的時(shí)候就會(huì)出現(xiàn)這個(gè)錯(cuò)誤
可以使用以下命令查看編譯出來(lái)的framework所支持的架構(gòu)
lipo -info framework文件路徑
可以看到都有arm64虚茶,所以在合并的時(shí)候沖突了戈鲁,解決方法就是在模擬器編譯framework時(shí)把a(bǔ)rm64架構(gòu)排除在外
TARGETS? ? ?>>>? ? Build Settings? ? >>>? ? Excluded Architectures? ? >>>? ? 添加Any iOS Simutator SDK,值為arm64
Excluded就有排除的意思嘹叫,這里設(shè)置在模擬器編譯的時(shí)候把a(bǔ)rm64架構(gòu)排除在外婆殿,如果是編譯Debug下的framework就在Debug下添加arm64,如果是編譯Release下的framework就在Release下添加arm64,添加好后重新編譯framework或粮,再使用lipo命令合并就不會(huì)報(bào)錯(cuò)了硝岗。
合并后會(huì)生成一個(gè)后綴是.lipo的文件
去掉后綴命浴,名字改成framework文件的名字(這里叫CustomFramework),替換掉CustomFramework.framework里的CustomFramework文件
如果合并的是Debug模式下的文件扯躺,就替換Debug模式下的iphoneos里的文件倍啥,如果合并的是Release模式下的就替換Release模式下的iphoneos里的文件蒲稳,
另外Modules文件夾里的文件也需要復(fù)制一份剩胁,放到替換了CustomFramework文件的Modules文件夾中,
替換后的CustomFramework.framework就是最終需要的framework建车,可以在真機(jī)和模擬器上使用康谆。
方法二:使用Script腳本
1月洛、創(chuàng)建Aggregate
2惜辑、添加腳本
TARGETS????>>>????Build Phases????>>>????左上角+????>>>????New Run Script Phase
在新建的Run Script 窗口里添加生成framework的腳本代碼
#!/bin/sh
#要build的target名
TARGET_NAME=${PROJECT_NAME}
if [[ $1 ]]
then
TARGET_NAME=$1
fi
UNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/${PROJECT_NAME}/"
#創(chuàng)建輸出目錄,并刪除之前的framework文件
mkdir -p "${UNIVERSAL_OUTPUT_FOLDER}"
rm -rf "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework"
#分別編譯模擬器和真機(jī)的Framework
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
#拷貝framework到univer目錄
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework" "${UNIVERSAL_OUTPUT_FOLDER}"
lipo "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" -remove arm64 -output "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}"
#合并framework介粘,輸出最終的framework到build目錄
lipo -create -output "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework/${TARGET_NAME}"
#刪除編譯之后生成的無(wú)關(guān)的配置文件
dir_path="${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/"
for file in ls $dir_path
do
if [[ ${file} =~ ".xcconfig" ]]
then
rm -f "${dir_path}/${file}"
fi
done
#判斷build文件夾是否存在,存在則刪除
if [ -d "${SRCROOT}/build" ]
then
rm -rf "${SRCROOT}/build"
fi
rm -rf "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator" "${BUILD_DIR}/${CONFIGURATION}-iphoneos"
#打開(kāi)合并后的文件夾
open "${UNIVERSAL_OUTPUT_FOLDER}"
可以看到腳本所做的事情也是分別編譯真機(jī)和模擬器下的framework然后合并成一個(gè),合并完成后會(huì)打開(kāi)合并后的文件夾闰渔,得到的CustomFramework.framework就是最終需要的framework正蛙,可以在真機(jī)和模擬器上使用
3愚隧、注意
如果是單獨(dú)創(chuàng)建的framework項(xiàng)目鳄厌,到這一步確實(shí)拿到了需要的framework
如果是在一個(gè)app的項(xiàng)目里通過(guò)TARGETS左下角的加號(hào)創(chuàng)建的framework項(xiàng)目,framework項(xiàng)目目錄索引在app項(xiàng)目的根目錄索引下,這時(shí)候編譯運(yùn)行腳本是沒(méi)法得到需要的framework的,因?yàn)槟_本是根據(jù)PROJECT_NAME創(chuàng)建的framework輸出目錄鞍历,app項(xiàng)目與framework項(xiàng)目名稱肯定不一樣,編譯后生成framework的路徑也不一樣迅腔,腳本執(zhí)行的時(shí)候就會(huì)找不到目標(biāo)文件锌雀,導(dǎo)致合并后的文件夾里并沒(méi)有需要的framework侈贷,編譯不會(huì)報(bào)錯(cuò)嫁蛇,只不過(guò)沒(méi)得到想要的結(jié)果
所以想用又不想改腳本內(nèi)容的話,記得單獨(dú)創(chuàng)建framework項(xiàng)目就可以了
以上如果覺(jué)得麻煩雕凹,還有更簡(jiǎn)單的方式殴俱,官方在2019年推出了xcframework政冻,使用xcodebuild命令合并framework為xcframework
xcodebuild -create-xcframework -framework XXX.framework -framework XXX.framework -output XXX.xcframework
xcframework可以理解為對(duì)真機(jī)和模擬器下framework的管理,會(huì)在對(duì)應(yīng)的模式下自動(dòng)連接對(duì)應(yīng)的庫(kù)线欲。
四明场、在其他項(xiàng)目中使用自制的framework
新建一個(gè)App項(xiàng)目,在這個(gè)項(xiàng)目里測(cè)試得到的CustomFramework.framework李丰。
從iOS13開(kāi)始Xcode新增了SceneDelegate來(lái)管理UI的生命周期榕堰,更適合開(kāi)發(fā)ipad多場(chǎng)景應(yīng)用,單場(chǎng)景的可以不用這個(gè)嫌套,先把SceneDelegate相關(guān)的東西刪掉
初始化window,設(shè)置根控制器圾旨,把自制的framework和測(cè)試項(xiàng)目放到同一個(gè)目錄下踱讨,通過(guò)下圖中的方法在測(cè)試項(xiàng)目里引入自制的framework,引入后左側(cè)目錄索引會(huì)自動(dòng)生成Frameworks目錄索引砍的,并且CustomFramework.framework已加入其中痹筛。
bundle資源也要加入到測(cè)試項(xiàng)目里
引入CustomFramework,編寫(xiě)測(cè)試代碼
在模擬器運(yùn)行代碼廓鞠,可能會(huì)報(bào)錯(cuò)
可以通過(guò)下圖的方法解決這個(gè)報(bào)錯(cuò)
大致的解釋是從Xcode的角度來(lái)看帚稠,iOS和iOS模擬器是兩個(gè)不同的平臺(tái),原來(lái)framework是默認(rèn)雙平臺(tái)的床佳,會(huì)同時(shí)構(gòu)建兩個(gè)平臺(tái)的framework滋早,現(xiàn)在是做區(qū)分,這樣的好處是可以在上傳Appstore構(gòu)建的時(shí)候省去剝離iOS模擬器相關(guān)的framework需求砌们。
結(jié)尾
到這里整個(gè)制作framework的流程基本就介紹完了杆麸。
靜態(tài)庫(kù)能在提供一定可復(fù)用功能的同時(shí)又能不暴露內(nèi)部實(shí)現(xiàn)的過(guò)程(swift語(yǔ)言制作的靜態(tài)庫(kù)可以看到內(nèi)部實(shí)現(xiàn)過(guò)程),這是靜態(tài)庫(kù)的優(yōu)勢(shì)浪感,但同樣的高度定制和復(fù)雜的東西出問(wèn)題的可能性也更大昔头,隨著版本更迭一個(gè)小問(wèn)題也可能會(huì)變得很麻煩,所以相對(duì)應(yīng)的文檔和更新記錄就比較重要影兽,一個(gè)成熟的庫(kù)說(shuō)明文檔和更新記錄都必不可少揭斧。
- 文/潘曉璐 我一進(jìn)店門(mén)蘸泻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)食铐,“玉大人,你說(shuō)我怎么就攤上這事狰腌〕疲” “怎么了?”我有些...
- 文/不壞的土叔 我叫張陵琼腔,是天一觀的道長(zhǎng)瑰枫。 經(jīng)常有香客問(wèn)我,道長(zhǎng)丹莲,這世上最難降的妖魔是什么光坝? 我笑而不...
- 正文 為了忘掉前任,我火速辦了婚禮甥材,結(jié)果婚禮上盯另,老公的妹妹穿的比我還像新娘。我一直安慰自己洲赵,他們只是感情好鸳惯,可當(dāng)我...
- 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著叠萍,像睡著了一般芝发。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上苛谷,一...
- 那天辅鲸,我揣著相機(jī)與錄音,去河邊找鬼腹殿。 笑死瓢湃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赫蛇。 我是一名探鬼主播绵患,決...
- 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼悟耘!你這毒婦竟也來(lái)了落蝙?” 一聲冷哼從身側(cè)響起,我...
- 序言:老撾萬(wàn)榮一對(duì)情侶失蹤暂幼,失蹤者是張志新(化名)和其女友劉穎筏勒,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體旺嬉,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡管行,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了邪媳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捐顷。...
- 正文 年R本政府宣布叮姑,位于F島的核電站唉地,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏传透。R本人自食惡果不足惜耘沼,卻給世界環(huán)境...
- 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望朱盐。 院中可真熱鬧群嗤,春花似錦、人聲如沸托享。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)闰围。三九已至,卻和暖如春既峡,著一層夾襖步出監(jiān)牢的瞬間羡榴,已是汗流浹背。 一陣腳步聲響...
- 正文 我出身青樓传惠,卻偏偏與公主長(zhǎng)得像迄沫,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子卦方,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- 1羊瘩、armv7,armv7s,arm64,i386,x86_64概念 制作靜態(tài)庫(kù)之前回顧一遍基礎(chǔ)概念(按各自需...
- .a /.framework /.bundle 理解與使用 前言: 為了防止世界被破壞,為了維護(hù)宇宙的和平盼砍,遂決定...
- 一尘吗、a庫(kù)封裝 1.1 創(chuàng)建工程 1.2添加需要封裝的代碼文件 1.3 添加對(duì)外開(kāi)放的頭文件選中Targets-B...
- iOS 庫(kù).a 和 framework的區(qū)別和創(chuàng)建 AlexYangle關(guān)注 1.92018.04.20 15:1...
- 轉(zhuǎn)載請(qǐng)注明出處:http://www.reibang.com/p/04a7e28f11b9作者:紀(jì)小衰 frame...