iOS開發(fā)知識儲備

iOS程序運行流程

系統(tǒng)調(diào)用app的main函數(shù)

  1. main函數(shù)調(diào)用UIApplicationMain.
  2. UIApplicationMain創(chuàng)建shared application instance, UIApplication默認(rèn)的instance.
  3. UIApplicationMain讀取Info.plist找到主nib文件, 加載nib勇哗,把shared application instance 設(shè)為nib的owner.
  4. 通過nib文件舟铜,創(chuàng)建app的獨立UIWindows object.
  5. 通過nib氓侧,實例化了程序的AppDelegate object.
  6. app內(nèi)部啟動結(jié)束,application:didFinishLaunchingWith- Options: 被設(shè)定成 wAppDelegate instance.
  7. AppDelegate向UIWindow instance發(fā)makeKeyAndVisible消息, app界面展示給用戶. app準(zhǔn)備好接收用戶的操作指令.

簡述應(yīng)用程序按Home鍵進入后臺時的生命周期导狡,以及從后臺回到前臺時的生命周期约巷?
應(yīng)用程序的狀態(tài):

  • Not running 未運行,程序沒啟動
  • Inactive 未激活旱捧,程序在前臺運行独郎,不過沒接受到事件,沒有事件處理的狀態(tài)下通常處于這個狀態(tài)枚赡。
  • Active 激活 程序在前臺并且接收到了事件
  • Backgound 后臺 程序在后臺而且能執(zhí)行代碼氓癌,大多數(shù)程序進入這個狀態(tài)后會在在這個狀態(tài)上停留一會。
  • Suspended 掛起 程序在后臺不能執(zhí)行代碼贫橙。
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
//告訴代理進程啟動但還沒進入狀態(tài)保存

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
// 告訴代理啟動基本完成程序準(zhǔn)備開始運行

-(void)applicationWillResignActive:(UIApplication *)application
// 當(dāng)應(yīng)用程序?qū)⒁敕腔顒訝顟B(tài)執(zhí)行贪婉,在此期間,應(yīng)用程序不接收消息或事件料皇,比如來電話了

-(void)applicationDidBecomeActive:(UIApplication *)application
// 當(dāng)應(yīng)用程序入活動狀態(tài)執(zhí)行谓松,這個剛好跟上面那個方法相反

-(void)applicationDidEnterBackground:(UIApplication *)application
// 當(dāng)程序被推送到后臺的時候調(diào)用。所以要設(shè)置后臺繼續(xù)運行践剂,則在這個函數(shù)里面設(shè)置即可

-(void)applicationWillEnterForeground:(UIApplication *)application
//當(dāng)程序從后臺將要重新回到前臺時候調(diào)用鬼譬,這個剛好跟上面的那個方法相反。

-(void)applicationWillTerminate:(UIApplication *)application
//當(dāng)程序?qū)⒁顺鍪潜徽{(diào)用逊脯,通常是用來保存數(shù)據(jù)和一些退出前的清理工作优质。這個需要要設(shè)置

UIApplicationExitsOnSuspend的鍵值。
-(void)applicationDidFinishLaunching:(UIApplication*)application

當(dāng)程序載入后執(zhí)行

描述應(yīng)用程序的啟動順序军洼?

1巩螃、程序入口main函數(shù)創(chuàng)建UIApplication實例和UIApplication代理實例
2、在UIApplication代理實例中重寫啟動方法匕争,設(shè)置第一ViewController
3避乏、在第一ViewController中添加控件,實現(xiàn)對應(yīng)的程序界面甘桑。

參考鏈接:http://www.reibang.com/p/bdf3f20848b9

iOS本地數(shù)據(jù)存儲都有哪幾種方式拍皮?iOS如何實現(xiàn)復(fù)雜對象的存儲歹叮?

  • NSKeyedArchiver(歸檔)采用歸檔的形式來保存數(shù)據(jù),該數(shù)據(jù)對象需要遵守NSCoding協(xié)議铆帽,并且該對象對應(yīng)的類必須提供encodeWithCoder:和initWithCoder:方法;
  • NSUserDefaults:用來保存應(yīng)用程序設(shè)置和屬性咆耿、用戶保存的數(shù)據(jù)。用戶再次打開程序或開機后這些數(shù)據(jù)仍然存在爹橱。NSUserDefaults可以存儲的數(shù)據(jù)類型包括:NSData萨螺、NSString、NSNumber愧驱、NSDate慰技、NSArray、NSDictionary;

Write寫入方式:永久保存在磁盤中;

  • SQLite(FMDB冯键、CoreData) ;
  • NSCoding + NSKeyedArchiver實現(xiàn)復(fù)雜對象的存儲;

堆和棧的區(qū)別惹盼?

  • 棧區(qū):(stack)由編譯器自動分配釋放,存放函數(shù)的參數(shù)值惫确、局部變量的值。
  • 堆區(qū):(heap)一般由程序員分配釋放蚯舱。
  • 全局區(qū):(靜態(tài)區(qū))(static) 全局變量和靜態(tài)變量改化。程序結(jié)束后由系統(tǒng)釋放。
  • 文字常量區(qū):: 常量字符串存放在這里枉昏。程序結(jié)束后由系統(tǒng)釋放陈肛。
  • 程序代碼區(qū): 存放函數(shù)體的二進制文件。
  • :只要棧的剩余空間大于所申請空間兄裂,系統(tǒng)將為程序提供內(nèi)存句旱,否則將報異常提示棧溢 出。
  • :首先應(yīng)該知道操作系統(tǒng)有一個記錄空閑內(nèi)存地址的鏈表晰奖,當(dāng)系統(tǒng)收到程序的申請時谈撒,會遍歷該鏈表,尋找第一個空間大于所申請空間的堆結(jié)點匾南,然后將該結(jié)點從空閑結(jié)點鏈表中刪除啃匿,并將該結(jié)點的空間分配給程序,另外蛆楞,對于大多數(shù)系統(tǒng)溯乒,會在這塊內(nèi)存空間中的首地址處記錄本次分配的大小,這樣豹爹,代碼中的delete語句才能正確的釋放本內(nèi)存空間裆悄。另外,由于找到的堆結(jié)點的大小不一定正好等于申請的大小臂聋,系統(tǒng)會自動的將多余的那部分重新放入空閑鏈表中光稼。

