2017最新版iOS SDK制作 集成及上線攻略(非demo級(jí)別)

本文系原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處,謝謝 !

前一段時(shí)間因公司業(yè)務(wù)需要,提了這樣一個(gè)需求:要把一個(gè)早期的項(xiàng)目(創(chuàng)建于2013年,非本公司項(xiàng)目)整個(gè)做成SDK,集成到一個(gè)未知的項(xiàng)目里面去,而且還要上線.乍一聽,這個(gè)好像也沒什么難度,由于之前對(duì)靜態(tài)庫略有研究,于是爽快的跟老大說:能做!(當(dāng)時(shí)我還沒拿到源碼,也不知道需求方到底想要如何對(duì)接,對(duì)于主工程更是一無所知).于是接下來兩個(gè)月,本人由于自己的一時(shí)沖動(dòng),入了一個(gè)天坑,差點(diǎn)沒爬出來.現(xiàn)在此項(xiàng)目已完結(jié),在此把自己近2個(gè)月踩過的坑,做個(gè)總結(jié),同時(shí)與大家分享下經(jīng)驗(yàn).

為了更好的梳理思路,我先在此拋出幾個(gè)問題,大家一起思考:
  • 1.把一整個(gè)項(xiàng)目做成SDK,原來工程里面的哪些東西要去掉,AppDelegate還能要嗎,.pch ,宏定義,Categary這些怎么處理?

  • 2.推送注簿、分享之類的功能還能用嗎?

  • 3.如果源碼里面用了百度地圖,支付等第三方SDK,能正常的在我們自己的SDK里面調(diào)用并保證功能嗎?(簡(jiǎn)言之,SDK里面能包含SDK嗎)

  • 4.如果源碼內(nèi)容太多,模塊劃分清晰,我們要想按模塊劃分做成多個(gè)SDK,那我們自己做的SDK能互調(diào)嗎?

  • 5.資源文件(圖片酝静、xib)怎么處理,源碼里面有近500個(gè),難道要一個(gè)個(gè)修改路徑?

  • 6.如果原項(xiàng)目里面用.strings,.plist等一系列的本地文件,路徑該如何加載?

  • 7.在對(duì)于主工程一無所知的情況下,庫的兼容性問題如何解決?

  • 8.即使對(duì)接成功以后,SDK模塊各個(gè)功能顯示正常,可以成功打出ipa嗎?

  • 9.即使成功的打出了ipa,可以成功的上傳到AppStore嗎?

  • 10.即使成功的上傳到了AppStore,由于審核人員用iPad測(cè)試項(xiàng)目,如果因?yàn)镾DK模塊中使用了xib加載VC,而xib又沒有適配iPad,導(dǎo)致VC界面加載失敗,審核被拒,怎么辦?

  • ......

沒錯(cuò),以上這些問題都遇到了,而且還不止這些.
首先,客觀的說,SDK不是這么用的.

這個(gè)事情本身就是個(gè)變態(tài)的需求.其次SDK對(duì)于源碼是有要求的,不是隨隨便便給你拉來一套代碼,都能完美的把所有功能做成一個(gè)SDK,然后隨便那個(gè)項(xiàng)目需要,就給哪個(gè)項(xiàng)目調(diào)(這簡(jiǎn)直萬能啊,有木有) 也許有人會(huì)說了,支付寶魔策、百度地圖不就是這樣嗎?拜托,這些都是功能性的,沒有哪個(gè)SDK是包含多個(gè)定制化界面和接口等等一堆東西的.可是,這又怎么樣呢,自己挖的坑,跪著也要填完了.

前言到此結(jié)束,接下來我們言歸正傳.

(以上10個(gè)問題在下面都會(huì)給出答案)

(一) 方案

    1. 何種形式
      對(duì)于iOS而言,我的理解:
    • 靜態(tài)庫: .framework政敢、.a
      .framework = .a+bundle, so 我要做出來的,是個(gè) XXX.framework
    • 其實(shí).framework本質(zhì)上也是一個(gè)bundle,只是把資源和二進(jìn)制文件放在一起加載,主工程打包IPA的時(shí)候會(huì)有問題,如上問題8,所以這種方案我就略過了,免得誤導(dǎo)大家
    1. 做成幾個(gè)SDK
      一個(gè)! 無論主工程什么樣,暴露一個(gè)接口控制器和幾個(gè)屬性,是最簡(jiǎn)單高效的調(diào)用方法.而且通過本人實(shí)踐證明,我們自己做的SDK不能互調(diào) !!!同時(shí)回答上面問題4
    1. 創(chuàng)建一個(gè).framework工程,記得 創(chuàng)建以后 Build Setting-- Mach-O Type選擇 Static Lib

