
ä»æ¥ãç§ãã¡ã¯éåžžæè¡äŒè°ãæè¡äŒè°ã§è©±ãããŠããªãããšã«é¢ããäžé£ã®èšäºãéããŠããŸãã ãã以éã®æçš¿ã§ã¯ãéçºäžã®ç±³åœã§äººæ°ã®ããiFunny iOSãšã³ã¿ãŒãã€ã¡ã³ãã¢ããªã±ãŒã·ã§ã³ã§åçåã¡ã«ããºã ãã©ã®ããã«æ©èœãããã説æããŸãã
åºåã¯ãç¡æã®ã¢ããªã±ãŒã·ã§ã³ãåçåããäž»ãªæ¹æ³ã®1ã€ã§ãã ããããä»ãiFunnyãç»å Žãã2011幎ã«ã¯ã©ã®ãããªãªãã·ã§ã³ããããŸãããïŒ ãã®ãµãŒãã¹ã¯ããšããšåŒ·åã§æç¶å¯èœãªããžãã¹ãšããŠæ§ç¯ããããããæåã®æ¥ããããŠãŒã¶ãŒãšãã¡ãã€ãããšãªããæ¡ä»¶ä»ã倧æåã§ã²ãŒã ã«åå ããªãããšã«æ±ºããŸããã
åœæãåçåã®äž»ãªãªãã·ã§ã³ã¯ããµãŒãã¹ã®ç¡æã®æ©èœãåæžããããŒãžã§ã³ãäœæããŠãããäž»ãªæ©èœã販売ããããšã§ããã æ¶è²»è ã¯è¥ããçµéšãæµ ãã1ãã«ãè¶ ããéé¡ãææŸãæºåãã§ããŠããŸããã§ããã
åçŽãªæ°åŠã§ã¯ã10ïŒ ã®å€æã§10ã»ã³ã以äžã®ARPUãååŸããããšã¯ã»ãšãã©äžå¯èœãªã¿ã¹ã¯ã§ããããšã瀺ãããŸããã
ããããç§ã¯ä»ã«ã©ã®ããã«ããªãã補åãåçåã§ãããã«ã€ããŠèããªããã°ãªããŸããã§ããã åºåã¢ãã«ã¯ãã§ã«ãŠã§ãäžã§éåžžã«ããŸãæ©èœããŠãããé»è©±ã§ããŸããªãå²ããšæãããŸãã
äžè¬ã«ãåçåã®ã¢ãã€ã«åºåã¢ãã«ã®å§ãŸãã¯ãåºåãããã¯ãŒã¯ã®SDKãçµ±åããŠããŒããŒã·ã§ã³ã§ãããµãŒãã¹ã§ããAdWhirlã®ç»å Žãšèããããšãã§ããŸãã ãã®å€èŠ³ã«ãããFillRateãåžå Žã§å¹³å50ïŒ ã«åŒãäžããåºåã¢ãã«ããã®åçãå°ãªããšã1ãã«ã®å£²äžã«å¹æµãããããšãã§ããŸããã ãã¹ãŠã®å¯èœãªéèŠã®æºæ³ãšãããã®éã®ç«¶äºã®çµç¹ã®å®æœã®ãŸãã«åçã¯ãåºåç£æ¥ã®æé·ã®äž»ãªæšé²è ã«ãªããä»æ¥ãŸã§äœ¿çšããç¶ããŠããŸãã
ããããã·ã¹ãã ãè€éã«ãªãã»ã©ãã·ã¹ãã ã®å®å®æ§ã¯äœäžããŸããããã¯ãiFunnyã¬ãã«ã®å€§èŠæš¡ãªãµãŒãã¹ã§ã¯ãŸã£ããåãå ¥ããããŸããã 2011幎ã«ãã®æ¹åã«åãå§ããå瀟ã¯ãã¢ãã€ã«ãããŒãšãã€ãã£ãåºåãæ±ãããã®æãå¹æçãªã¡ã«ããºã ã®1ã€ãäœæãããŠãŒã¶ãŒãããã®åçã40åã«å¢ãããŸãããããã«ãããå éšãããžã§ã¯ãã ãã§ãªããä»ã®äŒæ¥ãžã®æè³ãå¯èœã«ãªããŸããã
MoPubãšäŒç€Ÿ
2012幎以éãAdWhirlããMoPubã«ç§»è¡ããŸããã
MoPubã¯ãç¬èªã®ã¢ãžã¥ãŒã«ãè¿œå ã§ããã¢ãã€ã«åºåãã©ãããã©ãŒã ã§ãããããã€ãã®åªããããŒã«ãå«ãŸããŠããŸãã
- MoPubããŒã±ãããã¬ã€ã¹-ç¬èªã®åºåååŒæ;
- å€éšãããã¯ãŒã¯ãšé£æºããããã®åºåãããã¯ãŒã¯ã®ä»²ä»è ã
- ç¬èªã®ã¢ããªã±ãŒã·ã§ã³ã«ãããŒãåå¥ã«é 眮ãã衚瀺ãã«ã¹ã¿ãã€ãºã§ããé åºä»ãã¡ã«ããºã ã
MoPubã®äž»ãªå©ç¹ïŒ
- ã»ãšãã©ã®åºåãããã¯ãŒã¯ãšé£æºã§ããã
- æ°ãããµãŒãããŒãã£ãããã¯ãŒã¯ãæ¥ç¶ããããã®æ確ãªã¡ã«ããºã ã
- ãªãŒãã³ãœãŒã¹
- èšå€§ãªæ°ã®åºæ¬èšå®ãšã¿ãŒã²ãã£ã³ã°ã
- ãããã¯ãŒã¯åšèŸºã®å€§èŠæš¡ãªã³ãã¥ããã£ãç¬èªã®äŒè°ããããŸãã
MoPubã«ã¯æ¬ ç¹ããããŸãã
- GitHubã§ã®ããŒã«ãªã¯ãšã¹ãã¯åãå ¥ãããããéåžžããããã«å¯Ÿããåå¿ã¯ãããŸããã
- ã³ã³ãããŒã«ããã«ã¯éåžžã«è€éã§ãããéçºè ã«ãšã£ãŠã¯ããããã°äžã«ãã®æ§é ãæãäžããã®ã«æéãããããŸãã
çå®ã®å
ãããã·ã¢æ ç»ã®äž»äººå ¬ãèšã£ãããã«ãã匷ãã¯çå®ã§ããã ãã®ããŒãã§ã¯ãã¢ããªã±ãŒã·ã§ã³éçºè ãšããŠãiFunnyã®æåã®100äžããŠã³ããŒãã100人以äžã®ããŒãããŒããã®èŠèŽè ãšåºåãã©ãã£ãã¯ã®å¢å ã®åŸã«çŽé¢ããªããã°ãªããªãã£ãå°é£ã«ã€ããŠã話ããŸãã
å 容
åºååžå Žã¯ãã¯ãããžãŒäŒæ¥ã®éåžžã«éãããã«ãŒã¹ããã§ãããåæã«ãã¢ã°ãªã²ãŒã¿ãŒã¯æ°çŸäžã®äºç®ã§åã倧äŒæ¥ããç¹å®ã®ã¿ãŒã²ãããªãŒãã£ãšã³ã¹ã«åãããäžå°äŒæ¥ãŸã§ãããŒãããŒã®å€§ããªãããã¯ãŒã¯ãæã£ãŠããŸãã
ãããŒã®äºå調æŽãšåºåã³ã³ãã³ãã«é¢ããããªãå³æ Œãªã«ãŒã«ã«ãããããããããŒãããŒã®ãã®ç·å¯ããšæçåã«ãããæãæ£çŽãªåºå販売è ã¯ãã¢ããªã±ãŒã·ã§ã³ã§ã®ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãçŠæ¢ãŸãã¯å°ç¡ãã«ããã¯ãªãšã€ãã£ããå ¬éã§ããŸããã
åºåãããŒã«ã¯ãããããã€ãªãã³ã³ãã³ãã«ã¯ããã€ãã®äž»èŠãªã«ããŽãªããããŸãã
- ãã«ãã³ã³ãã³ãã æè¿ãããã¯ãŸããŸãå°ãªããªã£ãŠããããã«èŠããŸãããããã§ããããªã£ãŠããŸãã ãã®ã³ã³ãã³ããèšäºã«å ¬éããããšã¯ã§ããŸããã®ã§ãåçã¯ããã«ã¯ãããŸãã
- ãããŒå ã®ã·ã¹ãã ã¢ã©ãŒããäŸã¯ãŠãŒã¶ãŒtwitter.com/IfunnyStates/status/1029393804749668352ã§èŠãããšãã§ããŸã
- é³å£°ä»ãã®ã³ã³ãã³ãã ãµãŠã³ãã¯åºåãããã¯ãŒã¯ãã¢ãã¡ãŒã·ã§ã³ã§çŠæ¢ãããŠããŸããããã€ã³ã¿ãŒãã§ã€ã¹ãšå¯Ÿè©±ããã«ãµãŠã³ããåçãããå Žåãããã¯ã¢ããªã±ãŒã·ã§ã³ã®ãã°ãšããŠãŠãŒã¶ãŒã«èªèããããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã«æªåœ±é¿ãåãŒã
- 泚ç®ãéããã è¯ããããŒã¯ãŠãŒã¶ãŒã®æ³šæãåŒãä»ããã¯ãã§ãããããã¯å¿
ãããæ£çŽãªæ¹æ³ã§è¡ããããšã¯éããŸãããã¡ãã€ãã®ãããããªããããŒã«èœã¡ãããšããããŸãã ãŠãŒã¶ãŒã«ãããŒãã¿ããããããã1ã€ã®äžæ£ãªæ¹æ³ã¯ã次ã®ããã«ã¢ããªã±ãŒã·ã§ã³ã€ã³ã¿ãŒãã§ã€ã¹ãã·ãã¥ã¬ãŒãããããšã§ãã
ã¡ãªã¿ã«ããã·ã¢ã§ã¯ããã®ãããŒãæ®éã«ã¿ãããããšãäžéšã®ã¢ãã€ã«ãªãã¬ãŒã¿ãŒã«ææã®ãµãã¹ã¯ãªãã·ã§ã³ãçºè¡ã§ããŸãã詳现ã確èªãããŸã§ãããªãã¯ããã«ã€ããŠãç¥ããŸããã ããã¯åºåãæ±ãããã®äžæ£ãªæ¹æ³ã§ããããŸãããç±³åœã®äºæ¥è ã«ã¯ãã®ãããªæ©äŒã¯ãããŸããã
èªåã¯ãªãã¯
ç§ã®çµéšã瀺ãããã«ãããã¯ãŠãŒã¶ãŒã«ãšã£ãŠéåžžã«åŠå®çãªã±ãŒã¹ã§ãã JavaScriptãWKWebViewããŸãã¯UIWebViewã®æ©èœãããã³åºåã©ã€ãã©ãªã®å®è£ å ã®ç©Žã䜿çšããŠããããŒã³ã³ãã³ããéãããŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ããèªå°ããåºåãäœæã§ããŸãã
MoPubã®äŸã䜿çšããŠãã®åé¡ãç¹°ãè¿ãã«ã¯ã次ã®ã³ã³ãã³ãã®JavaScriptã³ãŒãããããŒã«è¿œå ããã ãã§ãã
<a href="https://ifunny.co" id="testbutton">test</a> <script>document.getElementById('testbutton').click(); </script>
ããã¯ãMoPubã®å€ãã®ããŒãžã§ã³ïŒããŒãžã§ã³4.13ãŸã§ïŒã§é·ãæ©èœããŸããã
MoPubã®å®è£ ã調æ»ããããšã§ãåºåãå šç»é¢ã§éãã ãã§ãªãããŠãŒã¶ãŒãç¹å®ã®ã¢ããªã±ãŒã·ã§ã³ã®AppStoreã«éãããããŒè¡šç€ºãèæ ®ããªããããè€éãªãªã³ã¯ãçæããããšãã§ããŸããã
ãšããã§ãiOSåãMoPub SDKã®ããŒãžã§ã³4.13.0ã®ãªãªãŒã¹ããŒãã«ã¯ããã®ä¿®æ£ã«é¢ããæ å ±ãå«ãŸããŠããŸãããããã¯ãSDKã®ããªãæ·±å»ãªããŒã«ã§ãããMoPubã®äžæ£ãªããŒãããŒãéåžžã«ç©æ¥µçã«æªçšããããã§ãã åŸã§èª¬æãããã°ã瀺ãããã«ããŠãŒã¶ãŒãšã®å¯Ÿè©±ãªãã«ãããŒãéãæ倧200äžåã®è©Šè¡ãæ¯æ¥ãããã¯ããå¿ èŠããããŸããã
MoPubã®å Žåãåé¡ãç°¡åã«èŠã€ããŠç¹°ãè¿ãããšãã§ããŸããããiFunnyãåäœããä»ã®ãããã¯ãŒã¯ã«ã¯éããã³ãŒããããããããŒããããã¯ãããããã°ãããããã¯ãŒã¯ãåæãããããããšã§ãåºçŸããèªåã¯ãªãã¯ã«å¯ŸåŠããå¿ èŠããããŸãã
iFunnyã¯ãã¹ãŠã®åºåããŒãããŒãšç·å¯ã«é£æºãããã®ãããªãããŒãéç¥ããŸãã iFunnyã®è¥ãèŠèŽè ã¯åºåäž»ã«ãšã£ãŠèå³æ·±ãã®ã§ãããŒãããŒã¯åãã§åœŒãã«äŒããããŒããŒã·ã§ã³ãããã®ãããªåºåãåé€ããŸãã
ã¯ã©ãã·ã¥
ã¯ã©ãã·ã¥ã¯åžžã«æªãã§ãã ããã«æªãããšã«ãã¯ããŒãºããœãŒã¹ãšã®äŸåé¢ä¿ãåå ã§çºçããå Žåãéæ¥çã«ã®ã¿åœ±é¿ãäžããããšãã§ããŸãã iFunnuã§åºåãæ±ã£ãŠããé·å¹Žã«ããã£ãŠãããã€ãã®ã¿ã€ãã®ã¯ã©ãã·ã¥ãèªèº«ã§ç¢ºèªãããŠãããããã€ãã®ã°ã«ãŒãã«åé¡ã§ããŸãã
- ã·ã¹ãã
ãããã«ã¯ããããã¯ãŒã¯ã©ã€ãã©ãªãWKWebViewïŒUIWebViewïŒãOpenGLã®äŸå€ãå«ãŸããŸãã
ãã®ã¿ã€ãã®ã¯ã©ãã·ã¥ã«çŽæ¥åœ±é¿ãäžããããšã¯éåžžã«å°é£ã§ããã以åã«WebGLã䜿çšããŠWebViewã³ã³ããŒãã³ãã®åäœãç 究ããŠããããããããã®äžéšã«åœ±é¿ãäžããããšã¯äŸç¶ãšããŠå¯èœã§ããã
ããã¯ããã®ãããªã¯ã©ãã·ã¥ã®ã¹ã¿ãã¯ã¬ãŒã¹ãã©ã®ããã«èŠãããã§ãïŒ
1 libGPUSupportMercury.dylib gpus_ReturnNotPermittedKillClient + 12
2 AGXGLDriver gldUpdateDispatch + 7132
3 libGPUSupportMercury.dylib gpusSubmitDataBuffers + 172
4 AGXGLDriver gldUpdateDispatch + 12700
5 WebCore WebCore::GraphicsContext3D::reshape(int, int) + 524
6 WebCore WebCore::WebGLRenderingContextBase::initializeNewContext() + 712
7 WebCore WebCore::WebGLRenderingContextBase::WebGLRenderingContextBase(WebCore::HTMLCanvasElement*, WTF::RefPtr<WebCore::GraphicsContext3D>&&, WebCore::GraphicsContext3D::Attributes) + 512
8 WebCore WebCore::WebGLRenderingContext::WebGLRenderingContext(WebCore::HTMLCanvasElement*, WTF::PassRefPtr<WebCore::GraphicsContext3D>, WebCore::GraphicsContext3D::Attributes) + 36
9 WebCore WebCore::WebGLRenderingContextBase::create(WebCore::HTMLCanvasElement*, WebCore::WebGLContextAttributes*, WTF::String const&) + 1272
10 WebCore WebCore::HTMLCanvasElement::getContext(WTF::String const&, WebCore::CanvasContextAttributes*) + 520
11 WebCore WebCore::JSHTMLCanvasElement::getContext(JSC::ExecState&) + 212
12 JavaScriptCore llint_entry + 27340
13 JavaScriptCore llint_entry + 24756
14 JavaScriptCore llint_entry + 24756
15 JavaScriptCore llint_entry + 24756
16 JavaScriptCore llint_entry + 25676
17 JavaScriptCore llint_entry + 24756
18 JavaScriptCore llint_entry + 24656
19 JavaScriptCore vmEntryToJavaScript + 260
20 JavaScriptCore JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) + 164
21 JavaScriptCore JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 348
22 JavaScriptCore JSC::profiledCall(JSC::ExecState*, JSC::ProfilingReason, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&, WTF::NakedPtr<JSC::Exception>&) + 160
23 WebCore WebCore::JSEventListener::handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event*) + 980
24 WebCore WebCore::EventTarget::fireEventListeners(WebCore::Event&, WebCore::EventTargetData*, WTF::Vector<WebCore::RegisteredEventListener, 1ul, WTF::CrashOnOverflow, 16ul>&) + 616
25 WebCore WebCore::EventTarget::fireEventListeners(WebCore::Event&) + 324
26 WebCore WebCore::EventContext::handleLocalEvents(WebCore::Event&) const + 108
27 WebCore WebCore::EventDispatcher::dispatchEvent(WebCore::Node*, WebCore::Event&) + 876
28 WebCore non-virtual thunk to WebCore::HTMLScriptElement::dispatchLoadEvent() + 80
29 WebCore WebCore::ScriptElement::execute(WebCore::CachedScript*) + 360
30 WebCore WebCore::ScriptRunner::timerFired() + 456
31 WebCore WebCore::ThreadTimers::sharedTimerFiredInternal() + 144
32 WebCore WebCore::timerFired(__CFRunLoopTimer*, void*) + 24
33 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 24
34 CoreFoundation __CFRunLoopDoTimer + 868
35 CoreFoundation __CFRunLoopDoTimers + 240
36 CoreFoundation __CFRunLoopRun + 1568
37 CoreFoundation CFRunLoopRunSpecific + 440
38 WebCore RunWebThread(void*) + 452
39 libsystem_pthread.dylib _pthread_body + 236
40 libsystem_pthread.dylib _pthread_start + 280
41 libsystem_pthread.dylib thread_start + 0
ããã«ããããã¯ããã¯ã°ã©ãŠã³ãã§å»ããšãã«æä»çã«çºçããŸãã ããã¯ãã¢ããªã±ãŒã·ã§ã³ãããã¯ã°ã©ãŠã³ãã«ãããšãã«OpenGLãšã³ãžã³ãåäœããªããšããäºå®ã«ãããã®ã§ãã
ããã§ã®ä¿®æ£ã¯éåžžã«ç°¡åã§ããããšãå€æããŸããã
ããã¯ã°ã©ãŠã³ãã§é¢ãããšãã¯ããããŒã®ã¹ã¯ãªãŒã³ã·ã§ãããæ®ãå¿ èŠããããŸãã
WebViewã³ã³ããŒãã³ããOpenGLã®äœ¿çšãåæ¢ããããã«ãç»é¢ããåºåãã¥ãŒãåé€ããŸãã
ããã¯ã°ã©ãŠã³ããçµäºãããããã¹ãŠãå ã«æ»ããŸãã
Objective-Cã³ãŒãã§ã¯ã次ã®ããã«ãªããŸãã
- (void)onWillResignActive { if (self.adView.superview) { UIGraphicsBeginImageContext(self.adView.bounds.size); [self.adView.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *adViewScreenShot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); adViewThumbView = [[UIImageView alloc] initWithImage:adViewScreenShot]; adViewThumbView.backgroundColor = [UIColor clearColor]; adViewThumbView.frame = self.adView.frame; NSInteger adIndex = [self.adView.superview.subviews indexOfObject:self.adView]; [self.adView.superview insertSubview:adViewThumbView atIndex:adIndex]; [self.adView removeFromSuperview]; } } - (void)onDidBecomeActive { if (self.adView && adViewThumbView) { NSInteger adIndex = [adViewThumbView.superview.subviews indexOfObject:adViewThumbView]; [adViewThumbView.superview insertSubview:self.adView atIndex:adIndex]; [adViewThumbView removeFromSuperview]; adViewThumbView = nil; } }
- çµ±å
ãããã¯ãiFunnyãMopubãããã³åºåãããã€ããŒã®ãžã£ã³ã¯ã·ã§ã³ã§çºçããåé¡ã§ãã
ååãšããŠããããã¯ãããã€ããŒã©ã€ãã©ãªãæŽæ°ããåŸãããã³ããããšå¯Ÿè©±ããæ°ããæ¹æ³ã®ããã«çºçããŸãã
æåŸã®ãã®ãããªã±ãŒã¹ã¯ã䜿çšãããŠããã©ã€ãã©ãªã®1ã€ã®æ¬¡ã®æŽæ°åŸã®ä»å¹Ž6æã§ããã ã©ã€ãã©ãªãåæåããæ°ããæ¹æ³ã¯ãã·ã³ã°ã«ãã³ã䜿çšããŠãããã¯ãŒã¯èšå®ãæ§æããããšãææ¡ããŸããã
å®è£ ã§èµ·ãã£ãããã«ã2åç®ãåããšå®æçã«ã¡ã€ã³ã¹ã¬ããã®ããªãŒãºãçºçãããããdispatch_onceã§åæåãã©ããããå¿ èŠããããŸããã
iFunny QAéšéã¯åºåã©ã€ãã©ãªãããŸããã¹ãã§ããããããã®åé¡ã¯ã¢ããããŒãã®ãã¹ãäžã«çºèŠãããŸããã
- äºæ³å€
ãã®ã¿ã€ãã®ã¯ã©ãã·ã¥ã¯ãã¯ã©ã€ã¢ã³ããå€æŽããã«çºçããããããŸã£ããå¶åŸ¡ã§ããŸããã
ãããã¯ãããŒãããŒã®ããã¯ãšã³ãã®æŽæ°ãšäžäœäºææ§ã®æ¬ åŠã«é¢é£ããŠããŸãã ãã®ãããªã¯ã©ãã·ã¥ã¯å€§èŠæš¡ãªåºåãããã€ããŒã§é »ç¹ã«çºçããŸãããå€æ°ã®ã¢ããªã±ãŒã·ã§ã³ã«åæã«åœ±é¿ãããããããã«ä¿®æ£ãããŸãã
1æ¥ãããã®ã¯ã©ãã·ã¥ã®ãªãiFunnyãæšæºã®99.8ïŒ ãã80ïŒ ã«äœäžããã¹ãã¢å ã§ã®æãã®ã³ã¡ã³ãã®æ°ãæ°åã«ãªã£ãå ŽåããããŸããã
æ§èœ
ååãšããŠããããŒåºåã¯WebViewã³ã³ããŒãã³ãã䜿çšããŠåºåã衚瀺ããããã衚瀺ãããåãããŒã¯ããã¹ãŠã®äŸåé¢ä¿ãæã€æ°ããWebViewã®åæåã§ãã
ããã«ãã¢ãã€ã«ããã€ã¹ã§ã®ãããŒåºåã¯Webã§ã®åºåã®åå«ã§ãããããäžéšã®ããŒãããŒã¯WebViewã䜿çšããŠç¬èªã®ããã¯ãšã³ããšéä¿¡ããŸãã
ã¢ããã°ã¬ãŒãåŸã«ãæ°ããã©ã€ãã©ãªå ã§ã¡ã¢ãªãªãŒã¯ãçºçããããšããããŸãã Xcodeã«Memory GraphããŒã«ãç»å ŽããåŸããµãŒãããŒãã£ã®ã©ã€ãã©ãªã§ãªãŒã¯ãèŠã€ããã®ãã¯ããã«ç°¡åã«ãªã£ããããããŒãããŒã«ãªãŒã¯ã«ã€ããŠããã«éç¥ã§ããããã«ãªããŸããã
以äžã¯ããŠãŒã¶ãŒã«åºåããªãå Žåã®iFunnyã¢ã€ãã«ã®GIFã§ãã