iOS類是否可以多繼承崖技?如果沒有,那可以用其他方法實現(xiàn)嗎钟哥?簡述實現(xiàn)過程
不可以迎献,可以通過消息轉(zhuǎn)發(fā)、delegate和protocol和類別來實現(xiàn)類似多繼承

KVO (Key-value observing)

  • KVO是觀察者模式的另一實現(xiàn)腻贰。

使用了isa混寫(isa-swizzling)來實現(xiàn)KVO
使用setter方法改變值KVO會生效吁恍,使用setValue:forKey即KVC改變值KVO也會生效,因為KVC會去調(diào)用setter方法

-(void)setValue:(id)value
{
    [self willChangeValueForKey:@"key"];
    [super setValue:value];
    [self didChangeValueForKey:@"key"];
}

那么通過直接賦值成員變量會觸發(fā)KVO嗎播演?
不會冀瓦,因為不會調(diào)用setter方法,需要加上
willChangeValueForKeydidChangeValueForKey方法來手動觸發(fā)才行

KVC(Key-value coding)

-(id)valueForKey:(NSString *)key;

-(void)setValue:(id)value forKey:(NSString *)key;

KVC就是指iOS的開發(fā)中写烤,可以允許開發(fā)者通過Key名直接訪問對象的屬性翼闽,或者給對象的屬性賦值。而不需要調(diào)用明確的存取方法洲炊。這樣就可以在運行時動態(tài)地訪問和修改對象的屬性感局。而不是在編譯時確定,這也是iOS開發(fā)中的黑魔法之一暂衡。很多高級的iOS開發(fā)技巧都是基于KVC實現(xiàn)的

當(dāng)調(diào)用setValue:屬性值 forKey:@”name“的代碼時询微,,底層的執(zhí)行機制如下:

程序優(yōu)先調(diào)用set<Key>:屬性值方法狂巢,代碼通過setter方法完成設(shè)置撑毛。注意,這里的<key>是指成員變量名唧领,首字母大小寫要符合KVC的命名規(guī)則藻雌,下同
如果沒有找到setName:方法,KVC機制會檢查+ (BOOL)accessInstanceVariablesDirectly方法有沒有返回YES斩个,默認(rèn)該方法會返回YES胯杭,如果你重寫了該方法讓其返回NO的話,那么在這一步KVC會執(zhí)行setValue:forUndefinedKey:方法萨驶,不過一般開發(fā)者不會這么做歉摧。所以KVC機制會搜索該類里面有沒有名為<key>的成員變量,無論該變量是在類接口處定義腔呜,還是在類實現(xiàn)處定義叁温,也無論用了什么樣的訪問修飾符,只在存在以<key>命名的變量核畴,KVC都可以對該成員變量賦值膝但。
如果該類即沒有set<key>:方法,也沒有_<key>成員變量谤草,KVC機制會搜索is<Key>的成員變量跟束。
和上面一樣莺奸,如果該類即沒有set<Key>:方法,也沒有
<key>和_is<Key>成員變量冀宴,KVC機制再會繼續(xù)搜索<key>和is<Key>的成員變量灭贷。再給它們賦值。
如果上面列出的方法或者成員變量都不存在略贮,系統(tǒng)將會執(zhí)行該對象的setValue:forUndefinedKey:方法甚疟,默認(rèn)是拋出異常。
即如果沒有找到Set<Key>方法的話逃延,會按照_key览妖,_iskey,key揽祥,iskey的順序搜索成員并進行賦值操作讽膏。

如果開發(fā)者想讓這個類禁用KVC,那么重寫+ (BOOL)accessInstanceVariablesDirectly方法讓其返回NO即可拄丰,這樣的話如果KVC沒有找到set<Key>:屬性名時府树,會直接用setValue:forUndefinedKey:方法。

當(dāng)調(diào)用valueForKey:@”name“的代碼時愈案,KVC對key的搜索方式不同于setValue:屬性值 forKey:@”name“挺尾,其搜
首先按get<Key>,<key>,is<Key>的順序方法查找getter方法,找到的話會直接調(diào)用站绪。如果是BOOL或者Int等值類型, 會將其包裝成一個NSNumber對象丽柿。

如果上面的getter沒有找到恢准,KVC則會查找countOf<Key>,objectIn<Key>AtIndex或<Key>AtIndexes格式的方法。如果countOf<Key>方法和另外兩個方法中的一個被找到甫题,那么就會返回一個可以響應(yīng)NSArray所有方法的代理集合(它是NSKeyValueArray馁筐,是NSArray的子類),調(diào)用這個代理集合的方法坠非,或者說給這個代理集合發(fā)送屬于NSArray的方法敏沉,就會以countOf<Key>,objectIn<Key>AtIndex或<Key>AtIndexes這幾個方法組合的形式調(diào)用。還有一個可選的get<Key>:range:方法炎码。所以你想重新定義KVC的一些功能盟迟,你可以添加這些方法,需要注意的是你的方法名要符合KVC的標(biāo)準(zhǔn)命名方法潦闲,包括方法簽名攒菠。
如果上面的方法沒有找到,那么會同時查找countOf<Key>歉闰,enumeratorOf<Key>,memberOf<Key>格式的方法辖众。如果這三個方法都找到卓起,那么就返回一個可以響應(yīng)NSSet所的方法的代理集合,和上面一樣凹炸,給這個代理集合發(fā)NSSet的消息戏阅,就會以countOf<Key>,enumeratorOf<Key>,memberOf<Key>組合的形式調(diào)用啤它。
如果還沒有找到奕筐,再檢查類方法+ (BOOL)accessInstanceVariablesDirectly,如果返回YES(默認(rèn)行為),那么和先前的設(shè)值一樣蚕键,會按_<key>,_is<Key>,<key>,is<Key>的順序搜索成員變量名救欧,這里不推薦這么做,因為這樣直接訪問實例變量破壞了封裝性锣光,使代碼更脆弱笆怠。如果重寫了類方法+ (BOOL)accessInstanceVariablesDirectly返回NO的話,那么會直接調(diào)用valueForUndefinedKey:方法誊爹,默認(rèn)是拋出異常蹬刷。
iOS用什么方式實現(xiàn)對一個對象的KVO?(KVO的本質(zhì)是什么频丘?)
利用RuntimeAPI動態(tài)生成一個子類办成,并且讓instance對象的isa指向這個全新的子類
當(dāng)修改instance對象的屬性時,會調(diào)用Foundation的_NSSetXXXValueAndNotify函數(shù)
willChangeValueForKey:
父類原來的setter
didChangeValueForKey:
內(nèi)部會觸發(fā)監(jiān)聽器(Oberser)的監(jiān)聽方法(observeValueForKeyPath:ofObject:change:context:)