我創(chuàng)建的 SDK 叫NewCityKit,測(cè)試SDK的測(cè)試工程為 testFramework,下文中皆以此為例

SDK_2.png

SDK-3.png

(二) 源碼的準(zhǔn)備

    1. 準(zhǔn)備源碼
    • 下圖箭頭指向的這些文件統(tǒng)統(tǒng)都不要(AppDelegate,Assets.xcassets,Base.lproj,main,Resource,info.plist )
    • 把項(xiàng)目里面除了這些以外的源文件,添加到你創(chuàng)建的SDK工程里面,
    • 另外,需要把項(xiàng)目用到的圖片全部放到一個(gè)文件夾里面(如圖一中的pic),方便打包成bundle時(shí)選擇源文件
    • 建議源碼里面用到的xib越少越好,如果像我遇到的這樣,代碼老舊,模塊耦合性高,還非本公司的源碼,對(duì)業(yè)務(wù)邏輯不熟還不給時(shí)間重構(gòu)著急要上線的,那只能硬著頭皮弄了(出坑的關(guān)鍵還在于對(duì)于工作量的準(zhǔn)確評(píng)估和有一個(gè)給力的隊(duì)友)
SDK-1.png
    1. NewCityKit 里面解決報(bào)錯(cuò)問題,目標(biāo): 編譯通過
    • 在此回答問題1: AppDelegate ,.pch不能用,宏定義可以,分類也可以,但需要在主工程 Build Setting-- Other Linker Flags添加 -Objc灾馒、 -all -load
SDK-4.png
  • 問題2:本人認(rèn)為只在SDK里面配置,這些功能實(shí)現(xiàn)的可能性基本為0,除非主工程配合
  • 問題3:可以,本人做項(xiàng)目期間已經(jīng)把百度地圖集成進(jìn)SDK里面,并且可以正常調(diào)用,實(shí)踐證明可行(但是這也說明那些開源成熟的SDK可以被我們自己制作的SDK包含,但是我們自己做的就不行,這個(gè)本人目前還未想通,或許是都可以,還需要更多的嘗試).
  • 在源碼較多的情況下,要進(jìn)行到編譯通過這一步,還是頗費(fèi)周折的,具體的問題有很多,比如MRC問題啦,.m重復(fù)或者找不到啦等等的,總之根據(jù)Xcode報(bào)錯(cuò)信息去解決,基本都沒什么問題的

(三) 資源的處理

    1. 處理資源文件 (本人創(chuàng)建的資源bundle 名為NewCityAsset,下文中都以此為例)
bundle-1.png
bundle-2.png
bundle-3.png
bundle-4.png
bundle-5.png
 * 在此回答`問題5`: 圖片不需要一個(gè)個(gè)修改路徑,但是xib需要
iOS的資源后綴都是@2X,@3X的格式,編譯成為bundle以后,會(huì)變成.tiff格式,這樣你原來寫的路徑圖片名稱后面必須在再上這個(gè)后綴才能取到,這樣就又麻煩了,這個(gè)問題我們可以在資源的target修改一個(gè)地方,就可以完美解決,如下圖:
bundle-6.png
  • 圖片用以下代碼做處理
寫 一個(gè)加載bundle的工具類

#import "BundleTools.h"
#define BUNDLE_NAME @"NewCityAsset"

@implementation BundleTools
+ (NSBundle *)getBundle{
    
    return [NSBundle bundleWithPath: [[NSBundle mainBundle] pathForResource: BUNDLE_NAME ofType: @"bundle"]];
}

+ (NSString *)getBundlePath: (NSString *) assetName{
    
    NSBundle *myBundle = [BundleTools getBundle];
    
    if (myBundle && assetName) {
        
        return [[myBundle resourcePath] stringByAppendingPathComponent: assetName];
    }
    
    return nil;
}
 

