系統(tǒng)推送的集成(一) —— 基本集成流程(一)

版本記錄

版本號(hào) 時(shí)間
V1.0 2018.06.21

前言

我們做APP很多時(shí)候都需要推送功能,以直播為例为迈,如果你關(guān)注的主播開(kāi)播了敌蜂,那么就需要向關(guān)注這個(gè)主播的人發(fā)送開(kāi)播通知箩兽,提醒用戶去看播,這個(gè)只是一個(gè)小的方面章喉,具體應(yīng)用根據(jù)公司的業(yè)務(wù)邏輯而定汗贫。前面已經(jīng)花了很多篇幅介紹了極光推送,其實(shí)極光推送無(wú)非就是將我們客戶端和服務(wù)端做的很多東西封裝了一下秸脱,節(jié)省了我們很多處理邏輯和流程落包,這一篇開(kāi)始,我們就利用系統(tǒng)的原生推送類(lèi)結(jié)合工程實(shí)踐說(shuō)一下系統(tǒng)推送的集成摊唇,希望我的講解能讓大家很清楚的理解它咐蝇。

幾個(gè)需要提前知道的問(wèn)題

1. 推送流程是如何的?

推送是蘋(píng)果系統(tǒng)提供的功能遏片,其實(shí)基本流程就是我們的客戶端要用deviceToken在蘋(píng)果服務(wù)器進(jìn)行注冊(cè)嘹害,并將這個(gè)deviceToken發(fā)送給我們的服務(wù)端綁定我們的賬號(hào),服務(wù)端將要推送的內(nèi)容發(fā)送給蘋(píng)果吮便,蘋(píng)果就會(huì)將定制化的內(nèi)容根據(jù)deviceToken發(fā)送給我們客戶端笔呀,我們就收到推送了。

也就是說(shuō)髓需,我們客戶端除了注冊(cè)PUSH许师,接收蘋(píng)果給我們的deviceToken,發(fā)送給我們服務(wù)端和當(dāng)前賬號(hào)綁定以外僚匆,我們除了等著收到PUSH進(jìn)行處理就決定不了別的事情了微渠,至于推送什么是我們服務(wù)端決定的,什么時(shí)候能收到就看蘋(píng)果服務(wù)器了咧擂。

下面這張圖就是很好的說(shuō)明了推送的原理逞盆,圖片源于網(wǎng)絡(luò)。

PUSH原理

2. deviceToken是如何獲取的松申?有什么用云芦?

deviceToken是我們用蘋(píng)果的API注冊(cè)PUSH的時(shí)候,蘋(píng)果的服務(wù)器發(fā)給我們的贸桶,我們?cè)诖矸椒?code>- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken中進(jìn)行接收舅逸。那么這個(gè)是做什么的呢?這個(gè)就是蘋(píng)果發(fā)送個(gè)性化推送找到你機(jī)器的憑證皇筛,有了它琉历,蘋(píng)果系統(tǒng)就知道這個(gè)消息要推送給你。

我們?cè)诖矸椒ㄖ惺盏酵扑秃螅话阋獙⑦@個(gè)deviceToken發(fā)送給我們的服務(wù)器旗笔,讓服務(wù)器將這個(gè)deviceToken和你當(dāng)前App的賬號(hào)進(jìn)行綁定彪置,這樣才能進(jìn)行個(gè)性化的推送和消息訂制。

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSLog(@"push - didRegisterForRemoteNotificationsWithDeviceToken");

    NSString * deviceid = [NSString stringWithFormat:@"%@", deviceToken];
    deviceid = [deviceid stringByReplacingOccurrencesOfString:@"<" withString:@""];
    deviceid = [deviceid stringByReplacingOccurrencesOfString:@">" withString:@""];
    deviceid = [deviceid stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    NSLog(@"push - deviceToken = %@", deviceid);
    // 這個(gè)是我自己寫(xiě)的單例换团,用來(lái)存儲(chǔ)關(guān)于App的一些基本信息悉稠,這里是用NSUserDefaults存儲(chǔ)當(dāng)前收到的deviceToken
    [JJAppPrefs setDeviceToken:deviceid];

    //這個(gè)是我寫(xiě)的一個(gè)單例宫蛆,用來(lái)專(zhuān)門(mén)處理Push相關(guān)的艘包,這個(gè)就是綁定token,將這個(gè)收到的deviceToken發(fā)送給你的服務(wù)器耀盗,
    // 服務(wù)器進(jìn)行綁定想虎,你只能知道綁定成功或者失敗,不用做其他的叛拷。
    [[JJPushManager manager] bindDeviceToken];
}