屬性關(guān)鍵字

  • 1.讀寫權(quán)限:readonly,readwrite(默認(rèn))
  • 2.原子性: atomic(默認(rèn))搂漠,nonatomic迂卢。atomic讀寫線程安全,但效率低桐汤,而且不是絕對的安全而克,比如如果修飾的是數(shù)組,那么對數(shù)組的讀寫是安全的怔毛,但如果是操作數(shù)組進行添加移除其中對象的還员萍,就不保證安全了。
  • 3.引用計數(shù):

retain / strong

assign:修飾基本數(shù)據(jù)類型拣度,修飾對象類型時碎绎,不改變其引用計數(shù),會產(chǎn)生懸垂指針抗果,修飾的對象在被釋放后筋帖,assign指針仍然指向原對象內(nèi)存地址,如果使用assign指針繼續(xù)訪問原對象的話窖张,就可能會導(dǎo)致內(nèi)存泄漏或程序異常
weak:不改變被修飾對象的引用計數(shù)幕随,所指對象在被釋放后,weak指針會自動置為nil
copy:分為深拷貝和淺拷貝
淺拷貝:對內(nèi)存地址的復(fù)制宿接,讓目標(biāo)對象指針和原對象指向同一片內(nèi)存空間會增加引用計數(shù)
深拷貝:對對象內(nèi)容的復(fù)制赘淮,開辟新的內(nèi)存空間

  • 可變對象的copy和mutableCopy都是深拷貝
  • 不可變對象的copy是淺拷貝辕录,mutableCopy是深拷貝
    copy方法返回的都是不可變對象

分類、擴展梢卸、代理走诞、通知、KVO蛤高、KVC蚣旱、屬性

@property (nonatomic, copy) NSMutableArray * array;這樣寫有什么影響?

因為copy方法返回的都是不可變對象戴陡,所以array對象實際上是不可變的塞绿,如果對其進行可變操作如添加移除對象恤批,則會造成程序crash

frame 和 bounds 的區(qū)別是什么喜庞?

frame相對于父視圖,是父視圖坐標(biāo)系下的位置和大小诀浪。bounds相對于自身,是自身坐標(biāo)系下的位置和大小延都。
frame以父控件的左上角為坐標(biāo)原點,bounds以自身的左上角為坐標(biāo)原點

什么時候會發(fā)生「隱式動畫」晰房?

當(dāng)改變CALayer的一個可做動畫的屬性求摇,它并不能立刻在屏幕上體現(xiàn)出來.相反殊者,它是從先前的值平滑過渡到新的值幽污。這一切都是默認(rèn)的行為簿姨,你不需要做額外的操作,這就是隱式動畫

UIView 和 CALayer 之間的關(guān)系扁位?

UIView顯示在屏幕上歸功于CALayer域仇,通過調(diào)用drawRect方法來渲染自身的內(nèi)容,調(diào)節(jié)CALayer屬性可以調(diào)整UIView的外觀泼掠,UIView繼承自UIResponder择镇,CALayer不可以響應(yīng)用戶事件
UIView是iOS系統(tǒng)中界面元素的基礎(chǔ)腻豌,所有的界面元素都繼承自它。它內(nèi)部是由Core Animation來實現(xiàn)的虱疏,它真正的繪圖部分做瞪,是由一個叫CALayer(Core Animation Layer)的類來管理穿扳。UIView本身矛物,更像是一個CALayer的管理器履羞,訪問它的根繪圖和坐標(biāo)有關(guān)的屬性忆首,如frame被环,bounds等筛欢,實際上內(nèi)部都是訪問它所在CALayer的相關(guān)屬性
UIView有個layer屬性版姑,可以返回它的主CALayer實例剥险,UIView有一個layerClass方法,返回主layer所使用的類控乾,UIView的子類阱持,可以通過重載這個方法衷咽,來讓UIView使用不同的CALayer來顯示

+[UIView animateWithDuration:animations:completion:] 內(nèi)部大概是如何實現(xiàn)的蒜绽?
animateWithDuration:這就等于創(chuàng)建一個定時器
animations:這是創(chuàng)建定時器需要實現(xiàn)的SEL
completion:是定時器結(jié)束以后的一個回調(diào)block

iOS 的沙盒目錄結(jié)構(gòu)是怎樣的躲雅?

Application:存放程序源文件相赁,上架前經(jīng)過數(shù)字簽名钮科,上架后不可修改
Documents:常用目錄绵脯,iCloud備份目錄蛆挫,存放數(shù)據(jù),這里不能存緩存文件,否則上架不被通過
Library
Caches:存放體積大又不需要備份的數(shù)據(jù),SDWebImage緩存路徑就是這個
Preference:設(shè)置目錄悴侵,iCloud會備份設(shè)置信息
tmp:存放臨時文件可免,不會被備份巴元,而且這個文件下的數(shù)據(jù)有可能隨時被清除的可能

Push Notification推送 是如何工作的逮刨?

推送通知分為兩種,一個是本地推送,一個是遠程推送
本地推送:不需要聯(lián)網(wǎng)也可以推送,是開發(fā)人員在APP內(nèi)設(shè)定特定的時間來提醒用戶干什么

  • 推送的原理主要分為以下幾步:
  1. 由App向iOS設(shè)備發(fā)送一個注冊通知修己,用戶需要同意系統(tǒng)發(fā)送推送睬愤。
  2. iOS向APNs遠程推送服務(wù)器發(fā)送App的Bundle Id和設(shè)備的UDID尤辱。
  3. APNs根據(jù)設(shè)備的UDID和App的Bundle Id生成deviceToken再發(fā)回給App光督。
  4. App再將deviceToken發(fā)送給遠程推送服務(wù)器(自己的服務(wù)器), 由服務(wù)器保存在數(shù)據(jù)庫中结借。
  5. 當(dāng)自己的服務(wù)器想發(fā)送推送時, 在遠程推送服務(wù)器中輸入要發(fā)送的消息并選擇發(fā)給哪些用戶的deviceToken船老,由遠程推送服務(wù)器發(fā)送給APNs柳畔。
  6. APNs根據(jù)deviceToken發(fā)送給對應(yīng)的用戶咽斧。