給UIImage寫一個(gè)分類,用運(yùn)行時(shí)替換掉系統(tǒng)的 imageNamed: 方法


#import "UIImage+load.h"
#import "BundleTools.h"
#import <objc/runtime.h>
@implementation UIImage (load)

+(void)load{

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method m1 = class_getClassMethod([UIImage class], @selector(imageNamed:));
        Method m2 = class_getClassMethod([UIImage class], @selector(WB_imageNamed:));
        method_exchangeImplementations(m1, m2);
    });
}

+ (UIImage *)WB_imageNamed:(NSString *)name{

    UIImage *image = [UIImage WB_imageNamed:name];
    
    if (image) {
        return image;
    }else{
        return [UIImage imageNamed:name inBundle:[BundleTools getBundle] compatibleWithTraitCollection:nil];
    }

}

至此,圖片資源處理完畢.

  • xib 分為2種:
    • 顯示cell的xib(此種沒有更好的辦法,只能替換[NSBundle mainBundle] 為 [BundleTools getBundle]
  
//替換前
    [self.collectionView registerNib:[UINib nibWithNibName:@"CollectionViewCell" bundle: [NSBundle mainBundle]] forCellWithReuseIdentifier:@"CollectionViewCell"];
//替換后
    [self.collectionView registerNib:[UINib nibWithNibName:@"CollectionViewCell" bundle:[BundleTools getBundle]] forCellWithReuseIdentifier:@"CollectionViewCell"];
 
  • 顯示與VC同名view的xib (此種可以用以下代碼來解決,原理同樣是運(yùn)行時(shí)替換系統(tǒng)方法)
#import "UIViewController+Bundle.h"
#import "BundleTools.h"
#import <objc/runtime.h>

@implementation UIViewController (Bundle)

+(void)load{
    
    Method m1 = class_getInstanceMethod([self class], @selector(init));
    Method m2 = class_getInstanceMethod([self class], @selector(v_init));
    method_exchangeImplementations(m1, m2);
    
}
- (instancetype)v_init {
    
    NSString *path = [[BundleTools getBundle] pathForResource:NSStringFromClass([self class]) ofType:@"nib"];
    
    if (path == nil)
        return [self v_init];
    else
        return [self initWithNibName:NSStringFromClass([self class]) bundle:[BundleTools getBundle]];
    
}

至此,資源文件處理完畢,但是mainBundle的坑到此還不算完......

  • 接著,我們用上面的問題6,來引出bundle的坑
    先上圖本地配置文件:
SDK-5.png
SDK-6.png
  • 先說 .strings,如果.string是以這樣的形式加載的,我們直接就簡(jiǎn)單粗暴,直接把這個(gè)文件拖入宿主工程,什么都不用改,.plist同理
 #define mLocalization(key, ...)     [NSString stringWithFormat: [[NSBundle mainBundle] localizedStringForKey:key value:@"" table:@"Localization"], ##__VA_ARGS__, nil]
  • 但是如果你不想這樣加載(不想向主工程暴露太多東西),你想加載SDK包里面的那個(gè)本地文件,那么,就要像加載圖片那樣,先找到mainBundle,再找到.framework,再找到這個(gè)文件,大體是這么個(gè)路徑

// 注意:二進(jìn)制文件的路徑,從這里找 @"NewCityKit.framework" 
NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle]pathForResource:@"NewCityKit.framework" ofType:nil]];
NSString* path = [bundle pathForResource:@"APIDecryptConfig" ofType:@"plist"];

// 資源的路徑,從這找 @"NewCityAsset.bundle"
NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle]pathForResource:@"NewCityAsset.bundle" ofType:nil]];
NSString* path = [bundle pathForResource:@"new_loading_black" ofType:@"gif"];

// 這個(gè)非常關(guān)鍵,千萬不要弄混了!!!

至此,問題6告一段落

  • 然后我們來說一下用運(yùn)行時(shí)替換系統(tǒng)方法 imageNamed:造成的坑
    • 這個(gè)當(dāng)時(shí)和主工程對(duì)接時(shí)直接導(dǎo)致的后果是:由于SDK和主工程都用了MJRefresh,直接造成兩邊的刷新的那個(gè)提示文字變成了英文的,如圖