3. 客戶端要如何開(kāi)啟推送舌厨?

這個(gè)是一個(gè)開(kāi)關(guān),只要點(diǎn)擊一下就可以了忿薇,就能開(kāi)啟推送了裙椭。

開(kāi)啟推送

4. 關(guān)于證書(shū)要做什么?

我們做推送是要證書(shū)的署浩,讓有賬號(hào)的人生成兩個(gè)證書(shū)揉燃,一個(gè)是測(cè)試環(huán)境證書(shū),一個(gè)是生產(chǎn)環(huán)境證書(shū)筋栋。

證書(shū)

具體如何生成證書(shū)可以看網(wǎng)上的資料炊汤,跟著一步步的做就可以了,這里就不多說(shuō)了弊攘。


注冊(cè)PUSH

截止目前抢腐,iOS已經(jīng)有了11的系統(tǒng),注冊(cè)PUSH從10系統(tǒng)以后就要考慮版本的差異了襟交。

如果你是在iOS10以前做PUSH是不用這么麻煩的迈倍,但是隨著iOS10的更新,一個(gè)新類(lèi)UNUserNotificationCenter出來(lái)了捣域,所以要根據(jù)版本的不同進(jìn)行不同的注冊(cè)邏輯啼染。

iOS10及其以后版本

//10及其以后系統(tǒng)使用下面方法進(jìn)行注冊(cè)

UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center setDelegate:self];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert |
                                         UNAuthorizationOptionBadge |
                                         UNAuthorizationOptionSound)
                      completionHandler:^(BOOL granted, NSError * _Nullable error) {
                          if (granted) {
                              NSLog(@"push - 注冊(cè)成功");
                          }
                          else{
                              NSLog(@"push - 注冊(cè)失敗");
                          }
                      }];
[[UIApplication sharedApplication] registerForRemoteNotifications];

這里,[[UIApplication sharedApplication] registerForRemoteNotifications];一定不能少竟宋,要不你是收不到deviceToken的提完。因?yàn)槟悴粚?xiě)這句話表示你沒(méi)有注冊(cè)。

同時(shí)丘侠,你要設(shè)置好代理@interface AppDelegate () <UNUserNotificationCenterDelegate>徒欣,否則你處理PUSH的方法都不會(huì)進(jìn)行回調(diào)的。

iOS9及其以前版本

iOS9及其以前版本使用類(lèi)UIUserNotificationSettings進(jìn)行注冊(cè)PUSH的蜗字。

//9及其以前系統(tǒng)使用下面方法進(jìn)行注冊(cè)

else if ([UIUserNotificationSettings self]) {
    id settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert |
                                                                UIUserNotificationTypeSound |
                                                                UIUserNotificationTypeBadge)
                                                    categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
    [[UIApplication sharedApplication] registerForRemoteNotifications];
}
else {
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
                                                                           UIRemoteNotificationTypeSound |
                                                                           UIRemoteNotificationTypeAlert)];
}

這里有幾個(gè)小的問(wèn)題打肝,UIUserNotificationSettings在10系統(tǒng)出現(xiàn)就廢棄了這個(gè)類(lèi)脂新。

NS_CLASS_DEPRECATED_IOS(8_0, 10_0, "Use UserNotifications Framework's UNNotificationSettings") __TVOS_PROHIBITED
@interface UIUserNotificationSettings : NSObject

這里大家也注意到了這個(gè)方法