APNs 服務(wù)器就是蘋果專門做遠程推送的服務(wù)器张惹。

  • deviceToken是由APNs生成的一個專門找到你某個手機上的App的一個標(biāo)識碼。
  • deviceToken 可能會變,如果你更改了你項目的bundle
  • Identifier或者APNs服務(wù)器更新了可能會變。

是一個與線程相關(guān)的機制屎暇。

一個RunLoop就是一個時間處理的循環(huán)根悼,用來不停的調(diào)度工作以及處理輸入時間挤巡。使用runloop的目的是讓你的線程在有工作的時候忙于工作,而沒工作的時候處于休眠狀態(tài)喉恋。runloop的設(shè)計是為了減少cpu無謂的空轉(zhuǎn);

進程與線程的特點與區(qū)別轻黑?

1)進程和線程都是由操作系統(tǒng)所體會的程序運行的基本單元,系統(tǒng)利用該基本單元實現(xiàn)系統(tǒng)對應(yīng)用的并發(fā)性玖详。
2)進程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式蟋座。 進程有獨立的地址空間向臀,一個進程崩潰后,在保護模式下不會對其它進程產(chǎn)生影響芹彬,而線程只是一個進程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量玩郊,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉反璃,所以多進程的程序要比多線程的程序健壯斋攀,但在進程切換時淳蔼,耗費資源較大讳癌,效率要差一些。但對于一些要求同時進行并且又要共享某些變量的并發(fā)操作,只能用線程商乎,不能用進程。 共享變量可以實現(xiàn)線程調(diào)用另一個線程抹凳。

25匹馬,現(xiàn)有5條跑道,沒有計時器嘁扼,要找出最快3匹馬强缘,至少要跑幾場访娶?

至少跑7場秘车,
對25匹馬隨機分成5個組(A,B,C,D,E,F),每組跑一場,記錄每一匹馬在當(dāng)前組中名次(第1名眯亦,第2名,第3名)(跑了五場)
從各個組中選取名次為第一名的馬組成一組,跑一場囊嘉,記錄名次(第六場),本組第1名則確定了25匹馬中最快的一匹馬
選取第六場中名次為第1名的所在原來組名次為第2琢蛤、3名馬,選取第六場中名次為第2名的所在原來組名次第1、2名馬(它自己+第2名)傻寂,選取第六場中名次為第3名所在原來組名次第1名的馬(它自己)疾掰,組成一組,跑一場,記錄名次(第七場),本場的第1呀潭、2名就是25匹馬中最快的第2、3名

8瓶液體,其中1瓶有毒藥,毒藥1小時后至死,請問最快找出毒藥唐片,需要幾只老鼠?

1只老鼠可以斷定2瓶液體,2^3=8钉汗,所以需要3只老鼠即可福侈,
對液體進行編號,001伟墙,010汉匙,011戏自,100,101剂娄,110,111
給1號老鼠喂編碼個位數(shù)上是1的液體(001,011怕午,101甲锡,111)虎韵,
給2號老鼠喂編碼十位數(shù)上是1的液體(010驶社,011硅瞧,110,111),
給3號老鼠喂編碼百位數(shù)上是1的液體(100月腋,101,110苫纤,111)喊废,
1小時后,
如果老鼠全活, 8號液體有毒陆蟆,
如果全都死,7號液體有毒,
如果1號死,2依痊,3活凉逛, 1號液體有毒
如果2號死毫胜, 1,3活穿撮,2號液體有毒
如果3號死枪向,1,2活负蠕, 4號液體有毒
如果1,2號死,3活赛不, 3號液體有毒
如果1惹苗,3號死,2活, 5號液體有毒
如果2,3號死蔬胯,1活, 6號液體有毒

UIButton不響應(yīng)事件的原因

按鈕添加到了一個沒有開啟用戶交互的父View上,例如UIImageView窿冯,這時候開啟父試圖的交互 view.userInteractionEnabled = YES
按鈕自身被遮擋,點擊的時候根本就沒有點擊到button执桌,而是他上面一層View,自然就不會響應(yīng)
按鈕的frame超出了父視圖的frame仰挣,這個是最容易出現(xiàn)的疗绣,按鈕的frame必須在父視圖的frame內(nèi)部點擊才有效
注意:超出父視圖不響應(yīng)雹有,但在父視圖里的會響應(yīng)随静。

webview的優(yōu)化畜伐,webview為什么會加載白屏
webview加載H5頁面過程

初始化 webview -> 請求頁面 -> 下載數(shù)據(jù) -> 解析HTML -> 請求 js/css 資源 -> dom 渲染 -> 解析 JS 執(zhí)行 -> JS 請求數(shù)據(jù) -> 解析渲染 -> 下載渲染圖片

優(yōu)化

  • 前端優(yōu)化

合并資源,減少http請求數(shù)
加快請求速度:預(yù)解析DNS万矾,減少域名數(shù)慎框,并行加載,CDN

分發(fā)

  • 客戶端優(yōu)化

離線包方案:把一個個功能模塊的所有相關(guān)頁面和資源打包

下發(fā)
提前初始化 webview笨枯,提供一個全局的webview。添加webview 池重用池严嗜,可以用兩個或多個 webview 重復(fù)使用

預(yù)加載數(shù)據(jù)

總結(jié):緩存/預(yù)加載/并行洲敢,緩存一切網(wǎng)絡(luò)請求,盡量在用戶打開之前就加載好所有內(nèi)容睦优,能并行做的事不串行做壮不。

app啟動優(yōu)化

App總啟動時間 = pre-main耗時 + main耗時,可以通過添加環(huán)境變量:DYLD_PRINT_STATISTICS

啟動流程

pre-main:系統(tǒng)dylib(動態(tài)鏈接庫)和自身App可執(zhí)行文件的加載
main: main方法執(zhí)行之后到AppDelegate類中的didFinishLaunchingWithOptions方法執(zhí)行結(jié)束前這段時間询一,主要是構(gòu)建第一個界面尸执,并完成渲染展示

pre-main優(yōu)化

