2GISã¯ããã£ã¬ã¯ããªã®äŒç€Ÿã®é»è©±çªå·ã«é¢ããç¥èãiPhoneã®ãŠãŒã¶ãŒãšå ±æããããšãã£ãšæã£ãŠããŸããã Androidãã©ãããã©ãŒã ã¯ãã®ãããªæ©äŒãæäŸããŸããããiOSã«ã¯é·ãéé©åãªããŒã«ããããŸããã§ããã
6æã«WWDC 2016ã«è¡ããŸãããã»ãã·ã§ã³ã®1ã€ã§ã Appleã®äººã ã¯ãããŽãŒãžã£ã¹ãªé©ãããã€ãŸãiOS 10ã®çºä¿¡è IDãããããã§ãããšèšããŸããã ã圌女ã¯å€ãã®å¶éã®ããæ©èœãæäŸããŸããã
è©Šäœæ©
æåã«ééãããåã³ãã¯ããè±å¯ãªãããã¥ã¡ã³ãã§ããã
âCXCallDirectoryExtensionContext
@interface CXCallDirectoryExtensionContext : NSExtensionContext @property (nonatomic, weak, nullable) id<CXCallDirectoryExtensionContextDelegate> delegate; - (void)addBlockingEntryWithNextSequentialPhoneNumber:(CXCallDirectoryPhoneNumber)phoneNumber; - (void)addIdentificationEntryWithNextSequentialPhoneNumber:(CXCallDirectoryPhoneNumber)phoneNumber label:(NSString *)label; - (void)completeRequestWithCompletionHandler:(nullable void (^)(BOOL expired))completion; @end
âCXCallDirectoryManager
@interface CXCallDirectoryManager : NSObject @property (readonly, class) CXCallDirectoryManager *sharedInstance; - (void)reloadExtensionWithIdentifier:(NSString *)identifier completionHandler:(nullable void (^)(NSError *_Nullable error))completion; - (void)getEnabledStatusForExtensionWithIdentifier:(NSString *)identifier completionHandler:(void (^)(CXCallDirectoryEnabledStatus enabledStatus, NSError *_Nullable error))completion; @end
ããã ãã§ãã ãŸããããã¯ãã£ãšæªãã£ããããããŸããã
ãã®ããšãããiOSçšãã€ã€ã©ãŒã¯å¥ã®ããã»ã¹ãã¹ãã³ããã¢ããªã±ãŒã·ã§ã³æ¡åŒµæ©èœã§ããããªãŒããŒããŒãããŠãã®ã¹ããŒã¿ã¹ãååŸã§ããããšãããããŸãã å¿ èŠãªãã®ã®ããã«èŠããŸãã
æ¡åŒµæ©èœèªäœã§ã¯ããé»è©±/ååãã®åœ¢åŒã§çªå·ãè¿œå ãããããã¯ããçªå·ãè¿œå ã§ããŸãã
æåã®ãããã¿ã€ãã¯30åã§å®æããŸããã 延é·ã«é ç·ããã1å°ã®å人çšé»è©±ã1å°ã®ãã¹ãçšé»è©±ãããã¯ã«è¿œå ããããã¹ãŠãåããŠèµ·åããŸãããåã³ã«å¶éã¯ãããŸããã§ããã æªæ¥ã¯éåžžã«æããããã«èŠããŸãã-ç§ãã¡ã¯ãããããã¹ãŠãç¿æ¥ã®æ¬¡ã®ãªãªãŒã¹ã«ã©ã®ããã«åé¡ããããããã§ã«æ³åããŠããŸããã
2çªç®ã®ãåã³ãã«åºäŒããŸã§ãã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ãããã€ã€ã©ãæå¹ã«ããããšã¯ã§ããŸããã ãŠãŒã¶ãŒãèšå®ã®å¥¥æ·±ãã«éãå¿ èŠããããŸãããããã¯æããã«ãã®æ©èœã®å€æãå¢å ãããŸããã
ãã®åŸã圌ãã¯äžé£ã®çªå·ãè¿œå ãå§ãã3çªç®ã®ãåã³ããçŸããŸããïŒãã¹ãŠã®çªå·ã¯ã決å®ãããåã«ããŒã¿ããŒã¹ã«èšé²ããå¿ èŠããããŸãïŒããã¯åãªãæåãªAppleã»ãã¥ãªãã£ã§ã-çä¿¡callerIDã«ã¢ã¯ã»ã¹ã§ããªãããã«ããããïŒã ãããŠãç§ãã¡ã®ããŒã¹ã¯ã眲åä»ãã®çŽ400äžã®æ°åã§ãã ããã¯140 MBã®ããã¹ãæ å ±ããŸãã¯ããªãèªäœãæŒããš40 MBã§ãããããããã¹ãŠãäœããã®æ¹æ³ã§æ¡åŒµæ©èœã«é ä¿¡ããå¿ èŠããããŸãã
ãã®ç¥èãæŠåšã«ããé»è©±/ååãã®åœ¢åŒã§ããŒã¿ãæºåãããã§ã«å®éã®ãããã¿ã€ããèŠã€ãå§ããŸããã
ããŒã¿ããŒã¹
æåã«ã圌ãã¯ãã¹ãŠã®æ°åãæãã«è¿œå ããããšã«ããŸããããããŠåã³é©ã-æ°åã¯ãšã«ããè¿œå ãããã¹ãã§ã¯ãããŸããããæé ã§ïŒ01ã02ã911ãªã© ãã以å€ã®å Žåãæ¡åŒµæ©èœã¯ããããããŸãã æåã®ããŒã¿8ã§ã¯ãxcodeæ¡åŒµæ©èœã¯ãšã©ãŒãªãã§ã¯ã©ãã·ã¥ããŸããã
ããã«ã1,999,999åã®æ°åã«å¶éãããŠããããšãããããŸããã ã¯ããæ£ç¢ºã«1,999,999ã§ããã2,000,000ã§ã¯ãããŸãããããã¯ã4,000,000ã®æ°å€ãšããŸã£ããåãã§ã¯ãããŸããã æåã«ã圌ãã¯3ã€ã®æ¡åŒµãäœããããšæã£ãŠããŸããããããããæ倧1,999,999åã®æ°åã§æºããããå£ã²ãã«å¹ãé£ã°ãããŸããã§ããã ãã®åŸã圌ãã¯å°åããšã«åå²ããããšã決ããŸããïŒã¢ã¹ã¯ã¯+ããŒã¿ãŒããã·ã¢ã®æ®ããå€åœäººã ãããã圌ãã¯ãã®æ±ºå®ãæåŠããŸãããããè€éãªé ä¿¡ãèãåºããæ©èœã®å®å®æ§ãããã«äœäžãããå¿ èŠããããåæã«æ©èœããããã€ãã®æ¡åŒµæ©èœã®äœæ¥ãå®å®ããŠããªãã£ãããã§ãã ã¯ãããŠãŒã¶ãŒã«3ã€ã®æ¡åŒµæ©èœããã¹ãŠåŒ·å¶çã«å«ããããããŸããã§ããã ãã®çµæããŠãŒã¶ãŒãèšå®ããéœåžã®æ°ã®ã¿ãæ®ãããšã«ããŸããã
æåã¯ãSQLiteãä»ããŠããŒã¿ãé ä¿¡ããããšèããŠããŸããã ããã·ãã«ã¹ã¯ãã100,000åã®åçŽãªããŒã¿ããŒã¹ãæ§ç¯ããããŒã¿ããŒã¹ãæäœããããã®ããžãã¯ãèšè¿°ãããã¢ãããžã§ã¯ããéå§ããŸããããäœããããŸããã§ããã ãšã©ãŒã¯ãããŸããããã¹ãŠåé¡ãããŸããããæ°å€ã¯æ±ºå®ãããŠããŸããã
ãã®ã±ãŒã¹ãæãäžããåŸãSQLiteããããŒã¿ãæé ã§ãã«ããããšãããšãããŒã¿ããŒã¹ã30 MBã®ãã£ãã·ã¥ãäœæããæ¡åŒµæ©èœãã¡ã¢ãªããã¯ã©ãã·ã¥ããããšãããããŸããã Appleã®ãã©ãŒã©ã ãæãäžããåŸã5 MBã®RAMã䜿çšããªãæ¹ãè¯ãããšã«æ°ä»ããŸããã ãã®çµæãã¢ã¹ã¯ã¯ããµã³ã¯ãããã«ãã«ã¯ãããã³ããã€ãã®éœåžã®ããŒã¿ããŒã¹ãçµã¿åãããå ŽåãããŒã¿ããŒã¹ãžã®ã¯ãšãªãå€§å¹ ã«è€éåããã¡ã¢ãªãæé©åããŠãã§ãããé«éåãããã¹ãããã»ã¹ãè€éã«ããå¿ èŠããããŸãã ããããã¹ãŠãè¡ãæéã¯ãŸã£ãããããŸããã§ããããäžæ¬æã§ããããã«ããã¢ããŒã¹ãã¯ãããžãŒã«é¢ããç§ã®èœåã¯æããã«ååã§ã¯ãããŸããã§ããã
ãã°ã®ããã«ããããã·ãŒã±ã³ã¹ã®åœ¢åŒã§ããŒã¿åœ¢åŒããã ãèŠãŸããïŒ
[uint16_tïŒãããã¯ãµã€ãº] [笊å·ãªãlong long intïŒé»è©±] [æååïŒåå]
ãã©ãã«ã®ãªãéåžžã«ã·ã³ãã«ãªããŒãµãŒïŒ
@interface DGSPhonesDataReader : NSObject /** , next, 0 */ @property (nonatomic, assign, readonly) unsigned long long int phone; /** , next, nil */ @property (nonatomic, copy, readonly, nullable) NSString *name; - (instancetype)initWithFilePath:(NSString *)path; - (BOOL)next; @end
#import "DGSPhonesDataReader.h" @interface DGSPhonesDataReader () @property (nonatomic, strong, readonly) NSData *data; @property (nonatomic, assign) NSUInteger location; @property (nonatomic, assign, readwrite) unsigned long long int phone; @property (nonatomic, copy, readwrite, nullable) NSString *name; @end @implementation DGSPhonesDataReader - (instancetype)initWithFilePath:(NSString *)path { self = [super init]; if (self == nil) return nil; NSError *error = nil; _data = [NSData dataWithContentsOfFile:path options:NSDataReadingMappedIfSafe error:&error]; _location = 0; if (_data == nil) { NSLog(@"DGSPhonesDataReader data create error: %@", error); } return self; } - (BOOL)next { uint16_t blockLength; [self.data getBytes:&blockLength range:NSMakeRange(self.location, sizeof(blockLength))]; self.location += sizeof(blockLength); unsigned long long int phone; NSUInteger textLength = blockLength - sizeof(phone); [self.data getBytes:&phone range:NSMakeRange(self.location, sizeof(phone))]; self.phone = phone; self.location += sizeof(phone); uint8_t buffer[textLength]; [self.data getBytes:buffer range:NSMakeRange(self.location, textLength)]; self.name = [[NSString alloc] initWithBytes:buffer length:textLength encoding:NSUTF8StringEncoding]; self.location += textLength; return self.location < self.data.length; } @end
ã¯ããçè«çã«ã¯ããã£ãã·ã¥ã䜿çšãã8 KBã®ãããã¯ãèªã¿èŸŒãå¿ èŠããããŸãã ãããããã®ãããªã¢ã«ãŽãªãºã ã¯ãå¥ã®ã·ã¹ãã ããã»ã¹ã§10ç§éã«2,000,000ã®æ°å€ã®ããŒã¿ããŒã¹ãå®è¡ããã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ã«äœããã®åœ±é¿ãäžããããšãªããããã«ããã¯æŽæ°ããšã«1åçºçãããããæé©åãæ°ã«ããªãããšã«ããŸããã
ãã£ãïŒ ããã§ãããŒã¿ããŒã¹ã®é»è©±çªå·ãå®å šã«è§£æã§ããéãã«5 MBã®ã¡ã¢ãªå¶éå ã«åãŸããŸãã ããããæéãçµã¡ãæ©èœã¯ãŸã æºåãã§ããŠããŸããã
ããŒã¿é ä¿¡
次ã«ããã®ããŒã¿ãæ¡åŒµæ©èœã«ãã€ãŸãå®éã«ã¯å¥ã®ã¢ããªã±ãŒã·ã§ã³ã§é ä¿¡ããæ¹æ³ãç解ããå¿ èŠããããŸããã ãŠãŒã¶ãŒãæ°ããå°åãããŠã³ããŒãããå€ãå°åãåé€ãããã¹ãŠãæŽæ°ãããã®ã§ãããã«çž«ãä»ããããšã¯æ©èœããŸãããããŒã¿ã¯å€ããæ°ããå°åãè¿œå ãããŸãããç§ãã¡ã¯æ£ç¢ºããšé¢é£æ§ã«ã€ããŠã®äŒç€Ÿã§ãã
ãã§ã«ãã¹ãŠãçºæãããŠããŠãåãéçºè ã®2ã€ã®ã¢ããªã±ãŒã·ã§ã³éã§ããŒã¿ãææ¢ãã§ããApp GroupsãšããçŽ æŽããããã®ããããŸããã
ãã¹ã«æ²¿ã£ãŠã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ã«ãã¡ã€ã«ãé 眮ã§ããŸãã
+ (NSString *)extensionDataPath { return [[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:[self extensionGroupName]].path stringByAppendingPathComponent:@"Dialer"]; }
ãããŠãæ¡åŒµã§ãããæã«å ¥ããŸãïŒ
NSString *databasePath = [[DGSCallKitExtensionModel extensionDataPath] stringByAppendingPathComponent:manifest.databaseName];
é éã«åé¡ã¯ãããŸããã§ããããããããšãããããŸãã
次ã«ãç®çã®åœ¢åŒã§ããŒã¿ãæºåããŸããã æ·±ãããããªãå Žåã¯ã500 MBã®.tsvãã¡ã€ã«ã108ã®å°åã«åæ£ããããã€ããªåœ¢åŒã§ãããè¿œãè¶ããJenkinsã§ãžã§ããäœæããŠäœæããå¿ èŠããããŸãã èŠããã«ãããã«ãããªãã®æéãè²»ãããŸãã-éçºå šäœã®çŽ90ïŒ ã
ãã®ããŒã¿ãé»è©±ã«é ä¿¡ããã¿ã¹ã¯ãçºçããŸããïŒéçºã®2çªç®ã®90ïŒ ïŒã
æåã¯ããªã³ããã³ããªãœãŒã¹ããã¯ãããžãŒã䜿çšãããšåæã«ãxcodeã®3çªç®ã®æ°žé ã«ç©ºã®ã¿ãïŒãªãœãŒã¹ã¿ã°ïŒãå¿ èŠãªçç±ãèŠã€ããããšã«ããŸããã
ãããã®äººã¯ããªãã«ãã£ãšããèšãã§ãããïŒ
èŠããã«ãç§ãã¡ã«ãšã£ãŠã®ãªãœãŒã¹ã¿ã°ã¯ã倩åœããã®åãªãããã§ãïŒã€ãŸãããªã³ããã³ãã§ã®ã¿ããŠã³ããŒãïŒã ããã«ãããäžéšã®ã¢ããªã±ãŒã·ã§ã³ãªãœãŒã¹ã«ã¿ã°ãã¿ã°ä»ããããã®ã¿ã€ãã瀺ããã¢ããªã±ãŒã·ã§ã³ã«å ¥åãããšãã«ããããbinarã«å«ããªããªããŸãã 次ã«ãNSBundleResourceRequestã䜿çšããŠããŠã³ããŒããã[NSBundle mainBundle]ããååŸã§ããŸãã ã€ãŸããä»ã®ããŒã ãããã¯ããå¿ èŠã¯ãŸã£ãããããŸãããä»ã®ããŒã ãä¿ç®¡ããæ¹æ³ãããŠãŒã¶ãŒã«æäŸããæ¹æ³ãèããå¿ èŠã¯ãããŸããã ãããŠãAppleèªèº«ããã¹ãŠã®ããŒã¿ãä¿åãããããååŸããããã®éåžžã«é©åãªAPIãæäŸããŸãã ããã§ãè¿ éãªçµ±åãçŽæãããã®ã
ãããããã¹ãŠãããã»ã©ãã©è²ã«ãªã£ãããã§ã¯ãããŸãããæåã®ãªãªãŒã¹ã§ã¯ããã®ãã¯ãããžãŒã¯éåžžã«ã²ã©ããã®ã§ããããŠãŒã¶ãŒã®çŽ20ïŒ ãäœãããŠã³ããŒãã§ããŸããã§ããã Appleã®ãã©ãŒã©ã ãæãäžããŠã¿ããšããã®ãããªåé¡ã ãã§ã¯ãªãããšãããããŸããããé·ãéä¿®æ£ãããããŸã£ããåå¿ããŸããã§ããã
ãªãœãŒã¹ã¿ã°ã¯å¥ã®æ¹æ³ã§ã«ããããŠé ä¿¡ããå¿ èŠããããŸããã ãã®çµæãããŒã¿ã¯éœåžæŽæ°ããŒã¿ããŒã¹ã«å ¥åãããŸããã ããã§ãéœåžã®æŽæ°ãšãšãã«ããŠãŒã¶ãŒã¯æ°ããããŒã¹çªå·ãåãåããŸãã
ãã¹ãŠå ã«
å°ãªããšããã€ã€ã©ãŒã¯AppStoreã«å ¥ããããã§ã¯4çªç®ã®ãåã³ããåŸ ã£ãŠããŸããã
ã€ã³ã¹ããŒã«ãæ£åžžã«å®äºããåŸãããŒã¿ããŒã¹ãåé€ããŸãããããã¯ãæºåž¯é»è©±ã®ã¡ã¢ãªã«æ¢ã«ãããã®ãä¿åããçç±ã§ãã ãã¹ãŠãããã»ã©åçŽã§ã¯ãªãããšãå€æããŸããããŠãŒã¶ãŒãèšå®ã«å ¥ããæ¡åŒµæ©èœããªãã«ããŠãããªã³ã«ãããšãåã«ãªã³ã«ããã®ã§ã¯ãªããæ¡åŒµæ©èœã¯å®å šãªæŽæ°ã·ããªãªã«åŸã£ãŠåäœããŸãã æ®å¿µãªããšã«ãç§ãã¡ã¯ãããèæ ®ã«å ¥ããŠãããããããè¡ã£ããã¹ãŠã®äººã¯ãããããæŽæ°ããå¯èœæ§ãªãã«åºç€ã倱ããŸããã 次ã®ããŒãžã§ã³ã§ã¯ããã®åé¡ããã°ããä¿®æ£ããé¢é£æ§ã®ããããŒã¿ãé»è©±ã«æ®ããŸãã
èå¥åãæ©èœããªããšããèŠæ ããŸãã¯èå¥åãæå¹ã«ããæ¹æ³ã«ã€ããŠã®è³ªåãåžžã«åãââåããŸãã ãããŸã§ã®ãšãããäžéãªãã·ã§ã³ãšããŠã2GISèšå®ã§è¡ååŒã«é¢ããåå¥ã®é ç®ãäœæããŸããã
iOS 10.3ã§ã¯ãAppleã¯ããã«å€ãã®åé¡ãæããããŸããããã®ããŒãžã§ã³ã«ã¢ããã°ã¬ãŒããããšããŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ãåã€ã³ã¹ããŒã«ãããæŽæ°ãããŒã«ãããŸã§ãèšå®ã§èå¥åãæ¶ããŸãã æ¡åŒµæ©èœã¯å šäœãšããŠäžå®å®ã«åäœããŸãã å®æçã«ïŒäžæãªçç±ãæ³åŸã®ããïŒãæŽæ°æã«èšå®ãããªãã«ãªãããå®å šã«æ¶ããŸãã å Žåã«ãã£ãŠã¯ãçªå·ãæŽæ°ããéçšã§ãã·ã¹ãã ã¯ãšã©ãŒã³ãŒãã䜿çšããŠæ¡åŒµæ©èœããµã€ã¬ã³ãã«éä»ãã«ããŸãã
âCXErrorCodeCallDirectoryManagerErrorLoadingInterrupted;
âCXErrorCodeCallDirectoryManagerErrorUnknownã
10æã«ãAppleã§ããŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³èªäœãããã€ã€ã©ãŒãæå¹ã«ã§ããããã«ããããã®ãã³ãš10.3ã®ãã°ã«ã€ããŠå°ããã¬ãŒããŒãäœæããŸããã Appleã¯10æ以éã®æåã®ãã±ãããç¡èŠãã2çªç®ã®ãã±ããã¯éåžžã«é·ãåã«ãªããŸãã
ãã®ãããè¿ãå°æ¥ããŠãŒã¶ãŒã«ãšã£ãŠè£œåãæ¹åã§ããå¯èœæ§ã¯äœããªããŸãã
æçµçã«ã©ã®ããã«æ©èœãããïŒ
- ãŠãŒã¶ãŒã¯éœåžãã¹ã€ã³ã°ããŸãã
- éœåžãããç§ãã¡ã®åœ¢åŒã§æ°å€ã®ããŒã¿ããŒã¹ãååŸããŸãã
- ãŠãŒã¶ãŒã«ã€ã³ã¹ããŒã«ãããŠãããã¹ãŠã®ããŒã¿ããŒã¹ã調ã¹ãŸãïŒæ¡åŒµæ©èœãšã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³éã®å ±éã®UserDefaultsã«ä¿åããŸãïŒã
- åããŒã¿ããŒã¹ã«ã¯ããã·ã¥ããããŸãã å°ãªããšã1ã€ã®ããã·ã¥ãäžèŽããªãå ŽåããŸãã¯æ°ããããã·ã¥ã衚瀺ãããå Žåããã¹ãŠã®æ°ããããŒã¿ããŒã¹ãå ±æã¹ãã¬ãŒãžã«æžã蟌ã¿ãã€ã³ã¹ããŒã«ã®æºåãã§ããŠãããšããŒã¯ããŸãã ããã¯ããŠãŒã¶ãŒãæ¡åŒµæ©èœãã¢ã¯ãã£ãã«ããªãããã¢ããªã±ãŒã·ã§ã³ãæå°åããåŸã§æå¹ã«ããå Žåã«å¿ èŠã§ãã
- æ¡åŒµæ©èœãã¢ã¯ãã£ããªå Žåã次ã®æ¹æ³ã§åèµ·åããŸãã
[[CXCallDirectoryManager sharedInstance] reloadExtensionWithIdentifier:bundleID completionHandler:^(NSError * _Nullable error) {}];
- æ¡åŒµæ©èœèªäœã§ã圌ãåãåã£ããšãïŒ
- (void)beginRequestWithExtensionContext:(CXCallDirectoryExtensionContext *)context
ã€ã³ã¹ããŒã«ã®æºåãã§ããŠããããŒã¹ããããã©ããã確èªããŸãã ããå Žåã¯ããã¹ãŠã調ã¹ãŠã次ã®çªå·ãè¿œå ããŸãã
[context addIdentificationEntryWithNextSequentialPhoneNumber:phone label:name];
- ããŒã¹ãã€ã³ã¹ããŒã«æžã¿ãšããŠããŒã¯ããŸãã
- æŽæ°ããšã«ããã»ã¹ãç¹°ãè¿ããŸãã
ã³ãŒãã§ã¯ã次ã®ããã«ãªããŸãã
- (RACSignal *)reloadExtensionsIfNeeded { @weakify(self); if (![DGSCallKitFetchModel isExtensionAvailable] || self.manifests.count == 0) return [RACSignal empty]; return [[[[[[[[[self fetchCanBeInstalledExtensionsRegionCodes] filter:^BOOL(NSSet *regionCodes) { return regionCodes.count > 0; }] deliverOn:[RACScheduler scheduler]] flattenMap:^RACStream *(NSSet *regionCodes) { @strongify(self); return [RACSignal combineLatest:@[ [self downloadDatabasesWithRegionCodesIfNeeded:regionCodes], [DGSCallKitFetchModel fetchExtensionEnabled] ]]; }] flattenMap:^RACStream *(RACTuple *t) { @strongify(self); RACTupleUnpack(NSSet *regionCodes, NSNumber *extensionEnabled) = t; // , if (!extensionEnabled.boolValue) return [RACSignal empty]; // , , // , // if ([self shouldInstallDatabasesWithRegionCodes:regionCodes]) { return [RACSignal return:regionCodes]; } else if ([self dialerEnabledWithRegionCodes:regionCodes]) { [self trackDialerInstalledEventWithRegionCodes:regionCodes]; } return [RACSignal empty]; }] flattenMap:^RACStream *(NSSet *regionCodes) { @strongify(self); return [self updateExtensionWithRegionCodes:regionCodes]; }] doNext:^(NSSet *regionCodes) { @strongify(self); ULogInfo(@"Dialer extension installed with region codes: %@", regionCodes); [self trackDialerInstalledEventWithRegionCodes:regionCodes]; }] doError:^(NSError *error) { @strongify(self); ULogError(@"Dialer extension error: %@", error); [self.analyticsSender trackEventWithCategory:kDGSCategoryDialer action:kDGSActionDialerFailed label:error.localizedDescription value:nil]; }] doCompleted:^{ ULogInfo(@"Dialer extension reload completed signal"); }]; } + (RACSignal *)fetchExtensionEnabled { NSString *bundleID = [DGSCallKitExtensionModel extensionBundleID]; return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [[CXCallDirectoryManager sharedInstance] getEnabledStatusForExtensionWithIdentifier:bundleID completionHandler:^(CXCallDirectoryEnabledStatus enabledStatus, NSError * _Nullable error) { if (enabledStatus == CXCallDirectoryEnabledStatusEnabled) { [subscriber sendNext:@YES]; } else { [subscriber sendNext:@NO]; } [subscriber sendCompleted]; }]; return nil; }]; } - (RACSignal *)updateExtensionWithRegionCodes:(NSSet<NSString *> *)regionCodes { ULogInfo(@"Reload dialer extension with tag: %@", regionCodes); NSString *bundleID = [DGSCallKitExtensionModel extensionBundleID]; return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [[CXCallDirectoryManager sharedInstance] reloadExtensionWithIdentifier:bundleID completionHandler:^(NSError * _Nullable error) { if (error) { [subscriber sendError:error]; } else { [subscriber sendNext:regionCodes]; [subscriber sendCompleted]; } }]; return nil; }]; }
ãã®æ©èœã®å®è£ ã«é¢ããäž»ãªåé¡ã¯ãããŒã¿ã®æºåãšã¢ããªã±ãŒã·ã§ã³ãžã®é ä¿¡ã§ããã çŽ100,000å°ã®é»è©±ã®å ç·ã§çž«ãå Žåããã®æ©èœã¯1æéã§å®äºããŸãïŒé»è©±ãããã°ïŒã
æ¢è£œã®åœ¢åŒã®ããŒã¿ããªããcãªæ¹æ³ã§ããŒã¿ãé ä¿¡ããã³æŽæ°ããå¿ èŠãããå Žåããã®æ©èœã®çµ±åã«ã¯å€ãã®æéããããããã®çµã¿èŸŒã¿ã®è€éãã®ããã«ããŠãŒã¶ãŒã¯æ®å¿µãªãããããããšãããšã¯èšããŸããã ã»ãšãã©ã®ã¬ãã¥ãŒã§ã¯ããããã¯ç§ã«ã¯æ©èœããŸãããããã¢ããªã±ãŒã·ã§ã³ãããŠã³ããŒãããŸããããäœãå€æããŸããããªã©ã®ãããªãã®ããããŸãã
çµè«ã®ä»£ããã«
çŸæç¹ã§ã¯ããã®æ©èœã¯å®æããŠããŸããè¿ãå°æ¥ãæ©èœãå®æãããèšç»ã¯ãããŸããã ããã§ããæãå®çŸ©ãããæ°åïŒçŽ100,000ã®æ°åïŒã«åŸã£ãŠéžæãè¡ããæ¡åŒµæ©èœã§ããã«çž«ãä»ããŠããŠãŒã¶ãŒãå°åãããŠã³ããŒãããã«æå°éã®æ©èœãããã«å©çšã§ããããã«ããŸãã ãŸããAndroidã®ãã€ã€ã©ãŒãŠãŒã¶ãŒããèŠæ ãå¯ããããŠããåéæ©é¢ãããŸããŸãªäžè«èª¿æ»ãããŸããŸãªéèãã©ãããããã®ä»ã®æãŸãããªãæ°åãªã©ããææ¯ããªæ°åã«é¢ããããŒã¿ãããªããããŸãã ç§ãã¡ããããããåå¥ã®ããã±ãŒãžã§ãã¹ãŠã®äººã«å±ããããšãã§ããŸãã
äžè¬çã«ãæ¯èªèº«ã§ããæå¹ã«ã§ããããã«ãããå®å®ãã䜿ãããããã®ãå¿ èŠã§ããã ãããã«ãããå°ãªããšã20,000人ã®ãŠãŒã¶ãŒããã®æ¡åŒµæ©èœãæå¹ã«ããŸããããããã¯æ¬åœã®å©ç¹ã§ããããã¹ãŠãç¡é§ã§ã¯ãªãã£ããšæããŠããŸãã