SDK-7.png

這個(gè)問題的解決方案也有2個(gè):

  • 1.簡(jiǎn)單粗暴的,單獨(dú)把里面的.strings 文件在主工程重新拖一份,就是這個(gè)東西
SDK-8.png
  • 2.我們來看一下MJ 是怎么加載這個(gè)bundle的

 + (instancetype)mj_refreshBundle
{
    static NSBundle *refreshBundle = nil;
    if (refreshBundle == nil) {
        // 這里不使用mainBundle是為了適配pod 1.x和0.x
        refreshBundle = [NSBundle bundleWithPath:[[NSBundle bundleForClass:[MJRefreshComponent class]] pathForResource:@"MJRefresh" ofType:@"bundle"]];
    }
    return refreshBundle;
}

我們?cè)賮砜匆幌逻@個(gè)東西最終出現(xiàn)在了哪里

SDK-9.png

對(duì),是. framework!!! 而不是我們自制的.bundle大家知道怎么做了嗎,原理同上,不再一一贅述
至此,bundle的坑基本羅列完畢,在我集成SDK期間,這是出bug最多的地方,也是困擾時(shí)間最長(zhǎng)的,解決的關(guān)鍵就在于找對(duì)路徑,參考經(jīng)典庫,不得不說,MJ對(duì)于bundle的處理容錯(cuò)性還是很高的,值得我們深究一下原理

(四) 庫的兼容性問題

終于進(jìn)行到這個(gè)最大的坑:問題7

關(guān)于這個(gè)我又想拋出一個(gè)問題了:
  • 比如AFN,SDK和主工程都用了,那最終集成以后,主工程調(diào)用的是它自己的庫還是SDK的庫?
    其實(shí)這個(gè)問題我也不太確定,只能根據(jù)實(shí)際猜測(cè)一下,我覺得他是根據(jù)加載順序來的,加載到SDK模塊的時(shí)候,主工程的代碼也優(yōu)先調(diào)用SDK里面的庫(這是庫的版本不一樣的情況下,如果一樣,我也不知道了,反正一樣的話不會(huì)報(bào)錯(cuò))
    當(dāng)時(shí)我們遇到這樣一個(gè)問題:
    主工程用CocoaPods管理第三方庫,版本都是最新的,而我們的SDK沒有用pod ,庫的版本不詳,不過看樣子像是13年下的,然后,合到一起,就崩到了sessionManager的get方法那里......(unrecognized selector sent to class) 我們的網(wǎng)絡(luò)用的還是AFHTTPRequestOperation,AFHTTPSessionManager的get方法不一樣,怎么辦?
    • 改AFN方法? 改動(dòng)較大,時(shí)間不夠,隱患略高,而且SDK里面的網(wǎng)絡(luò)請(qǐng)求嵌套了加解密,牽一發(fā)而動(dòng)全身啊,不妥
    • 后經(jīng)高人指點(diǎn),找到了一個(gè)完美的解決辦法:修改SDK里面AFHTTPSessionManager的類名和文件名! OC為面向?qū)ο蟮恼Z言,類名改掉了,就不是同一個(gè)對(duì)象了,怎么也調(diào)不到我們的方法了吧,而且基本不影響我們?cè)瓉淼拇a!簡(jiǎn)直完美!!!
最后,關(guān)于這個(gè)問題做個(gè)小結(jié):在SDK和主工程不是同一撥人在臨近時(shí)間段內(nèi)開發(fā)的情況下,除非SDK源碼有時(shí)間重寫或者主工程照著SDK庫的版本來用,否則統(tǒng)一庫的版本幾乎是不可能的,那么這時(shí)解決兼容性問題我覺得可以用上述方法,簡(jiǎn)單而高效.
但是,SDK工程和主工程能否共用一套第三方庫呢,本人沒有嘗試pod是否可以用于SDK工程,如果可以的話,那么這個(gè)猜想是可行的.本人認(rèn)為,這是一個(gè)比較理想的集成SDK的方案,避免了庫版本不統(tǒng)一的問題,同時(shí)大大減小了主工程安裝包的大小,但是這種方案需要在客觀條件允許的情況下,才能實(shí)現(xiàn)