減少類的數(shù)量如失,刪除無用代碼(未被調(diào)用的靜態(tài)變量送粱、類和方法,抽象重復(fù)代碼
+load方法中做的事情延遲到+initialize中,或者在+load中做的事情不宜花費過多時間
減少不必要的framework抗俄,或者優(yōu)化已有的framework

main階段優(yōu)化

didFinishLaunchingWithOptions,日志动雹、統(tǒng)計,某個功能的預(yù)加載,第三方SDK初始化胰蝠,可以采用懶加載,或者分階段

啟動

首頁啟動渲染的頁面優(yōu)化躲庄,對于viewDidLoad以及viewWillAppear方法中盡量去嘗試少做钾虐,晚做,不做效扫,或者采用異步的方式去做。不使用xib或者storyboard浩习,直接使用代碼

談?wù)勀銓VC的理解掘托?

KVC|可以通過(key)直接訪問對象的屬性籍嘹,或者給對象的屬性賦值,這樣可以在運行時動態(tài)的訪問或修改對象的屬性當(dāng)調(diào)用setValue:屬性值forKey: @"name"的代碼時泪掀,颂碘,底層的執(zhí)行機制如下∶

1、程序優(yōu)先調(diào)用set key>:屬性值方法塔拳,代碼通過(setter方法|完成設(shè)置。注意靠抑,這里的<key是指成員變量名,首字母大小寫要符合(KVC)的命名規(guī)則荠列,下同

2载城、如果沒有找到setName:|方法,KVC機制會檢查(+(BOOL)accessInstancelariablesDirectly方法有沒有返回VYES 川队,默認(rèn)該方法會返回(VEs ,如果你重寫了該方法讓其返回NO的話垦搬,那么在這一步(KC 會執(zhí)行(setValue: forUndefinedKey:)方法,不過一般開發(fā)者不會這么做猴贰。所以KVC機制會搜索該類里面有沒有名為<kep)的成員變量,無論該變量是在類接口處定義瑟捣,還是在類實現(xiàn)處定義栅干,也無論用了什么樣的訪問修飾符,只在存在以<key命名的變量桑李,KVC都可以對該成員變量賦值窿给。

3、如果該類即沒有set<key>:方法崩泡,也沒有(_<key>成員變量角撞,KVC機制會搜索(_is<Key>)的成員變量勃痴。

4热康、和上面一樣,如果該類即沒有set:方法褐隆,也沒有_和_is成員變量,KVC機制再會繼續(xù)搜索和is的成員變量庶弃。再給它們賦值。

談?wù)剬π阅軆?yōu)化的看法固惯,如何做缴守?

從用戶體驗出發(fā):

1、程序logging不要太長贴捡、
2村砂、相同數(shù)據(jù)不做重復(fù)獲取、
3础废、昂貴資源要重用(cell评腺、sqlite、date)蒿讥,
4、良好的編程習(xí)慣和程序設(shè)計:選擇正確的集合對象和算法來進行編程媒殉、選擇適合的數(shù)據(jù)存儲格式(plist侥钳、SQLite)柄错、優(yōu)化SQLite查詢語句
5苦酱、數(shù)據(jù)資源方面的優(yōu)化(緩存和異步加載)

解決方案:

  • 能夠發(fā)現(xiàn)問題
  • 利用log或工具分析問題原因
  • 假設(shè)問題原因
  • 改進代碼和設(shè)計

oc中可修改和不可以修改類型给猾?

答:可修改不可修改的集合類敢伸,這個我個人簡單理解就是可動態(tài)添加修改和不可動態(tài)添加修改一樣。比如NSArray和NSMutableArray池颈,前者在初始化后的內(nèi)存控件就是固定不可變的,后者可以添加等每币,可以動態(tài)申請新的內(nèi)存空間

說說響應(yīng)鏈

當(dāng)事件發(fā)生的時候琢歇,響應(yīng)鏈?zhǔn)紫缺话l(fā)送給第一個響應(yīng)者(往往是事件發(fā)生的視圖,也就是用戶觸摸屏幕的地方)揭保。事件將沿著響應(yīng)者鏈一直向下傳遞魄宏,直到被接受并作出處理。一般來說塔次,第一響應(yīng)這是個視圖對象或者其子類名秀,當(dāng)其被觸摸后事件就交由它處理,如果他不處理继榆,時間就會被傳遞給視圖控制器對象;
UIViewController(如果存在)汁掠,然后是它的父視圖對象(superview),以此類推知道頂層視圖考阱。接下來會沿著頂層視圖(top view)到窗口(UIwindow 對象) 再到程序的(UIApplication對象)乞榨,如果整個過程都沒有響應(yīng)這個事件当娱,則該事件被丟棄考榨,一般情況下,在響應(yīng)鏈中只要有對象處理事件冀惭,事件就會被傳遞 ;
典型的響應(yīng)路線圖如First Responser --> The Window -->The Applicationn --> App Delegate

熟悉哪些設(shè)計模式掀鹅?

MVC 模式、單例模式溃槐、MVVM 模式科吭、代理模式、工廠模式对人,觀察者模式

  1. mvc 模式:model 保存應(yīng)用模型和處理數(shù)據(jù)邏輯、view 負責(zé) model 數(shù)據(jù)和交互控件的顯示牺弄、controller 負責(zé) model 和 View 之間的通訊

  2. 單例模式:用一個靜態(tài)方法返回這個類的對象势告。這個對象是全局唯一的。整個項目里面只開辟一塊內(nèi)層咱台,比如登錄之后獲取的用戶數(shù)據(jù)存儲、NSNotificationcenter春贸、NSUserdefaults , sharedApplication遗遵。

缺點:這塊內(nèi)層直到項目推出時才能釋放。
優(yōu)勢:使用簡單允粤,延時求值,易于跨模塊, 便于資源共享控制绳姨,方便傳值和修改單例的屬性

談?wù)勀銓VC的理解阔挠?為什么要用MVC脑蠕?

MVC是Model-VIew-Controller,就是模型-視圖-控制器, MVC把軟件系統(tǒng)分為三個部分:Model迂求,View晃跺,Controller。
Cocoa中所有的控件掀虎、窗口等都繼承自 UIView烹玉,對應(yīng)MVC中的 V。UIView及其子類主要負責(zé)UI的實現(xiàn)县忌,而UIView所產(chǎn)生的事件都可以采用委托的方式继效,交給UIViewController實現(xiàn)。對于不同的 UIView厉颤,都有相應(yīng)的UIViewController 對應(yīng)MVC中的C凡简。比如在iPhone OS上常用的UITableView,它所對應(yīng)的Controller就是UITableViewController潘鲫。至于MVC中的M溉仑,那需要根據(jù)用 戶自己的需求來實現(xiàn)了。
MVC可以幫助確保幫助實現(xiàn)程序最大程度的可重用性怨喘。各MVC元素彼此獨立運作,通過分開這些元素必怜,可以構(gòu)建可維護梳庆,可獨立更新的程序組建。