- (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types NS_DEPRECATED_IOS(3_0, 8_0, "Use -[UIApplication registerForRemoteNotifications] and UserNotifications Framework's -[UNUserNotificationCenter requestAuthorizationWithOptions:completionHandler:]") __TVOS_PROHIBITED;

可以看見(jiàn),這個(gè)方法在iOS 8.0也已經(jīng)廢棄了粗梭,改用上面提示的那兩個(gè)方法了争便。

上面這兩種注冊(cè)方法,需要像iOS10以上的那個(gè)方法設(shè)置代理嗎断医?簡(jiǎn)單來(lái)說(shuō)滞乙,不用你去做,他們的代理叫UIApplicationDelegate鉴嗤,系統(tǒng)已經(jīng)給你設(shè)置好了斩启。也就是說(shuō)10以前的系統(tǒng)直接就可以寫(xiě)代理方法進(jìn)行相應(yīng)的處理了,不用再進(jìn)行遵循代理這一個(gè)步驟了醉锅。

// 這個(gè)系統(tǒng)已經(jīng)給你寫(xiě)好了

@interface AppDelegate : UIResponder <UIApplicationDelegate>

獲取deviceToken

上面你去注冊(cè)PUSH兔簇,注冊(cè)成功后,蘋(píng)果服務(wù)器就會(huì)返回給你deviceToken硬耍,在下面幾個(gè)代理方法中獲取deviceToken的狀態(tài)已經(jīng)進(jìn)行其他處理垄琐。

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
    NSLog(@"push - didRegisterUserNotificationSettings");
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSLog(@"push - didRegisterForRemoteNotificationsWithDeviceToken");

    NSString * deviceid = [NSString stringWithFormat:@"%@", deviceToken];
    deviceid = [deviceid stringByReplacingOccurrencesOfString:@"<" withString:@""];
    deviceid = [deviceid stringByReplacingOccurrencesOfString:@">" withString:@""];
    deviceid = [deviceid stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    NSLog(@"push - deviceToken = %@", deviceid);
    // 這個(gè)是我自己寫(xiě)的單例,用來(lái)存儲(chǔ)關(guān)于App的一些基本信息经柴,這里是用NSUserDefaults存儲(chǔ)當(dāng)前收到的deviceToken
    [JJAppPrefs setDeviceToken:deviceid];

    //這個(gè)是我寫(xiě)的一個(gè)單例狸窘,用來(lái)專(zhuān)門(mén)處理Push相關(guān)的,這個(gè)就是綁定token口锭,將這個(gè)收到的deviceToken發(fā)送給你的服務(wù)器朦前,
    // 服務(wù)器進(jìn)行綁定,你只能知道綁定成功或者失敗鹃操,不用做其他的韭寸。
    [[JJPushManager manager] bindDeviceToken];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    NSLog(@"push - didFailToRegisterForRemoteNotificationsWithError = %@", error);
}

這里我們?cè)诖矸椒ㄖ惺盏絛eviceToken,首先進(jìn)行本地存儲(chǔ)荆隘,然后在發(fā)給服務(wù)器進(jìn)行和當(dāng)前賬號(hào)的綁定恩伺。


收到PUSH的處理

和注冊(cè)PUSH一樣,對(duì)于PUSH的處理也是要分系統(tǒng)版本的椰拒。

1. 代理方法的調(diào)用

iOS 10及其以后

//iOS10新增
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler API_AVAILABLE(ios(10.0))
{
    NSLog(@"push - didReceiveNotificationResponse = %@", response);

    [[JJPushManager manager]  jj_userNotificationCenter:center didReceiveNotificationResponse:response];

    completionHandler();
}

//iOS10新增
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler API_AVAILABLE(ios(10.0))
{
    NSLog(@"push - willPresentNotification");

    [[JJPushManager manager] jj_userNotificationCenter:center willPresentNotification:notification];

    completionHandler(UNNotificationPresentationOptionBadge|
                      UNNotificationPresentationOptionSound|
                      UNNotificationPresentationOptionAlert);
}

這里有幾個(gè)問(wèn)題需要注意:

  • JJPushManager是我自己寫(xiě)的單例晶渠,用來(lái)處理接收到的PUSH以及綁定和解綁deviceToken。這里在單例分出來(lái)進(jìn)行處理燃观,可以減少AppDelegate中代碼的冗雜褒脯,分離出單利進(jìn)行處理更清晰。

  • 關(guān)于iOS10這兩個(gè)方法缆毁,收到橫幅的時(shí)候- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler API_AVAILABLE(ios(10.0))方法會(huì)調(diào)用番川,用戶點(diǎn)擊查看橫幅的時(shí)候- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler API_AVAILABLE(ios(10.0))會(huì)進(jìn)行調(diào)用。

  • 對(duì)于iOS10以后的系統(tǒng),無(wú)論App在前臺(tái)颁督、后臺(tái)或者是殺死都會(huì)收到推送的橫幅践啄。