(五) 打包上線的問題

  • 1.打包ipa出錯(cuò): Found an unexpected Mach-O header code: 0x72613c21
    這個(gè)錯(cuò)誤請(qǐng)參考以下鏈接
    iOS 打包 "Found an unexpected Mach-O header code: 0x72613c21"報(bào)錯(cuò)

    • 原因基本上就是主工程的這個(gè)地方添加了二進(jìn)制文件(copy bundle resources只能添加資源,不能添加二進(jìn)制文件),導(dǎo)致打包失敗
  • 2 . upload to AppStore 失敗
    item 90171 ,item 90166,大家可以自行Google,資源NewCityAsset.bundle里有plist,可執(zhí)行文件(.m,.h,.exe,.o等等),去掉就好了

    1. 審核被拒
      這個(gè)真沒有啥好辦法呢,老老實(shí)實(shí)修改xib(主要是和VC同名的xib),適配iPad,這也是一個(gè)比較坑的地方,如果用的地方太多的話,那就要哭了......
最后給大家看一下SDK集成以后的文件目錄:
SDK-11.png

二進(jìn)制文件和資源分開的,雖然.framework里面包含了.bundle,但是主工程里2個(gè)都要拖進(jìn)來,為了能正常的在主工程添加資源(這個(gè)一定要添加,否則主工程調(diào)用SDK會(huì)出錯(cuò)的)

SDK-13.png
至此,本人將近2個(gè)月踩過的關(guān)于制作iOS SDK的關(guān)鍵坑,都已經(jīng)羅列完畢!!!

本人絞盡腦汁編寫了將近一天的時(shí)間,如果看完對(duì)你有幫助,請(qǐng)點(diǎn)個(gè)贊!

另外,關(guān)于如何暴露接口控制器,如何調(diào)用傳參等問題,本人覺得比較簡(jiǎn)單,就不細(xì)說了,不會(huì)的同學(xué)請(qǐng)自行搜索,也歡迎大家加我的微信,隨時(shí)交流探討

文章如有錯(cuò)誤之處,歡迎大家批評(píng)指正,謝謝 !

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末咏尝,一起剝皮案震驚了整個(gè)濱河市压语,隨后出現(xiàn)的幾起案子啸罢,更是在濱河造成了極大的恐慌,老刑警劉巖胎食,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扰才,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡厕怜,警方通過查閱死者的電腦和手機(jī)衩匣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粥航,“玉大人琅捏,你說我怎么就攤上這事〉萑福” “怎么了柄延?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)缀程。 經(jīng)常有香客問我搜吧,道長(zhǎng),這世上最難降的妖魔是什么杨凑? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任滤奈,我火速辦了婚禮,結(jié)果婚禮上蠢甲,老公的妹妹穿的比我還像新娘僵刮。我一直安慰自己,他們只是感情好鹦牛,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勇吊,像睡著了一般曼追。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上汉规,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天礼殊,我揣著相機(jī)與錄音,去河邊找鬼针史。 笑死晶伦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的啄枕。 我是一名探鬼主播婚陪,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼频祝!你這毒婦竟也來了泌参?” 一聲冷哼從身側(cè)響起脆淹,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沽一,沒想到半個(gè)月后盖溺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铣缠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年烘嘱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝗蛙。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拙友,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出歼郭,到底是詐尸還是另有隱情遗契,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布病曾,位于F島的核電站牍蜂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏泰涂。R本人自食惡果不足惜鲫竞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望逼蒙。 院中可真熱鬧从绘,春花似錦、人聲如沸是牢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驳棱。三九已至批什,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間社搅,已是汗流浹背驻债。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留形葬,地道東北人合呐。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像笙以,于是被迫代替她去往敵國和親淌实。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,729評(píng)論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件翩伪、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,058評(píng)論 4 62
  • 1. 我是誰微猖? 我問自己。四周沒有任何東西缘屹,始終沒有凛剥。 好吧,那我就叫...迭漣吧轻姿。 ...
    邊城十三少閱讀 236評(píng)論 0 1
  • 文:雙木林兮 在去往無錫的路上犁珠,我的腦海中一直縈繞著《雷雨》中周樸園的低吟:無錫是個(gè)好地方,不由得心中對(duì)它充滿了無...
    雙木林兮閱讀 185評(píng)論 0 1