簡述NotificationCenter膏执、KVC、KVO欺栗、Delegate征峦?并說明它們之間的區(qū)別栏笆?

Notification:觀察者模式,controller向defaultNotificationCenter添加自己的 notification竖伯,其他類注冊這個notification就可以收到通知七婴,這些類可以在收到通知時做自己的操作(多觀察者默認(rèn)隨機順序發(fā)通知給 觀察者們,而且每個觀察者都要等當(dāng)前的某個觀察者的操作做完才能輪到他來操作打厘,可以用NotificationQueue的方式安排觀察者的反應(yīng)順序户盯,也 可以在添加觀察者中設(shè)定反映時間,取消觀察需要在viewDidUnload 跟dealloc中都要注銷);
KVC鍵值編碼吗伤,可以直接通過字符串的名字(key)來間接訪問屬性的機制硫眨,而不是通過調(diào)用getter和setter方法訪問;
KVO:觀測指定對象的屬性,當(dāng)指定對象的屬性更改之后會通知相應(yīng)的觀察者;
delegate:一對一巧号,delegate遵循某個協(xié)議并實現(xiàn)協(xié)議聲明的方法;

怎么用 copy 關(guān)鍵字?

NSString越走、NSArray靠欢、NSDictionary 等等經(jīng)常使用 copy 關(guān)鍵字,是因為他們有對應(yīng)的可變類型:NSMutableString、NSMutableArray疼进、NSMutableDictionary伞广;

block也經(jīng)常使用 copy 關(guān)鍵字。
MRC 中,方法內(nèi)部的 block 是在棧區(qū)的,使用 copy 可以把它放到堆區(qū)在 ARC 中寫不寫都行:對于 block 使用 copy 還是 strong 效果是一樣的嚼锄,但寫上 copy 也無傷大雅区丑,還能時刻?醒我們:編譯器自動對 block 進行了 copy操作。如果不寫 copy 可霎,該類的調(diào)用者有可能會忘記或者根本不知道“編譯器會自動對 block進行了 copy 操作”宴杀,他們有可能會在調(diào)用之前自行拷貝屬性值。這種操作多余而低效旷余。
copy 此特質(zhì)所表達的所屬關(guān)系與 strong 類似扁达。然而設(shè)置方法并不保留新值,而是將其“拷 貝” (copy)穗酥。 當(dāng)屬性類型為 NSString 時,經(jīng)常用此特質(zhì)來保護其封裝性骏啰,因為傳遞給設(shè)置方法的新值有可能指向一個 NSMutableString 類的實例抽高。這個類是 NSString 的子類,表示一種可修改其值的字符串壁熄,此時若是不拷貝字符串碳竟,那么設(shè)置完屬性之后,字符串的值就可能會在對象不知情的情況下遭人更改昌执。所以诈泼,這時就要拷貝一份“不可變” (immutable)的字符串懂拾,確保對象中的字符串值不會無意間變動。

談?wù)勀銓Χ嗑€程開發(fā)的理解铐达?

好處:
1.使多線程可以把占據(jù)時間長的程序中的任務(wù)放到后臺去處理
2.用戶界面可以更加吸引力岖赋,這樣比如用戶點擊了一個按鈕去觸發(fā)某些事件的處理,
可以彈出一個進度條來顯示處理的進度
3.程序的運行速度可能加快
缺點:
1.如果有大量的線程,會影響性能,因為操作系統(tǒng)需要在它們之間切換瓮孙。
2.更多的線程需要更多的內(nèi)存空間唐断。

ios中有幾種實現(xiàn)多線程的方法?

多線程參考鏈接:http://www.reibang.com/p/f28a50f72bb1

  1. NSThread
  2. NSOperationQueue
  3. GCD Thread

是這三種范式里面相對輕量級的杭抠,但也是使用起來最負責(zé)的栗涂,你需要自己管理thread的生命周期,線程之間的同步斤程。線程共享同一應(yīng)用程序的部分內(nèi)存空間, 它們擁有對數(shù)據(jù)相同的訪問權(quán)限菩混。你得協(xié)調(diào)多個線程對同一數(shù)據(jù)的訪問忿墅,一般做法是在訪問之前加鎖,這會導(dǎo)致一定的性能開銷沮峡。在 iOS 中我們可以使用多種形式的 thread: Cocoa threads: 使用NSThread 或直接從 NSObject 的類方法 performSelectorInBackground:withObject: 來創(chuàng)建一個線程疚脐。如果你選擇thread來實現(xiàn)多線程,那么 NSThread 就是官方推薦優(yōu)先選用的方式邢疙。
Cocoa operations是基于 Obective-C實現(xiàn)的棍弄,類 NSOperation 以面向?qū)ο蟮姆绞椒庋b了用戶需要執(zhí)行的操作望薄,我們只要聚焦于我們需要做的事情,而不必太操心線程的管理呼畸,同步等事情痕支,因為NSOperation已經(jīng)為我 們封裝了這些事情。 NSOperation 是一個抽象基類蛮原,我們必須使用它的子類卧须。iOS 提供了兩種默認(rèn)實現(xiàn):NSInvocationOperation 和 NSBlockOperation。
Grand Central Dispatch (GCD): iOS4 才開始支持儒陨,它提供了一些新的特性花嘶,以及運行庫來支持多核并行編程,它的關(guān)注點更高:如何在多個 cpu 上提升效率蹦漠。

具體實施
這三種編程方式從上到下椭员,抽象度層次是從低到高的,抽象度越高的使用越簡單笛园,也是Apple最推薦使用的隘击。

三種方式的優(yōu)缺點介紹:

1)NSThread:
優(yōu)點:NSThread 比其他兩個輕量級
缺點:需要自己管理線程的生命周期,線程同步喘沿。線程同步對數(shù)據(jù)的加鎖會有一定的系統(tǒng)開銷