這樣就收到開(kāi)播通知了,下一步就是點(diǎn)擊進(jìn)行處理了沉御。

iOS 9及其以后

這里接收通知的就一個(gè)方法

//iOS9及其以后方法
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    NSLog(@"push - didReceiveRemoteNotification = %@", userInfo);
 
    [[JJPushManager manager] jj_application:application didReceiveRemoteNotification:userInfo];
}

這里有幾個(gè)問(wèn)題需要注意:

  • iOS9系統(tǒng)當(dāng)App在前臺(tái)的時(shí)候是沒(méi)有橫幅的屿讽,這個(gè)時(shí)候就需要我們進(jìn)行特殊的處理,一個(gè)方案是模擬成本地通知進(jìn)行展示吠裆,另外一個(gè)就是彈出系統(tǒng)的AlertView伐谈,然后進(jìn)行相關(guān)的業(yè)務(wù)邏輯處理,比如跳進(jìn)某個(gè)主播的直播間硫痰。

2. PUSH處理

PUSH我統(tǒng)一在自己寫(xiě)的單例JJPushManager中進(jìn)行的處理衩婚。

@interface JJPushManager()

@property (nonatomic, strong) NSDictionary *currentPushDict;
@property (nonatomic, strong) JJFeed *feed;

@end

@implementation CPPushManager

#pragma mark -  Class Public Function

+ (instancetype)manager
{
    static JJPushManager *pushManager;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        pushManager = [[JJPushManager alloc] init];
        [[NSNotificationCenter defaultCenter] addObserver:pushManager selector:@selector(handlePushWhenApplicationActive) name:UIApplicationDidBecomeActiveNotification object:nil];
    });
    return pushManager;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark -  Object Private Function

//根據(jù)信息數(shù)據(jù)返回Feed模型
- (CPFeed *)gainFeedInfo
{
    self.feed = [[JJFeed alloc] initWithDict:self.currentPushDict];
    return self.feed;
}

- (void)initCurrentPush:(NSDictionary *)currentPushDict
{
    if (!currentPushDict) {
        return;
    }
    
    self.currentPushDict = currentPushDict;
}

//直接跳到直播間
- (void)gotoPlayingRoom
{
    // 未登錄時(shí)窜护,不處理push信息
    if ([JJUserManager loadUserPref] == NO) {
        return;
    }
    
    CPFeed *feedInfo = [self gainFeedInfo];
    
    if (!feedInfo) {
        return;
    }
    
    JJViewController *vc = (JJViewController *)JJCurrentNaviController.topViewController;
    if ([vc isKindOfClass:[JJPlayingViewController class]]) {
        return;
    }
    
    //直接跳轉(zhuǎn)到直播間
    JJPlayingViewController *playVC = [[JJPlayingViewController alloc] initWithFeed:feedInfo];
    [CPCurrentNaviController pushViewController:playVC animated:YES];
}

#pragma mark -  Object Public Function

//iOS10以下使用這個(gè)方法接收通知
- (void)jj_application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    [self initCurrentPush:userInfo];
    if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
        JJViewController *vc = (JJViewController *)JJCurrentNaviController.topViewController;
        if ([vc isKindOfClass:[JJPlayingViewController class]]) {
            return;
        }
        [self gainFeedInfo];
        NSString *titleStr = [NSString stringWithFormat:@"快來(lái)圍觀效斑,%@開(kāi)播啦~", self.feed.anchorPrefs.userNickName];
        IMP_WSELF();
        [vc showAlertViewWithTitle:titleStr message:nil cancelAction:nil ensureAction:^{
            [wself gotoPlayingRoom];
        }];
    }
}

//iOS10新增
- (void)jj_userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response API_AVAILABLE(ios(10.0))
{
    NSDictionary * userInfo = response.notification.request.content.userInfo;
    [self initCurrentPush:userInfo];
    if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
        [self gotoPlayingRoom];
    }
}

