From f318634295a87319ffa7c0dc4f5d46bd55ab7c79 Mon Sep 17 00:00:00 2001 From: DaidoujiChen Date: Wed, 26 Nov 2014 17:39:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=85=A5=20DaiPortal,=20update=20read?= =?UTF-8?q?me?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +- e-Hentai.xcodeproj/project.pbxproj | 38 +++ .../HentaiDownloadBookOperation.m | 26 +- .../MainViewController/MainViewController.m | 17 +- e-Hentai/ThirdParty/DaiPortal/DaiPortal.h | 59 ++++ e-Hentai/ThirdParty/DaiPortal/DaiPortal.m | 289 ++++++++++++++++++ .../DaiPortal/DaiPortalBlockAnalysis.h | 25 ++ .../DaiPortal/DaiPortalBlockAnalysis.m | 67 ++++ .../DaiPortal/DaiPortalPerformHelper.h | 18 ++ .../DaiPortal/DaiPortalPerformHelper.m | 161 ++++++++++ .../ThirdParty/DaiPortal/DaiPortalWarehouse.h | 23 ++ .../ThirdParty/DaiPortal/DaiPortalWarehouse.m | 69 +++++ .../ThirdParty/DaiPortal/NSObject+DaiPortal.h | 21 ++ .../ThirdParty/DaiPortal/NSObject+DaiPortal.m | 31 ++ e-Hentai/e-Hentai-Prefix.pch | 1 + 15 files changed, 825 insertions(+), 28 deletions(-) create mode 100644 e-Hentai/ThirdParty/DaiPortal/DaiPortal.h create mode 100644 e-Hentai/ThirdParty/DaiPortal/DaiPortal.m create mode 100644 e-Hentai/ThirdParty/DaiPortal/DaiPortalBlockAnalysis.h create mode 100644 e-Hentai/ThirdParty/DaiPortal/DaiPortalBlockAnalysis.m create mode 100644 e-Hentai/ThirdParty/DaiPortal/DaiPortalPerformHelper.h create mode 100644 e-Hentai/ThirdParty/DaiPortal/DaiPortalPerformHelper.m create mode 100644 e-Hentai/ThirdParty/DaiPortal/DaiPortalWarehouse.h create mode 100644 e-Hentai/ThirdParty/DaiPortal/DaiPortalWarehouse.m create mode 100644 e-Hentai/ThirdParty/DaiPortal/NSObject+DaiPortal.h create mode 100644 e-Hentai/ThirdParty/DaiPortal/NSObject+DaiPortal.m diff --git a/README.md b/README.md index 0b93d5b9..3a4eb773 100644 --- a/README.md +++ b/README.md @@ -61,4 +61,10 @@ daidoujichen@gmail.com - 提供一些不同於系統色的一些額外色調. - Icons8 App - - 可以免費取得一些 icon 的小工具. \ No newline at end of file + - 可以免費取得一些 icon 的小工具. + +- DaiInboxHUD + - 我自己隔壁棚的工具, 是個模仿 inbox app 等待中的 hud. + +- DaiPortalV2 + - 我自己隔壁棚的工具, 導進來試用看看, 一邊做調整, 目前的定位還不是太清楚, 試用中. \ No newline at end of file diff --git a/e-Hentai.xcodeproj/project.pbxproj b/e-Hentai.xcodeproj/project.pbxproj index 94574b60..16f711e4 100644 --- a/e-Hentai.xcodeproj/project.pbxproj +++ b/e-Hentai.xcodeproj/project.pbxproj @@ -70,6 +70,11 @@ 0180D92C1A02140E002554FC /* settings@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0180D92A1A02140E002554FC /* settings@3x.png */; }; 0180D92F1A0214AD002554FC /* delivery@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0180D92D1A0214AD002554FC /* delivery@2x.png */; }; 0180D9301A0214AD002554FC /* delivery@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0180D92E1A0214AD002554FC /* delivery@3x.png */; }; + 019290211A25D6C70094B423 /* DaiPortal.m in Sources */ = {isa = PBXBuildFile; fileRef = 019290181A25D6C70094B423 /* DaiPortal.m */; }; + 019290221A25D6C70094B423 /* DaiPortalBlockAnalysis.m in Sources */ = {isa = PBXBuildFile; fileRef = 0192901A1A25D6C70094B423 /* DaiPortalBlockAnalysis.m */; }; + 019290231A25D6C70094B423 /* DaiPortalPerformHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 0192901C1A25D6C70094B423 /* DaiPortalPerformHelper.m */; }; + 019290241A25D6C70094B423 /* DaiPortalWarehouse.m in Sources */ = {isa = PBXBuildFile; fileRef = 0192901E1A25D6C70094B423 /* DaiPortalWarehouse.m */; }; + 019290251A25D6C70094B423 /* NSObject+DaiPortal.m in Sources */ = {isa = PBXBuildFile; fileRef = 019290201A25D6C70094B423 /* NSObject+DaiPortal.m */; }; 0199268919ADDB83009F814B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0199268819ADDB83009F814B /* Foundation.framework */; }; 0199268B19ADDB83009F814B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0199268A19ADDB83009F814B /* CoreGraphics.framework */; }; 0199268D19ADDB83009F814B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0199268C19ADDB83009F814B /* UIKit.framework */; }; @@ -189,6 +194,16 @@ 0180D92A1A02140E002554FC /* settings@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "settings@3x.png"; sourceTree = ""; }; 0180D92D1A0214AD002554FC /* delivery@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "delivery@2x.png"; sourceTree = ""; }; 0180D92E1A0214AD002554FC /* delivery@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "delivery@3x.png"; sourceTree = ""; }; + 019290171A25D6C70094B423 /* DaiPortal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DaiPortal.h; sourceTree = ""; }; + 019290181A25D6C70094B423 /* DaiPortal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DaiPortal.m; sourceTree = ""; }; + 019290191A25D6C70094B423 /* DaiPortalBlockAnalysis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DaiPortalBlockAnalysis.h; sourceTree = ""; }; + 0192901A1A25D6C70094B423 /* DaiPortalBlockAnalysis.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DaiPortalBlockAnalysis.m; sourceTree = ""; }; + 0192901B1A25D6C70094B423 /* DaiPortalPerformHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DaiPortalPerformHelper.h; sourceTree = ""; }; + 0192901C1A25D6C70094B423 /* DaiPortalPerformHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DaiPortalPerformHelper.m; sourceTree = ""; }; + 0192901D1A25D6C70094B423 /* DaiPortalWarehouse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DaiPortalWarehouse.h; sourceTree = ""; }; + 0192901E1A25D6C70094B423 /* DaiPortalWarehouse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DaiPortalWarehouse.m; sourceTree = ""; }; + 0192901F1A25D6C70094B423 /* NSObject+DaiPortal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+DaiPortal.h"; sourceTree = ""; }; + 019290201A25D6C70094B423 /* NSObject+DaiPortal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+DaiPortal.m"; sourceTree = ""; }; 0199268519ADDB83009F814B /* e-Hentai.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "e-Hentai.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 0199268819ADDB83009F814B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 0199268A19ADDB83009F814B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; @@ -342,6 +357,7 @@ 0150033619B6E5E90055F47D /* ThirdParty */ = { isa = PBXGroup; children = ( + 019290161A25D6C70094B423 /* DaiPortal */, 01624CDF1A0B5A6400568EC8 /* DaiInboxHUD */, 016DAD9419E392F900E528BE /* GooglePlus */, 016BBEF919B94E4F0015E11E /* FilesManager */, @@ -486,6 +502,23 @@ path = MenuViewController; sourceTree = ""; }; + 019290161A25D6C70094B423 /* DaiPortal */ = { + isa = PBXGroup; + children = ( + 019290171A25D6C70094B423 /* DaiPortal.h */, + 019290181A25D6C70094B423 /* DaiPortal.m */, + 019290191A25D6C70094B423 /* DaiPortalBlockAnalysis.h */, + 0192901A1A25D6C70094B423 /* DaiPortalBlockAnalysis.m */, + 0192901B1A25D6C70094B423 /* DaiPortalPerformHelper.h */, + 0192901C1A25D6C70094B423 /* DaiPortalPerformHelper.m */, + 0192901D1A25D6C70094B423 /* DaiPortalWarehouse.h */, + 0192901E1A25D6C70094B423 /* DaiPortalWarehouse.m */, + 0192901F1A25D6C70094B423 /* NSObject+DaiPortal.h */, + 019290201A25D6C70094B423 /* NSObject+DaiPortal.m */, + ); + path = DaiPortal; + sourceTree = ""; + }; 0199267C19ADDB83009F814B = { isa = PBXGroup; children = ( @@ -747,6 +780,7 @@ 016BBF0D19B94E4F0015E11E /* LightWeightPlist+AccessObject.m in Sources */, 0150034519B6E5E90055F47D /* TFHppleElement.m in Sources */, 016BBF0C19B94E4F0015E11E /* FMStream.m in Sources */, + 019290221A25D6C70094B423 /* DaiPortalBlockAnalysis.m in Sources */, 0150034619B6E5E90055F47D /* XPathQuery.m in Sources */, 01624CE81A0B5A6400568EC8 /* DaiInboxHUD.m in Sources */, 01FB6FD419E23FB4006CBEF2 /* NSString+Hentai.m in Sources */, @@ -760,16 +794,20 @@ 01BFAD5119DE435700A5649F /* SettingViewController.m in Sources */, 0118081519B6F06200FE0DA1 /* FakeViewController.m in Sources */, 01624CEB1A0B5A6400568EC8 /* DaiIndoxWindow.m in Sources */, + 019290241A25D6C70094B423 /* DaiPortalWarehouse.m in Sources */, 017AE5C21A00D24600317939 /* SearchFilterViewController.m in Sources */, 0118081B19B6F06200FE0DA1 /* PhotoViewController.m in Sources */, 0137F40F19C1695800528359 /* HentaiDownloadBookOperation.m in Sources */, 016BBF1019B94E4F0015E11E /* LightWeightPlist+SourceFromDisk.m in Sources */, + 019290231A25D6C70094B423 /* DaiPortalPerformHelper.m in Sources */, 01A166EC19E28D5E00203360 /* NSDictionary+Hentai.m in Sources */, 01BC52251A0CC04B00B37891 /* DaiInboxDisplayLink.m in Sources */, 011AEA5119DD28DE00A15CA5 /* SliderViewController.m in Sources */, 01624CEA1A0B5A6400568EC8 /* DaiInboxViewController.m in Sources */, + 019290251A25D6C70094B423 /* NSObject+DaiPortal.m in Sources */, 01BBD60119E3D428003538CF /* HentaiPhotoCell.m in Sources */, 016BBF1119B94E4F0015E11E /* LightWeightPlist.m in Sources */, + 019290211A25D6C70094B423 /* DaiPortal.m in Sources */, 016BBF0B19B94E4F0015E11E /* FilesManager.m in Sources */, 0163C7D719D8FD5300105ECF /* DownloadedViewController.m in Sources */, 01624CE91A0B5A6400568EC8 /* DaiInboxView.m in Sources */, diff --git a/e-Hentai/HentaiDownloadCenter/HentaiDownloadBookOperation.m b/e-Hentai/HentaiDownloadCenter/HentaiDownloadBookOperation.m index aa0537ce..8891e6d8 100644 --- a/e-Hentai/HentaiDownloadCenter/HentaiDownloadBookOperation.m +++ b/e-Hentai/HentaiDownloadCenter/HentaiDownloadBookOperation.m @@ -166,22 +166,14 @@ - (void)checkEndOfFile { @weakify(self); [HentaiParser requestImagesAtURL:self.hentaiInfo[@"url"] atIndex:self.hentaiIndex completion: ^(HentaiParserStatus status, NSArray *images) { @strongify(self); - if (![self isCancelled]) { - switch (status) { - case HentaiParserStatusSuccess: - [self.hentaiImageURLs addObjectsFromArray:images]; - [self preloadImages:images]; - [self waitingOnDownloadFinish]; - break; - case HentaiParserStatusNetworkFail: - [UIAlertView hentai_alertViewWithTitle:self.hentaiInfo[@"title"] message:@"網路失敗~所以無法下載~" cancelButtonTitle:@"好~ O3O"]; - [self hentaiFinish]; - break; - case HentaiParserStatusParseFail: - [UIAlertView hentai_alertViewWithTitle:self.hentaiInfo[@"title"] message:@"被移除囉~所以無法下載~" cancelButtonTitle:@"好~ O3O"]; - [self hentaiFinish]; - break; - } + if (status && ![self isCancelled] && [images count]) { + [self.hentaiImageURLs addObjectsFromArray:images]; + [self preloadImages:images]; + [self waitingOnDownloadFinish]; + } + else { + [UIAlertView hentai_alertViewWithTitle:self.hentaiInfo[@"title"] message:@"被移除囉~所以無法下載~" cancelButtonTitle:@"好~ O3O"]; + [self hentaiFinish]; } }]; } @@ -196,7 +188,7 @@ - (void)checkEndOfFile { [HentaiCacheLibraryDictionary removeObjectForKey:self.hentaiKey]; LWPForceWrite(); ) - [[NSNotificationCenter defaultCenter] postNotificationName:HentaiDownloadSuccessNotification object:self.hentaiInfo[@"title"]]; + [[self portal:HentaiDownloadSuccessNotification] send:[DaiPortalPackage item:self.hentaiInfo[@"title"]]]; [self hentaiFinish]; } else { diff --git a/e-Hentai/MainViewController/MainViewController.m b/e-Hentai/MainViewController/MainViewController.m index 5260440e..d08ac5c5 100644 --- a/e-Hentai/MainViewController/MainViewController.m +++ b/e-Hentai/MainViewController/MainViewController.m @@ -165,14 +165,11 @@ - (void)reloadDatas { //把 request 的判斷都放到這個 method 裡面來 - (void)loadList:(void (^)(BOOL successed, NSArray *listArray))completion { [HentaiParser requestListAtFilterUrl:self.filterString completion: ^(HentaiParserStatus status, NSArray *listArray) { - switch (status) { - case HentaiParserStatusSuccess: - completion(YES, listArray); - break; - case HentaiParserStatusParseFail: - case HentaiParserStatusNetworkFail: - completion(NO, nil); - break; + if (status && [listArray count]) { + completion(YES, listArray); + } + else { + completion(NO, nil); } }]; } @@ -228,10 +225,10 @@ - (void)setupRecvNotifications { //接 HentaiDownloadSuccessNotification @weakify(self); - [[[NSNotificationCenter defaultCenter] rac_addObserverForName:HentaiDownloadSuccessNotification object:nil] subscribeNext: ^(NSNotification *notification) { + [[self portal:HentaiDownloadSuccessNotification] recv: ^(NSString *alertViewMessage) { @strongify(self); if (self && [UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController == nil) { - [UIAlertView hentai_alertViewWithTitle:@"下載完成!" message:notification.object cancelButtonTitle:@"好~ O3O"]; + [UIAlertView hentai_alertViewWithTitle:@"下載完成!" message:alertViewMessage cancelButtonTitle:@"好~ O3O"]; } }]; } diff --git a/e-Hentai/ThirdParty/DaiPortal/DaiPortal.h b/e-Hentai/ThirdParty/DaiPortal/DaiPortal.h new file mode 100644 index 00000000..e331d2cf --- /dev/null +++ b/e-Hentai/ThirdParty/DaiPortal/DaiPortal.h @@ -0,0 +1,59 @@ +// +// DaiPortal.h +// DaiPortalV2 +// +// Created by 啟倫 陳 on 2014/11/24. +// Copyright (c) 2014年 ChilunChen. All rights reserved. +// + +#import + +//為了統一傳進跟回傳的東西, 所以用一個固定的格式來規範 +@interface DaiPortalPackage : NSObject + +//空的包包, 什麼都沒有 ++ (DaiPortalPackage *)empty; + +//只有一個物件 ++ (DaiPortalPackage *)item:(id)anItem; + +//很多的物件 ++ (DaiPortalPackage *)items:(id)firstItem, ...NS_REQUIRES_NIL_TERMINATION; + +@end + +typedef void (^VoidBlock)(); +typedef DaiPortalPackage *(^PackageBlock)(); + +@interface DaiPortal : NSObject + +//分別是該傳送門的識別名稱跟所依附的物件 +@property (nonatomic, strong) NSString *identifier; +@property (nonatomic, weak) id dependObject; + +@end + +//建立用來接收資料的部分, 收到觸發時會運行 aBlock 的內容, 帶上 warp 結尾的 method, block 內的 code 會以非同步方式運行 +@interface DaiPortal (Reciver) + +- (void)recv:(VoidBlock)aBlock; +- (void)recv_warp:(VoidBlock)aBlock; +- (void)respond:(PackageBlock)aBlock; +- (void)respond_warp:(PackageBlock)aBlock; + +@end + +//用來傳送資料的部分, 負責觸發已建立的傳送門, 帶上 warp 結尾的 method, block 內的 code 會以非同步方式運行 +@interface DaiPortal (Sender) + +//send 為傳一個以上的東西過去, send 則為純粹的觸發 +- (void)send:(DaiPortalPackage *)package; +- (void)send; + +//帶上 result 的話可以收到回傳的訊息 +- (void)send:(DaiPortalPackage *)package completion:(VoidBlock)completion; +- (void)send:(DaiPortalPackage *)package completion_warp:(VoidBlock)completion; +- (void)completion:(VoidBlock)completion; +- (void)completion_warp:(VoidBlock)completion; + +@end diff --git a/e-Hentai/ThirdParty/DaiPortal/DaiPortal.m b/e-Hentai/ThirdParty/DaiPortal/DaiPortal.m new file mode 100644 index 00000000..e9ed27aa --- /dev/null +++ b/e-Hentai/ThirdParty/DaiPortal/DaiPortal.m @@ -0,0 +1,289 @@ +// +// DaiPortal.m +// DaiPortalV2 +// +// Created by 啟倫 陳 on 2014/11/24. +// Copyright (c) 2014年 ChilunChen. All rights reserved. +// + +#import "DaiPortal.h" + +#import +#import "DaiPortalWarehouse.h" +#import "DaiPortalBlockAnalysis.h" +#import "DaiPortalPerformHelper.h" + +//https://github.com/krzysztofzablocki/NSObject-SFExecuteOnDealloc +//用來檢測物件是否 dealloc + +@interface SFExecuteOnDeallocInternalObject : NSObject + +@property (nonatomic, copy) void (^block)(); + +- (id)initWithBlock:(void (^)(void))aBlock; + +@end + +@implementation SFExecuteOnDeallocInternalObject + +- (id)initWithBlock:(void (^)(void))aBlock { + self = [super init]; + if (self) { + self.block = aBlock; + } + return self; +} + +- (void)dealloc { + if (self.block) { + self.block(); + } +} + +@end + +@interface DaiPortalPackage () + +@property (nonatomic, strong) id anyObject; + +@end + +@implementation DaiPortalPackage + ++ (DaiPortalPackage *)empty { + DaiPortalPackage *newResult = [DaiPortalPackage new]; + newResult.anyObject = nil; + return newResult; +} + ++ (DaiPortalPackage *)item:(id)anObject { + DaiPortalPackage *newResult = [DaiPortalPackage new]; + newResult.anyObject = @[anObject]; + return newResult; +} + ++ (DaiPortalPackage *)items:(id)firstItem, ...NS_REQUIRES_NIL_TERMINATION { + NSMutableArray *objects = [NSMutableArray array]; + if (firstItem) { + va_list list; + id listObject = firstItem; + va_start(list, firstItem); + do { + if (listObject) { + [objects addObject:listObject]; + } + listObject = va_arg(list, id); + } + while (listObject != nil); + va_end(list); + } + DaiPortalPackage *newResult = [DaiPortalPackage new]; + newResult.anyObject = objects; + return newResult; +} + +@end + +@interface DaiPortal () + +@property (nonatomic, copy) id actionBlock; +@property (nonatomic, readonly) NSUInteger argumentsInBlock; +@property (nonatomic, assign) BOOL isDisposable; +@property (nonatomic, assign) BOOL isWarp; + +- (void)deallocObserver; +- (void)signPortal:(id)block; +- (void)broadcastObjects:(NSArray *)objects toIdentifier:(NSString *)identifier; +- (void)handleRecvNotification:(NSNotification *)reciverNotification; + +@end + +@implementation DaiPortal + +- (id)init { + self = [super init]; + if (self) { + self.isWarp = NO; + self.isDisposable = NO; + } + return self; +} + +- (void)setActionBlock:(id)actionBlock { + _actionBlock = [actionBlock copy]; + _argumentsInBlock = [DaiPortalBlockAnalysis argumentsInBlock:actionBlock] - 1; +} + +//用來監測物件是否該被移除 +- (void)deallocObserver { + if (!objc_getAssociatedObject(self.dependObject, _cmd)) { + SFExecuteOnDeallocInternalObject *internalObject = [[SFExecuteOnDeallocInternalObject alloc] initWithBlock: ^{ + [DaiPortalWarehouse resign:self.dependObject]; + }]; + objc_setAssociatedObject(self.dependObject, _cmd, internalObject, OBJC_ASSOCIATION_RETAIN); + } +} + +//把新的傳送門登記到倉庫中 +- (void)signPortal:(id)block { + [self deallocObserver]; + self.actionBlock = block; + [[DaiPortalWarehouse daiPortalNotificationCenter] addObserver:self selector:@selector(handleRecvNotification:) name:self.identifier object:nil]; + [DaiPortalWarehouse sign:self]; +} + +//把資料群發出去給想收的人 +- (void)broadcastObjects:(NSArray *)objects toIdentifier:(NSString *)identifier { + [[DaiPortalWarehouse daiPortalNotificationCenter] postNotificationName:identifier object:objects userInfo:@{ @"source": self.dependObject }]; +} + +//控制接到的通知 +- (void)handleRecvNotification:(NSNotification *)notification { + //如果依附的對象已經被刪除, 這邊則直接將他從 list 移除 + if (!self.dependObject) { + [DaiPortalWarehouse removeDisposable:self]; + return; + } + + //要先看傳送過來的數量是不是跟要輸出的數量一致 + if (self.argumentsInBlock == [notification.object count]) { + //根據 block 的類型又可以分為回傳 void 及 DaiPortalPackage 兩種 + switch ([DaiPortalBlockAnalysis returnTypeInBlock:self.actionBlock]) { + case DaiPortalBlockAnalysisReturnTypeID: + { + if (self.isWarp) { + __weak DaiPortal *weakSelf = self; + [self warp: ^{ + DaiPortalPackage *result = [DaiPortalPerformHelper idPerformObjects:notification.object usingBlock:weakSelf.actionBlock]; + [weakSelf weft: ^{ + if (result && result.anyObject) { + [weakSelf broadcastObjects:result.anyObject toIdentifier:[NSString stringWithFormat:@"%@_result", weakSelf.identifier]]; + } + [weakSelf disposableCheck]; + }]; + }]; + } + else { + DaiPortalPackage *result = [DaiPortalPerformHelper idPerformObjects:notification.object usingBlock:self.actionBlock]; + if (result && result.anyObject) { + [self broadcastObjects:result.anyObject toIdentifier:[NSString stringWithFormat:@"%@_result", self.identifier]]; + } + [self disposableCheck]; + } + break; + } + + case DaiPortalBlockAnalysisReturnTypeVoid: + { + if (self.isWarp) { + __weak DaiPortal *weakSelf = self; + [self warp: ^{ + [DaiPortalPerformHelper voidPerformObjects:notification.object usingBlock:weakSelf.actionBlock]; + [weakSelf weft: ^{ + [weakSelf disposableCheck]; + }]; + }]; + } + else { + [DaiPortalPerformHelper voidPerformObjects:notification.object usingBlock:self.actionBlock]; + [self disposableCheck]; + } + break; + } + + case DaiPortalBlockAnalysisReturnTypeUnknow: + { + NSLog(@"應該沒有人會到這邊吧, O口O!"); + break; + } + } + } + else { + NSLog(@"從 %@ 傳送往 %@, 識別為 <%@> 的參數數量不匹配.", notification.userInfo[@"source"], self.dependObject, self.identifier); + } +} + +- (void)disposableCheck { + //免洗的傳送門用一次就丟掉 + if (self.isDisposable) { + [DaiPortalWarehouse removeDisposable:self]; + } +} + +- (void)warp:(void (^)(void))block { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block); +} + +- (void)weft:(void (^)(void))block { + dispatch_async(dispatch_get_main_queue(), block); +} + +@end + +@implementation DaiPortal (Reciver) + +- (void)recv:(VoidBlock)aBlock { + [self signPortal:aBlock]; +} + +- (void)recv_warp:(VoidBlock)aBlock { + self.isWarp = YES; + [self recv:aBlock]; +} + +- (void)respond:(PackageBlock)aBlock { + [self signPortal:aBlock]; +} + +- (void)respond_warp:(PackageBlock)aBlock { + self.isWarp = YES; + [self respond:aBlock]; +} + +@end + +@implementation DaiPortal (Sender) + +- (void)send:(DaiPortalPackage *)package { + [self broadcastObjects:package.anyObject toIdentifier:self.identifier]; +} + +- (void)send { + [self send:[DaiPortalPackage empty]]; +} + +- (void)send:(DaiPortalPackage *)package completion:(VoidBlock)completion { + [self signResultPortal:completion isWarp:NO]; + [self send:package]; +} + +- (void)send:(DaiPortalPackage *)package completion_warp:(VoidBlock)completion { + [self signResultPortal:completion isWarp:YES]; + [self send:package]; +} + +- (void)completion:(VoidBlock)completion { + [self signResultPortal:completion isWarp:NO]; + [self send:[DaiPortalPackage empty]]; +} + +- (void)completion_warp:(VoidBlock)completion { + [self signResultPortal:completion isWarp:YES]; + [self send:[DaiPortalPackage empty]]; +} + +#pragma mark - private + +- (void)signResultPortal:(id)block isWarp:(BOOL)isWarp { + [self deallocObserver]; + DaiPortal *resultPortal = [DaiPortal new]; + resultPortal.identifier = [NSString stringWithFormat:@"%@_result", self.identifier]; + resultPortal.dependObject = self.dependObject; + resultPortal.actionBlock = block; + resultPortal.isDisposable = YES; + resultPortal.isWarp = isWarp; + [[DaiPortalWarehouse daiPortalNotificationCenter] addObserver:resultPortal selector:@selector(handleRecvNotification:) name:resultPortal.identifier object:nil]; + [DaiPortalWarehouse sign:resultPortal]; +} + +@end diff --git a/e-Hentai/ThirdParty/DaiPortal/DaiPortalBlockAnalysis.h b/e-Hentai/ThirdParty/DaiPortal/DaiPortalBlockAnalysis.h new file mode 100644 index 00000000..5790fe47 --- /dev/null +++ b/e-Hentai/ThirdParty/DaiPortal/DaiPortalBlockAnalysis.h @@ -0,0 +1,25 @@ +// +// DaiPortalBlockAnalysis.h +// DaiPortal +// +// Created by 啟倫 陳 on 2014/11/18. +// Copyright (c) 2014年 ChilunChen. All rights reserved. +// + +//https://github.com/mikeash/MABlockForwarding +//用來檢測 block 裡面包含的參數數量 + +typedef enum { + DaiPortalBlockAnalysisReturnTypeID, + DaiPortalBlockAnalysisReturnTypeVoid, + DaiPortalBlockAnalysisReturnTypeUnknow +} DaiPortalBlockAnalysisReturnType; + +#import + +@interface DaiPortalBlockAnalysis : NSObject + ++ (NSUInteger)argumentsInBlock:(id)blockObj; ++ (DaiPortalBlockAnalysisReturnType)returnTypeInBlock:(id)blockObj; + +@end diff --git a/e-Hentai/ThirdParty/DaiPortal/DaiPortalBlockAnalysis.m b/e-Hentai/ThirdParty/DaiPortal/DaiPortalBlockAnalysis.m new file mode 100644 index 00000000..477275ac --- /dev/null +++ b/e-Hentai/ThirdParty/DaiPortal/DaiPortalBlockAnalysis.m @@ -0,0 +1,67 @@ +// +// DaiPortalBlockAnalysis.m +// DaiPortal +// +// Created by 啟倫 陳 on 2014/11/18. +// Copyright (c) 2014年 ChilunChen. All rights reserved. +// + +#import "DaiPortalBlockAnalysis.h" + +struct BlockDescriptor { + unsigned long reserved; + unsigned long size; + void *rest[1]; +}; + +struct Block { + void *isa; + int flags; + int reserved; + void *invoke; + struct BlockDescriptor *descriptor; +}; + +enum { + BLOCK_HAS_COPY_DISPOSE = (1 << 25), + BLOCK_HAS_CTOR = (1 << 26), + BLOCK_IS_GLOBAL = (1 << 28), + BLOCK_HAS_STRET = (1 << 29), + BLOCK_HAS_SIGNATURE = (1 << 30), +}; + +@implementation DaiPortalBlockAnalysis + ++ (NSUInteger)argumentsInBlock:(id)blockObj { + struct Block *block = (__bridge void *)blockObj; + struct BlockDescriptor *descriptor = block->descriptor; + assert(block->flags & BLOCK_HAS_SIGNATURE); + int index = 0; + if (block->flags & BLOCK_HAS_COPY_DISPOSE) { + index += 2; + } + NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:descriptor->rest[index]]; + return [signature numberOfArguments]; +} + ++ (DaiPortalBlockAnalysisReturnType)returnTypeInBlock:(id)blockObj { + struct Block *block = (__bridge void *)blockObj; + struct BlockDescriptor *descriptor = block->descriptor; + assert(block->flags & BLOCK_HAS_SIGNATURE); + int index = 0; + if (block->flags & BLOCK_HAS_COPY_DISPOSE) { + index += 2; + } + NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:descriptor->rest[index]]; + if (strncmp(signature.methodReturnType, "@", 1) == 0) { + return DaiPortalBlockAnalysisReturnTypeID; + } + else if (strncmp(signature.methodReturnType, "v", 1) == 0) { + return DaiPortalBlockAnalysisReturnTypeVoid; + } + else { + return DaiPortalBlockAnalysisReturnTypeUnknow; + } +} + +@end diff --git a/e-Hentai/ThirdParty/DaiPortal/DaiPortalPerformHelper.h b/e-Hentai/ThirdParty/DaiPortal/DaiPortalPerformHelper.h new file mode 100644 index 00000000..eb93ba1c --- /dev/null +++ b/e-Hentai/ThirdParty/DaiPortal/DaiPortalPerformHelper.h @@ -0,0 +1,18 @@ +// +// DaiPortalPerformHelper.h +// DaiPortal +// +// Created by 啟倫 陳 on 2014/11/18. +// Copyright (c) 2014年 ChilunChen. All rights reserved. +// + +//概念來自 ReactiveCocoa 裡面的 RACBlockTrampoline + +#import + +@interface DaiPortalPerformHelper : NSObject + ++ (id)idPerformObjects:(NSArray *)objects usingBlock:(id)block; ++ (void)voidPerformObjects:(NSArray *)objects usingBlock:(id)block; + +@end diff --git a/e-Hentai/ThirdParty/DaiPortal/DaiPortalPerformHelper.m b/e-Hentai/ThirdParty/DaiPortal/DaiPortalPerformHelper.m new file mode 100644 index 00000000..86546158 --- /dev/null +++ b/e-Hentai/ThirdParty/DaiPortal/DaiPortalPerformHelper.m @@ -0,0 +1,161 @@ +// +// DaiPortalPerformHelper.m +// DaiPortal +// +// Created by 啟倫 陳 on 2014/11/18. +// Copyright (c) 2014年 ChilunChen. All rights reserved. +// + +#import "DaiPortalPerformHelper.h" + +@implementation DaiPortalPerformHelper + ++ (id)idPerformObjects:(NSArray *)objects usingBlock:(id)block { + switch ([objects count]) { + case 0: + { + id (^performBlock)() = block; + return performBlock(); + } + + case 1: + { + id (^performBlock)(id) = block; + return performBlock(objects[0]); + } + + case 2: + { + id (^performBlock)(id, id) = block; + return performBlock(objects[0], objects[1]); + } + + case 3: + { + id (^performBlock)(id, id, id) = block; + return performBlock(objects[0], objects[1], objects[2]); + } + + case 4: + { + id (^performBlock)(id, id, id, id) = block; + return performBlock(objects[0], objects[1], objects[2], objects[3]); + } + + case 5: + { + id (^performBlock)(id, id, id, id, id) = block; + return performBlock(objects[0], objects[1], objects[2], objects[3], objects[4]); + } + + case 6: + { + id (^performBlock)(id, id, id, id, id, id) = block; + return performBlock(objects[0], objects[1], objects[2], objects[3], objects[4], objects[5]); + } + + case 7: + { + id (^performBlock)(id, id, id, id, id, id, id) = block; + return performBlock(objects[0], objects[1], objects[2], objects[3], objects[4], objects[5], objects[6]); + } + + case 8: + { + id (^performBlock)(id, id, id, id, id, id, id, id) = block; + return performBlock(objects[0], objects[1], objects[2], objects[3], objects[4], objects[5], objects[6], objects[7]); + } + + case 9: + { + id (^performBlock)(id, id, id, id, id, id, id, id, id) = block; + return performBlock(objects[0], objects[1], objects[2], objects[3], objects[4], objects[5], objects[6], objects[7], objects[8]); + } + + default: + { + NSLog(@"參數太多了, 沒有支援囉"); + return nil; + } + } +} + ++ (void)voidPerformObjects:(NSArray *)objects usingBlock:(id)block { + switch ([objects count]) { + case 0: + { + void (^performBlock)() = block; + performBlock(); + break; + } + + case 1: + { + void (^performBlock)(id) = block; + performBlock(objects[0]); + break; + } + + case 2: + { + void (^performBlock)(id, id) = block; + performBlock(objects[0], objects[1]); + break; + } + + case 3: + { + void (^performBlock)(id, id, id) = block; + performBlock(objects[0], objects[1], objects[2]); + break; + } + + case 4: + { + void (^performBlock)(id, id, id, id) = block; + performBlock(objects[0], objects[1], objects[2], objects[3]); + break; + } + + case 5: + { + void (^performBlock)(id, id, id, id, id) = block; + performBlock(objects[0], objects[1], objects[2], objects[3], objects[4]); + break; + } + + case 6: + { + void (^performBlock)(id, id, id, id, id, id) = block; + performBlock(objects[0], objects[1], objects[2], objects[3], objects[4], objects[5]); + break; + } + + case 7: + { + void (^performBlock)(id, id, id, id, id, id, id) = block; + performBlock(objects[0], objects[1], objects[2], objects[3], objects[4], objects[5], objects[6]); + break; + } + + case 8: + { + void (^performBlock)(id, id, id, id, id, id, id, id) = block; + performBlock(objects[0], objects[1], objects[2], objects[3], objects[4], objects[5], objects[6], objects[7]); + break; + } + + case 9: + { + void (^performBlock)(id, id, id, id, id, id, id, id, id) = block; + performBlock(objects[0], objects[1], objects[2], objects[3], objects[4], objects[5], objects[6], objects[7], objects[8]); + break; + } + + default: + NSLog(@"參數太多了, 沒有支援囉"); + break; + } +} + +@end diff --git a/e-Hentai/ThirdParty/DaiPortal/DaiPortalWarehouse.h b/e-Hentai/ThirdParty/DaiPortal/DaiPortalWarehouse.h new file mode 100644 index 00000000..b0d1f125 --- /dev/null +++ b/e-Hentai/ThirdParty/DaiPortal/DaiPortalWarehouse.h @@ -0,0 +1,23 @@ +// +// DaiPortalWarehouse.h +// DaiPortalV2 +// +// Created by 啟倫 陳 on 2014/11/24. +// Copyright (c) 2014年 ChilunChen. All rights reserved. +// + +#import + +#import "DaiPortal.h" + +@interface DaiPortalWarehouse : NSObject + +//分別處理登記, 註銷, 移除一次性使用傳送門 ++ (void)sign:(DaiPortal *)newPortal; ++ (void)resign:(id)dependObject; ++ (void)removeDisposable:(DaiPortal *)disposableObject; + +//daiportal 專用的 notification center, 不會跟系統的混在一起 ++ (NSNotificationCenter *)daiPortalNotificationCenter; + +@end diff --git a/e-Hentai/ThirdParty/DaiPortal/DaiPortalWarehouse.m b/e-Hentai/ThirdParty/DaiPortal/DaiPortalWarehouse.m new file mode 100644 index 00000000..2eabab61 --- /dev/null +++ b/e-Hentai/ThirdParty/DaiPortal/DaiPortalWarehouse.m @@ -0,0 +1,69 @@ +// +// DaiPortalWarehouse.m +// DaiPortalV2 +// +// Created by 啟倫 陳 on 2014/11/24. +// Copyright (c) 2014年 ChilunChen. All rights reserved. +// + +#import "DaiPortalWarehouse.h" + +#import + +@implementation DaiPortalWarehouse + +#pragma mark - class method + ++ (void)sign:(DaiPortal *)newPortal { + __weak id weakSelf = self; + [self portalPotecter: ^{ + [[weakSelf portals] addObject:newPortal]; + }]; +} + ++ (void)resign:(id)dependObject { + __weak id weakSelf = self; + [self portalPotecter: ^{ + NSMutableArray *removeObjects = [NSMutableArray array]; + for (DaiPortal *eachPortal in [weakSelf portals]) { + if (eachPortal.dependObject == dependObject) { + [[weakSelf daiPortalNotificationCenter] removeObserver:eachPortal]; + [removeObjects addObject:eachPortal]; + } + } + [[weakSelf portals] removeObjectsInArray:removeObjects]; + }]; +} + ++ (void)removeDisposable:(DaiPortal *)disposableObject { + __weak id weakSelf = self; + [self portalPotecter: ^{ + [[weakSelf daiPortalNotificationCenter] removeObserver:disposableObject]; + [[weakSelf portals] removeObject:disposableObject]; + }]; +} + +#pragma mark - private + ++ (void)portalPotecter:(void (^)(void))yourCode { + //dispatch_sync(dispatch_get_main_queue(), yourCode); + yourCode(); +} + ++ (NSMutableArray *)portals { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + objc_setAssociatedObject(self, _cmd, [NSMutableArray array], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + }); + return objc_getAssociatedObject(self, _cmd); +} + ++ (NSNotificationCenter *)daiPortalNotificationCenter { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + objc_setAssociatedObject(self, _cmd, [NSNotificationCenter new], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + }); + return objc_getAssociatedObject(self, _cmd); +} + +@end diff --git a/e-Hentai/ThirdParty/DaiPortal/NSObject+DaiPortal.h b/e-Hentai/ThirdParty/DaiPortal/NSObject+DaiPortal.h new file mode 100644 index 00000000..72c9474e --- /dev/null +++ b/e-Hentai/ThirdParty/DaiPortal/NSObject+DaiPortal.h @@ -0,0 +1,21 @@ +// +// NSObject+DaiPortal.h +// DaiPortalV2 +// +// Created by 啟倫 陳 on 2014/11/25. +// Copyright (c) 2014年 ChilunChen. All rights reserved. +// + +#import + +#import "DaiPortal.h" + +@interface NSObject (DaiPortal) + +//開端, 所有的傳送門都需要先有一個識別的名字 +- (DaiPortal *)portal:(NSString *)identifier; + +// - 是掛在 instance 身上, + 則是掛在 class 身上 ++ (DaiPortal *)portal:(NSString *)identifier; + +@end diff --git a/e-Hentai/ThirdParty/DaiPortal/NSObject+DaiPortal.m b/e-Hentai/ThirdParty/DaiPortal/NSObject+DaiPortal.m new file mode 100644 index 00000000..300f83b1 --- /dev/null +++ b/e-Hentai/ThirdParty/DaiPortal/NSObject+DaiPortal.m @@ -0,0 +1,31 @@ +// +// NSObject+DaiPortal.m +// DaiPortalV2 +// +// Created by 啟倫 陳 on 2014/11/25. +// Copyright (c) 2014年 ChilunChen. All rights reserved. +// + +#import "NSObject+DaiPortal.h" + +@implementation NSObject (DaiPortal) + +#pragma mark - instance method + +- (DaiPortal *)portal:(NSString *)identifier { + DaiPortal *newPortal = [DaiPortal new]; + newPortal.identifier = identifier; + newPortal.dependObject = self; + return newPortal; +} + +#pragma mark - class method + ++ (DaiPortal *)portal:(NSString *)identifier { + DaiPortal *newPortal = [DaiPortal new]; + newPortal.identifier = identifier; + newPortal.dependObject = self; + return newPortal; +} + +@end diff --git a/e-Hentai/e-Hentai-Prefix.pch b/e-Hentai/e-Hentai-Prefix.pch index 993394ce..73748208 100644 --- a/e-Hentai/e-Hentai-Prefix.pch +++ b/e-Hentai/e-Hentai-Prefix.pch @@ -25,6 +25,7 @@ #import "NSDictionary+Hentai.h" #import "UITableViewCell+Hentai.h" #import "DaiInboxHUD.h" + #import "NSObject+DaiPortal.h" //from pod #import