NSThread實現(xiàn)的技術(shù)有下面三種:
一般使用cocoa thread 技術(shù)闸度。
(一)NSThread的使用
NSThread 有兩種直接創(chuàng)建方式:

-(id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument

-(void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument

參數(shù)的意義:
selector :線程執(zhí)行的方法竭贩,這個selector只能有一個參數(shù)蚜印,而且不能有返回值。target :selector消息發(fā)送的對象 argument:傳輸給target的唯一參數(shù)留量,也可以是nil

第一種方式會直接創(chuàng)建線程并且開始運行線程窄赋,第二種方式是先創(chuàng)建線程對象,然后再運行線程操作楼熄,在運行線程操作前可以設(shè)置線程的優(yōu)先級等線程信息

不顯式創(chuàng)建線程的方法:

用NSObject的類方法 performSelectorInBackground:withObject: 創(chuàng)建一個線程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];

(二) NSOperation

優(yōu)點:不需要關(guān)心線程管理忆绰,數(shù)據(jù)同步的事情,可以把精力放在自己需要執(zhí)行的操作上可岂。
Cocoa operation 相關(guān)的類是 NSOperation 错敢,NSOperationQueue。
NSOperation是個抽象類缕粹,使用它必須用它的子類稚茅,可以實現(xiàn)它或者使用它定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation。
創(chuàng)建NSOperation子類的對象平斩,把對象添加到NSOperationQueue隊列里執(zhí)行亚享。

NSOperation 實現(xiàn)多線程的使用步驟分為三步:

創(chuàng)建操作:先將需要執(zhí)行的操作封裝到一個 NSOperation 對象中。
創(chuàng)建隊列:創(chuàng)建 NSOperationQueue 對象绘面。
將操作加入到隊列中:將 NSOperation 對象添加到 NSOperationQueue 對象中欺税。
之后呢侈沪,系統(tǒng)就會自動將 NSOperationQueue 中的 NSOperation 取出來,在新線程中執(zhí)行操作晚凿。

NSOperationQueue 控制串行執(zhí)行亭罪、并發(fā)執(zhí)行

之前我們說過,NSOperationQueue 創(chuàng)建的自定義隊列同時具有串行晃虫、并發(fā)功能皆撩,上邊我們演示了并發(fā)功能,那么他的串行功能是如何實現(xiàn)的哲银?

這里有個關(guān)鍵屬性 maxConcurrentOperationCount扛吞,叫做最大并發(fā)操作數(shù)。用來控制一個特定隊列中可以有多少個操作同時參與并發(fā)執(zhí)行荆责。

注意:這里 maxConcurrentOperationCount 控制的不是并發(fā)線程的數(shù)量滥比,而是一個隊列中同時能并發(fā)執(zhí)行的最大操作數(shù)。而且一個操作也并非只能在一個線程中運行做院。
最大并發(fā)操作數(shù):maxConcurrentOperationCount
maxConcurrentOperationCount 默認(rèn)情況下為-1盲泛,表示不進行限制,可進行并發(fā)執(zhí)行键耕。
maxConcurrentOperationCount 為1時寺滚,隊列為串行隊列。只能串行執(zhí)行屈雄。
maxConcurrentOperationCount 大于1時村视,隊列為并發(fā)隊列。操作并發(fā)執(zhí)行酒奶,當(dāng)然這個值不應(yīng)超過系統(tǒng)限制蚁孔,即使自己設(shè)置一個很大的值,系統(tǒng)也會自動調(diào)整為 min{自己設(shè)定的值惋嚎,系統(tǒng)設(shè)定的默認(rèn)最大值}杠氢。

參考鏈接:http://www.reibang.com/p/4b1d77054b35

(三)GCD

Grand Central Dispatch (GCD)是Apple開發(fā)的一個多核編程的解決方法。在iOS4.0開始之后才能使用另伍。GCD是一個替代諸如NSThread, NSOperationQueue, NSInvocationOperation等技術(shù)的很高效和強大的技術(shù)鼻百。

使用 GCD 有很多好處啊,具體如下:
GCD 可用于多核的并行運算摆尝;
GCD 會自動利用更多的 CPU 內(nèi)核(比如雙核温艇、四核);
GCD 會自動管理線程的生命周期(創(chuàng)建線程结榄、調(diào)度任務(wù)中贝、銷毀線程);
程序員只需要告訴 GCD 想要執(zhí)行什么任務(wù)臼朗,不需要編寫任何線程管理代碼邻寿。
GCD 擁有以上這么多的好處蝎土,而且在多線程中處于舉足輕重的地位。那么我們就很有必要系統(tǒng)地學(xué)習(xí)一下 GCD 的使用方法绣否。

2. GCD 任務(wù)和隊列
學(xué)習(xí) GCD 之前誊涯,先來了解 GCD 中兩個核心概念:『任務(wù)』 和 『隊列』。

任務(wù):就是執(zhí)行操作的意思蒜撮,換句話說就是你在線程中執(zhí)行的那段代碼暴构。在 GCD 中是放在 block 中的。執(zhí)行任務(wù)有兩種方式:『同步執(zhí)行』 和 『異步執(zhí)行』段磨。兩者的主要區(qū)別是:是否等待隊列的任務(wù)執(zhí)行結(jié)束取逾,以及是否具備開啟新線程的能力。

同步執(zhí)行(sync)

同步添加任務(wù)到指定的隊列中苹支,在添加的任務(wù)執(zhí)行結(jié)束之前砾隅,會一直等待,直到隊列里面的任務(wù)完成之后再繼續(xù)執(zhí)行债蜜。
只能在當(dāng)前線程中執(zhí)行任務(wù)晴埂,不具備開啟新線程的能力。

異步執(zhí)行(async):

異步添加任務(wù)到指定的隊列中寻定,它不會做任何等待儒洛,可以繼續(xù)執(zhí)行任務(wù)。
可以在新的線程中執(zhí)行任務(wù)狼速,具備開啟新線程的能力琅锻。
舉個簡單例子:你要打電話給小明和小白。
『同步執(zhí)行』 就是:你打電話給小明的時候唐含,不能同時打給小白浅浮。只有等到給小明打完了沫浆,才能打給小白(等待任務(wù)執(zhí)行結(jié)束)捷枯。而且只能用當(dāng)前的電話(不具備開啟新線程的能力)。
『異步執(zhí)行』 就是:你打電話給小明的時候专执,不用等著和小明通話結(jié)束(不用等待任務(wù)執(zhí)行結(jié)束)淮捆,還能同時給小白打電話。而且除了當(dāng)前電話本股,你還可以使用其他一個或多個電話(具備開啟新線程的能力)攀痊。

注意:異步執(zhí)行(async)雖然具有開啟新線程的能力,但是并不一定開啟新線程拄显。這跟任務(wù)所指定的隊列類型有關(guān)(下面會講)苟径。

隊列(Dispatch Queue):這里的隊列指執(zhí)行任務(wù)的等待隊列,即用來存放任務(wù)的隊列躬审。隊列是一種特殊的線性表棘街,采用 FIFO(先進先出)的原則蟆盐,即新任務(wù)總是被插入到隊列的末尾,而讀取任務(wù)的時候總是從隊列的頭部開始讀取遭殉。每讀取一個任務(wù)石挂,則從隊列中釋放一個任務(wù)。

在 GCD 中有兩種隊列:『串行隊列』 和 『并發(fā)隊列』险污。兩者都符合 FIFO(先進先出)的原則痹愚。兩者的主要區(qū)別是:執(zhí)行順序不同,以及開啟線程數(shù)不同蛔糯。

串行隊列(Serial Dispatch Queue):
每次只有一個任務(wù)被執(zhí)行拯腮。讓任務(wù)一個接著一個地執(zhí)行。(只開啟一個線程蚁飒,一個任務(wù)執(zhí)行完畢后疾瓮,再執(zhí)行下一個任務(wù))

并發(fā)隊列(Concurrent Dispatch Queue):
可以讓多個任務(wù)并發(fā)(同時)執(zhí)行。(可以開啟多個線程飒箭,并且同時執(zhí)行任務(wù))
注意:并發(fā)隊列 的并發(fā)功能只有在異步(dispatch_async)方法下才有效狼电。

ViewController生命周期

按照執(zhí)?順序排列:

initWithCoder:通過nib?件初始化時觸發(fā)。
awakeFromNib:nib文件被加載的時候弦蹂,會發(fā)生一個awakeFromNib的消息到nib文件中的每個對象肩碟。
loadView:開始加載視圖控制器?帶的view。
viewDidLoad:視圖控制器的view被加載完成凸椿。
viewWillAppear:視圖控制器的view將要顯示在window上削祈。
updateViewConstraints:視圖控制器的view開始更新AutoLayout約束。
viewWillLayoutSubviews:視圖控制器的view將要更新內(nèi)容視圖的位置脑漫。
viewDidLayoutSubviews:視圖控制器的view已經(jīng)更新視圖的位置髓抑。
viewDidAppear:視圖控制器的view已經(jīng)展示到window上。
viewWillDisappear:視圖控制器的view將要從window上消失优幸。
viewDidDisappear:視圖控制器的view已經(jīng)從window上消失吨拍。

struct、Class的區(qū)別

class可以繼承网杆,struct不可以
class是引用類型羹饰,struct是值類型
struct在function里修改property時需要mutating關(guān)鍵字修飾

NSArray與NSSet的區(qū)別?

NSArray內(nèi)存中存儲地址連續(xù)碳却,而NSSet不連續(xù)
NSSet效率高队秩,內(nèi)部使用hash查找;NSArray查找需要遍歷
NSSet通過anyObject訪問元素昼浦,NSArray通過下標(biāo)訪問

NSHashTable與NSMapTable馍资?

NSHashTable是NSSet的通用版本,對元素弱引用关噪,可變類型鸟蟹;可以在訪問成員時copy
NSMapTable是NSDictionary的通用版本物舒,對元素弱引用,可變類型戏锹;可以在訪問成員時copy
(注:NSHashTable與NSSet的區(qū)別:NSHashTable可以通過option設(shè)置元素弱引用/copyin冠胯,只有可變類型。但是添加對象的時候NSHashTable耗費時間是NSSet的兩倍锦针。

  • NSMapTable與NSDictionary的區(qū)別:同上)

屬性關(guān)鍵字assign荠察、retain、weak奈搜、copy

assign:用于基本數(shù)據(jù)類型和結(jié)構(gòu)體悉盆。如果修飾對象的話,當(dāng)銷毀時馋吗,屬性值不會自動置nil焕盟,可能造成野指針。
weak:對象引用計數(shù)為0時宏粤,屬性值也會自動置nil
retain:強引用類型脚翘,ARC下相當(dāng)于strong,但block不能用retain修飾绍哎,因為等同于assign不安全来农。
strong:強引用類型,修飾block時相當(dāng)于copy崇堰。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沃于,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子海诲,更是在濱河造成了極大的恐慌繁莹,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件特幔,死亡現(xiàn)場離奇詭異咨演,居然都是意外死亡,警方通過查閱死者的電腦和手機敬辣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門雪标,熙熙樓的掌柜王于貴愁眉苦臉地迎上來零院,“玉大人溉跃,你說我怎么就攤上這事「娉” “怎么了撰茎?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長打洼。 經(jīng)常有香客問我龄糊,道長逆粹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任炫惩,我火速辦了婚禮僻弹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘他嚷。我一直安慰自己蹋绽,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布筋蓖。 她就那樣靜靜地躺著卸耘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪粘咖。 梳的紋絲不亂的頭發(fā)上蚣抗,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機與錄音瓮下,去河邊找鬼翰铡。 笑死,一個胖子當(dāng)著我的面吹牛讽坏,可吹牛的內(nèi)容都是我干的两蟀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼震缭,長吁一口氣:“原來是場噩夢啊……” “哼赂毯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拣宰,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤党涕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后巡社,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膛堤,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年晌该,在試婚紗的時候發(fā)現(xiàn)自己被綠了肥荔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡朝群,死狀恐怖燕耿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情姜胖,我是刑警寧澤誉帅,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響蚜锨,放射性物質(zhì)發(fā)生泄漏肛走。R本人自食惡果不足惜债查,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一肛响、第九天 我趴在偏房一處隱蔽的房頂上張望闪檬。 院中可真熱鬧,春花似錦氛悬、人聲如沸饲鄙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忍级。三九已至,卻和暖如春伪朽,著一層夾襖步出監(jiān)牢的瞬間轴咱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工烈涮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留朴肺,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓坚洽,卻偏偏與公主長得像戈稿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子讶舰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354

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