解決ç
ããããäžèšã®ãã¹ãŠã®åé¡ã«ãããããããiFunnyã¯å®å®ããŠåäœããæ¯æ¥äœçŸäžäººãã®ãŠãŒã¶ãŒã«ç¬é¡ããããããŠããŸãã
åºåã«é¢ããé·å¹Žã®æŽ»åãéããŠãéçºããŒã ã«ã¯ãåºåã®åé¡ãé©åã«ç£èŠããæéå ã«ãããã«å¯Ÿå¿ããããã®ããŒã«ãããã€ããããŸãã
ãã®ã³ã°ã·ã¹ãã
ããã§ãiFunnyã®äŸå€ãã°ã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³å šäœã«åºãããŸããããã®ãããClickHouseãããŒã¹ãšããç¬èªã®ããã¯ãšã³ãã䜿çšããŠãGrafanaã§è¡šç€ºããŸãã
ããããã¢ããªã±ãŒã·ã§ã³ã§ãã°ãæäœããããã®æåã®ã¿ã¹ã¯ã¯ãåºåã®äŸå€çãªç¶æ³ãæ£ç¢ºã«èšé²ããããšã§ããã
é話ãiFunnyã«è»¢éããããã©ãããå€æããã«ã¯ãããã€ãã®é¢é£ã³ã³ããŒãã³ãããããŸãã ããããã«ã€ããŠè©³ãã説æããŸãã
IFAdView
ããã¯MPAdViewã¯ã©ã¹ã®åå«ã§ãïŒMoPubã«åºåã衚瀺ãã圹å²ãæãããŸãïŒã
hitTestïŒwithEventã¡ãœããã¯ããã®ã¯ã©ã¹ã§ãªãŒããŒã©ã€ããããŸãã
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitView = [super hitTest:point withEvent:event]; if (hitView) { [[IFAdsExceptionManager instance] triggerTouchView]; } return hitView; }
ãããã£ãŠããŠãŒã¶ãŒãåºåãšå¯Ÿè©±ãããšããäºå®ã«åºã¥ããŠããªã¬ãŒãèšå®ããŸãã
IFURLProtocol
NSURLProtocolãç¶æ¿ããã¡ãœããã説æããŸãã
+ (BOOL)canInitWithRequest:(NSURLRequest *)request { __weak NSString *wRequestURL = request.URL.absoluteString; dispatch_async(dispatch_get_main_queue(), ^{ if (wRequestURL == nil) return; if ([wRequestURL hasPrefix:@"itms-appss://itunes.apple.com"] || [wRequestURL hasPrefix:@"itms-apps://itunes.apple.com"] || [wRequestURL hasPrefix:@"itmss://itunes.apple.com"] || [wRequestURL hasPrefix:@"http://itunes.apple.com"] || [wRequestURL hasPrefix:@"https://itunes.apple.com"]) { [[IFAdsExceptionManager instance] adsTriggerItunesURL:wRequestURL]; } }); return NO; }
ããã¯ãã¢ããªã±ãŒã·ã§ã³ããAppStoreãéãããã®ããªã¬ãŒã§ããããã«äœ¿çšå¯èœãªãã¹ãŠã®URLããªã¹ãããŸãã
IFAdsExceptionManager
ããªã¬ãŒãåéãããã°ã«äŸå€ã¬ã³ãŒããçæããã¯ã©ã¹ã
ããªã¬ãŒã®çš®é¡ãæ確ã«ããããã«ããã®ã¯ã©ã¹ã®åã€ã³ã¿ãŒãã§ã€ã¹ã¡ãœããã«ã€ããŠèª¬æããŸãã
- (void)triggerTouchView; . <source lang="objectivec">- (void)triggerItunesURL:(NSString *)itunesURL;
iTunesã§ãªãã€ã¬ã¯ããçºçãããã©ããã決å®ããããªã¬ãŒã
- (void)triggerResignActive;
ã¢ããªã±ãŒã·ã§ã³ã«ããã¢ã¯ãã£ããã£ã®æ倱ã決å®ããããªã¬ãŒã åã®2ã€ã®ããªã¬ãŒãæ¯èŒããŸãã
- (void)resetTriggers;
ããªã¬ãŒããªã»ããããŸãã ããã¯ã°ã©ãŠã³ããé¢ãããšãããŸãã¯AppStoreãèªåã§éããšããããšãã°ãå€ãããŒãžã§ã³ã®iOSã§è©äŸ¡ããããã«ãŠãŒã¶ãŒãéä¿¡ãããšãã«åŒã³åºããŸãã
@property (nonatomic, strong) FNAdConfigurationInfo *lastRequestedConfiguration; @property (nonatomic, strong) FNAdConfigurationInfo *lastLoadedConfiguration; @property (nonatomic, strong) FNAdConfigurationInfo *lastFailedConfiguration;
æåŸã«æåãŸãã¯å€±æããåºåãèšé²ããããã®ããããã£ã ãã°ãžã®ã¡ãã»ãŒãžãäœæããå¿ èŠããããŸããã
ã¢ã«ãŽãªãºã ã¯éåžžã«ã·ã³ãã«ã§ããããšãããããŸããããå¹æçã§ãã ããã«ãããMoPubããã®èªåæ€åºã ãã§ãªããä»ã®ãããã¯ãŒã¯ããã®èªåæ€åºã远跡ã§ããŸãã
æè¿ãèªåã§éãåºåã¯SKStoreProductViewControllerãéãããšãå€ãããããã®ã³ã³ãããŒã©ãŒã®èªåã§éãã®å®çŸ©ã«åãçµãã§ããŸãã ãã®äŸå€ãå®çŸ©ããã¢ã«ãŽãªãºã ã¯ããå°ãè€éã«ãªããŸãããObjective-Cã©ã³ã¿ã€ã ãããã§åœ¹ç«ã¡ãŸãã
ããŒã«ã«ã¹ã¿ã³ã
ãã®ã³ã°ã·ã¹ãã ã«åºã¥ããŠãiFunnyã¯ããŠãŒã¶ãŒããªã¢ã«ã¿ã€ã ã§è¡šç€ºããåºåãåä¿¡ããã³ãããã°ããããã«ãããŒã«ã«ã¹ã¿ã³ãã®éçºãéå§ããŸããã
ã¹ã¿ã³ãã®æ§æïŒ
- ãã«ããšãŒãžã§ã³ã
- ããã€ã¹
- åãããã€ããŒã®ãã¹ãã¹ã€ãŒã
ã¹ã¿ã³ãã§äœ¿çšãããèå³æ·±ããœãªã¥ãŒã·ã§ã³ã®1ã€ã¯ãå®éã®åºåã«å¯ŸãããŠãŒã¶ãŒã®èŠæ ããã®IDFAã§ãã
2016幎é ãããVPNã®ã¿ã䜿çšããŠç±³åœãã¿ãŒã²ãããšããå®éã®åºåã®åä¿¡ãåæ¢ãããããIDFAããã€ã¹ãå®éã®ãŠãŒã¶ãŒã®IDFAã«çœ®ãæããå¿ èŠããããŸãã
ããã¯ãObjective-Cã©ã³ã¿ã€ã ãšã¹ãŠã£ãºãªã³ã°ã䜿çšããŠéåžžã«ç°¡åã«å®è¡ã§ããŸãã
ASIdentifierManagerã¯ã©ã¹ã®AdvertisingIdentifierã¡ãœããã眮ãæããå¿ èŠããããŸãã
ããã§ã¯ãã«ããŽãªãä»ããŠãããè¡ããŸãã
@interface ASIdentifierManager (IDFARewrite) @end @implementation ASIdentifierManager (IDFARewrite) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ if (AdsMonitorTests.customIDFA != nil) { [self swizzleIDFA]; } }); } + (void)swizzleIDFA { Class class = [self class]; SEL originalSelector = @selector(advertisingIdentifier); SEL swizzledSelector = @selector(swizzled_advertisingIdentifier); Method originalMethod = class_getInstanceMethod(class, originalSelector); Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (didAddMethod) { class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } } #pragma mark - Method Swizzling - (NSUUID *)swizzled_advertisingIdentifier { NSUUID *result = AdsMonitorTests.customIDFA; return result; } @end
ãŠãŒã¶ãŒIDFAããã«ããšãŒãžã§ã³ãã«è»¢éããã«ã¯ã èšäºã§èª¬æãããŠããæ¹æ³ããã«ãã§äœ¿çšããŸãã
çµè«ãšããŠããããŒåºåã¯ç±³åœã§ããŸãæ©èœããåçåã®äž»èŠãªæ¹æ³ãšããŠ7幎éç©æ¥µçã«äœ¿çšãããŠãããããiFunnyã¯ãããŒåºåãšããŸãæ©èœããããšãåŠã³ãŸããã
ãããããããŒãäŒç€Ÿã®åçã®75ïŒ ããããããšããäºå®ã«ãããããããåçåã®ä»£æ¿æ¹æ³ã«é¢ããäœæ¥ãé²è¡äžã§ãããç±³åœåžå Žã§ã®ãã€ãã£ãåºåããã³åºåãªãŒã¯ã·ã§ã³ã®äœ¿çšã§ãã§ã«ããã€ãã®çµéšãåŸãããŠããŸãã
äžè¬ã«ãäŒããã¹ãããšããããŸãã