Objective-C++を使ってMRCで快適に開発する

06641ec93c5914e0db74cddff2ec6004?s=47 Yuki Yasoshima
September 15, 2017

 Objective-C++を使ってMRCで快適に開発する

iOSDC 2017 9/15

サンプルコード
https://github.com/objective-audio/objc_ptr_sample

06641ec93c5914e0db74cddff2ec6004?s=128

Yuki Yasoshima

September 15, 2017
Tweet

Transcript

  1. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF 0CKFDUJWF$ Λ࢖ͬͯ .3$Ͱշదʹ։ൃ͢Δ :VLJ:BTPTIJNB !ZBTP@TBO

  2. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF 0CKFDUJWF$ͷϝϞϦ؅ཧ

  3. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF "VUPNBUJD3FGFSFODF$PVOUJOH "3$ ࢀরΧ΢ϯλํࣜͷϝϞϦ؅ཧΛ ίϯύΠϥ͕ࣗಈͰߦͬͯ͘ΕΔ

  4. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF "3$ͷઃఆ

  5. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF .BOVBM3FGFSFODF$PVOUJOH .3$ ࢀরΧ΢ϯλํࣜͷϝϞϦ؅ཧΛ खಈͰߦ͏

  6. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF .3$ͰͷϝϞϦ؅ཧ TestClass *value = [[TestClass alloc] init]; // ࢀরΧ΢ϯτ

    1 [value release]; // ࢀরΧ΢ϯτ 0
  7. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF .3$ͰͷϝϞϦ؅ཧ NSNumber *value = [[NSNumber alloc] initWithInt:1]; [value retain];

    // ࢀরΧ΢ϯτ 2 [value release]; // ࢀরΧ΢ϯτ 1 [value release]; // ࢀরΧ΢ϯτ 0
  8. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF .3$ͰͷϝϞϦ؅ཧ @autoreleasepool { NSNumber *value = [[NSNumber alloc] initWithInt:1];

    [value autorelease]; // ࢀরΧ΢ϯτ = 1 (- 1) ... } // ࢀরΧ΢ϯτ = 0
  9. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF "3$ͷ৔߹ͷΫϥε࣮૷ @implementation Sample { NSNumber *_value; } - (void)setValue:(NSNumber

    *)value { _value = value; } - (NSNumber *)value { return _value; } @end
  10. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF .3$ͷ৔߹ͷΫϥε࣮૷ @implementation Sample { NSNumber *_value; } - (void)setValue:(NSNumber

    *)value { [value retain]; [_value release]; _value = value; } - (NSNumber *)value { return [[_value retain] autorelease]; } - (void)dealloc { [_value release]; [super dealloc]; } @end
  11. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF 0CKFDUJWF$

  12. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF ֦ுࢠΛNNʹ͢Δ

  13. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF ࣅͨػೳͷݺͼํͷҧ͍ 0CKFDUJWF$ 4XJGU $ Πϯελϯεม਺ɾϝιου ϝϯόม਺ɾؔ਺ ΠχγϟϥΠβ ίϯετϥΫλ δΣωϦΫε

    ςϯϓϨʔτ ϒϩοΫɾΫϩʔδϟ ϥϜμࣜ
  14. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF 0CKFDUJWF$ #import <Foundation/Foundation.h> #import <string> #import <iostream> void Sample()

    { NSString *objcText = @"Obj-C Text"; NSLog(@"%@", objcText); std::string cppText = "C++ Text"; std::cout << cppText << std::endl; }
  15. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF 0CKFDUJWF$ @implementation ObjcClass { std::string _text; } - (void)setText:(std::string

    const &)text { _text = text; } - (std::string const &)text { return _text; } @end
  16. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF 0CKFDUJWF$ class CppClass { NSString *_text; public: void setText(NSString

    *text) { _text = text; } NSString *text() { return _text; } };
  17. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF $ ͷϝϞϦ؅ཧ

  18. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF $ ΦϒδΣΫτͷΠϯελϯεԽ CppClass *pointer = new CppClass(); delete pointer;

  19. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF $ ΦϒδΣΫτͷΠϯελϯεԽ CppClass value_1; CppClass value_2(2); CppClass value_3{3}; CppClass

    value_4 = CppClass(4); auto value_5 = CppClass(5);
  20. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF ղ์͞ΕΔλΠϛϯάʢؔ਺ʣ void SampleFunc() { CppClass value; } // <-

    value͸ؔ਺ͷείʔϓΛൈ͚Δ࣌ʹղ์͞ΕΔ
  21. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF ղ์͞ΕΔλΠϛϯάʢؔ਺ʣ void SampleFunc() { if (true) { CppClass value;

    } // <- value͸JGͷείʔϓΛൈ͚Δ࣌ʹղ์͞ΕΔ }
  22. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF ղ์͞ΕΔλΠϛϯάʢ$ Ϋϥεʣ class CppParentClass { public: CppClass value; ~CppParentClass()

    { } // <- σετϥΫλ͕ݺ͹Εͨޙʹϝϯόม਺value͕ղ์͞ΕΔ };
  23. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF ղ์͞ΕΔλΠϛϯάʢ0CK$Ϋϥεʣ @implementation ObjcParent { CppClass value; } - (void)dealloc

    { [super dealloc];// <- deallocͷதͰΠϯελϯεม਺͕ղ์͞ΕΔ } @end
  24. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF 0CKFDUJWF$ͷΦϒδΣΫτΛ อ࣋͢Δ$ ͷΫϥεΛ࡞Δ

  25. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF 0CKFDUJWF$ͷΦϒδΣΫτΛ อ࣋͢Δ$ ͷΫϥεΛ࡞ͬͨ

  26. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF PCKD@QUSIQQ // // objc_ptr.hpp // #pragma once #include <memory>

    #include <functional> template <typename T> class objc_impl { public: T const value; objc_impl(T value) : value(value) { [value retain]; } ~objc_impl() { [value release]; } }; template <typename T> class weak_objc_ptr; template <typename T> objc_ptr<T> make_objc_ptr(T value) { objc_ptr<T> ptr(value); [value release]; return ptr; } template <typename T> class weak_objc_ptr { std::weak_ptr<objc_impl<T>> _impl; public: weak_objc_ptr() = default; weak_objc_ptr(objc_ptr<T> ptr) : _impl(ptr._impl) { } objc_ptr<T> lock() const { if (auto locked = _impl.lock()) { return objc_ptr<T>(locked); } else { return objc_ptr<T>(); } } }; template <typename T> weak_objc_ptr<T> to_weak(objc_ptr<T> ptr) { return weak_objc_ptr<T>(ptr); } template <typename T> class objc_ptr { friend class weak_objc_ptr<T>; std::shared_ptr<objc_impl<T>> _impl; objc_ptr(std::shared_ptr<objc_impl<T>> holder) : _impl(holder) { } public: objc_ptr() : objc_ptr(nil) { } objc_ptr(T value) : _impl(std::make_shared<objc_impl<T>>(value)) { } objc_ptr(std::function<T(void)> handler) { @autoreleasepool { _impl = std::make_shared<objc_impl<T>>(handler()); } } T value() const { return _impl->value; } T operator*() const { return _impl->value; } explicit operator bool() const { return _impl->value != nil; } };
  27. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF PCKD@QUS5 TIBSFE@QUSPCKD@JNQM5 PCKD@QUSΫϥεͷߏ੒ PCKD@JNQM5 ˞5͸0CKFDUJWF$ͷΫϥεͷܕʢʮ/44USJOH ʯͳͲʣ 5WBMVFʢSFUBJOͯ͠อ࣋ʣ

  28. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF PCKD@QUSͷ࢖༻ྫ

  29. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF SFUBJOͯ͠อ࣋͢Δ TestClass *testObj = [[[TestClass alloc] init] autorelease]; objc_ptr<TestClass

    *> test_ptr(testObj); NSLog(@"value : %@", test_ptr.value()); NSLog(@"value : %@", *test_ptr);
  30. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF ࢀরΧ΢ϯτͦͷ··อ࣋͢Δ auto test_ptr = make_objc_ptr([[TestClass alloc] init]); NSLog(@“value :

    %@", *test_ptr);
  31. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF BVUPSFMFBTFΛ֎ͯ͠อ࣋͢Δ objc_ptr<TestClass *> test_ptr( []() { return [[[TestClass alloc]

    init] autorelease]; } ); NSLog(@"value : %@", *test_ptr);
  32. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF ऑࢀরͰอ࣋͢Δ auto test_ptr = make_objc_ptr([[TestClass alloc] init]); weak_objc_ptr<TestClass *>

    weak_ptr = test_ptr; if (auto locked_ptr = weak_ptr.lock()) { NSLog(@"value : %@", *locked_ptr); }
  33. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF ௚઀ऑࢀরΛฦؔ͢਺ auto test_ptr = make_objc_ptr([[TestClass alloc] init]); auto weak_ptr

    = to_weak(test_ptr); auto handler = [weak_ptr]() { auto locked_ptr = weak_ptr.lock(); NSLog(@"locked value : %@", locked_ptr.value()); }; handler();
  34. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF Πϯελϯεม਺Ͱ࢖͏ @implementation Sample { objc_ptr<NSNumber *> _value; } -

    (void)setValue:(NSNumber *)value { _value = value; } - (NSNumber *)value { return *_value; } @end
  35. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF ͭͷ0CKFDUJWF$ΦϒδΣΫτΛ ෳ਺ͷPCKD@QUSʹ࣋ͨͤͳ͍ํ͕ྑ͍ ʢಛʹXFBLΛ࢖͏৔߹ʣ ࢖༻্ͷ஫ҙ

  36. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF PCKD@QUSಉ࢜ΛൺֱͰ͖ΔΑ͏ʹ͢ΔɺͳͲ "3$ͱ.3$ΛPCKD@QUSͰٵऩ͢Δ ͞Βʹൃలͤ͞Δ

  37. IUUQTHJUIVCDPNPCKFDUJWFBVEJPPCKD@QUS@TBNQMF ͓ΘΓ