//iOS10新增
- (void)jj_userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification API_AVAILABLE(ios(10.0))
{
    NSDictionary * userInfo = notification.request.content.userInfo;
    [self initCurrentPush:userInfo];
}

#pragma mark -  Action && Notification

//進(jìn)入Active消息通知
- (void)handlePushWhenApplicationActive
{
    if (!self.currentPushDict) {
        return;
    }

    [self gotoPlayingRoom];
    self.currentPushDict = nil;
}

注意:上面只是簡(jiǎn)單的邏輯,更復(fù)雜的處理根據(jù)產(chǎn)品的需求進(jìn)行額外的處理柱徙。


幾個(gè)其他問(wèn)題

1. 關(guān)于測(cè)試

開(kāi)發(fā)和QA在進(jìn)行測(cè)試的時(shí)候缓屠,都應(yīng)該使用推送的開(kāi)發(fā)證書(shū)進(jìn)行測(cè)試,直接用正式證書(shū)測(cè)試是收不到的护侮。

2. 關(guān)于到達(dá)率

利用開(kāi)發(fā)證書(shū)進(jìn)行推送測(cè)試敌完,有的時(shí)候到達(dá)率并不是100%,我用11系統(tǒng)試了一下羊初,基本是100%滨溉,用9系統(tǒng)測(cè)試,很大幾率就收不到长赞,偶爾可以收到晦攒,這個(gè)和蘋(píng)果測(cè)試環(huán)境證書(shū)有關(guān)系,正式環(huán)境就沒(méi)事了得哆,這個(gè)我們客戶端控制不了脯颜,也不用擔(dān)心,這并不是bug贩据。

3. 關(guān)于用戶登錄和退出

這個(gè)需要額外的處理栋操,當(dāng)用戶登錄(不管用手機(jī)號(hào)還是三方)都需要重新注冊(cè)下PUSH,綁定deviceToken饱亮,當(dāng)用戶退出登錄的時(shí)候矾芙,需要發(fā)送到服務(wù)端解綁deviceToken并移除deviceToken的本地存儲(chǔ)。

登錄

[(AppDelegate *)([UIApplication sharedApplication].delegate) registerPushNotifications];

退出登錄

[[JJPushManager manager] unbindDeviceToken];
[JJUserManager clearData];

參考資料

1. IOS Push消息推送原理及應(yīng)用

后記

本篇主要講述了系統(tǒng)PUSH的相關(guān)集成及問(wèn)題近上,感興趣的給個(gè)贊或者關(guān)注~~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剔宪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌歼跟,老刑警劉巖和媳,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異哈街,居然都是意外死亡留瞳,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)骚秦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)她倘,“玉大人,你說(shuō)我怎么就攤上這事作箍∮擦海” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵胞得,是天一觀的道長(zhǎng)荧止。 經(jīng)常有香客問(wèn)我,道長(zhǎng)阶剑,這世上最難降的妖魔是什么跃巡? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮牧愁,結(jié)果婚禮上素邪,老公的妹妹穿的比我還像新娘。我一直安慰自己猪半,他們只是感情好兔朦,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著磨确,像睡著了一般沽甥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上俐填,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天安接,我揣著相機(jī)與錄音,去河邊找鬼英融。 笑死盏檐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的驶悟。 我是一名探鬼主播胡野,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼痕鳍!你這毒婦竟也來(lái)了硫豆?” 一聲冷哼從身側(cè)響起龙巨,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎熊响,沒(méi)想到半個(gè)月后旨别,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡汗茄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年秸弛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片洪碳。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡递览,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瞳腌,到底是詐尸還是另有隱情绞铃,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布嫂侍,位于F島的核電站儿捧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏吵冒。R本人自食惡果不足惜纯命,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望痹栖。 院中可真熱鬧,春花似錦瞭空、人聲如沸揪阿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)南捂。三九已至,卻和暖如春旧找,著一層夾襖步出監(jiān)牢的瞬間溺健,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工钮蛛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鞭缭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓魏颓,卻偏偏與公主長(zhǎng)得像岭辣,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子甸饱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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