Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Objective-C++: What could possibly go wrong?

Objective-C++: What could possibly go wrong?

Talk for AltConf 2015 in San Francisco

We're digging into the beautiful madness called Objective-C++ and look at use cases where it's great, where it's terrible and how to not shoot yourself in the foot. Did you know that modern C++ has it's own version of ARC, weak and blocks? You'll learn to identify common performance bottlenecks and a small subset of C++ that will be a useful addition to your toolbox. This is based on a large codebase that shares a common core over iOS, Android and even runs on the Mac.

Avatar for Peter Steinberger

Peter Steinberger

June 09, 2015
Tweet

More Decks by Peter Steinberger

Other Decks in Programming

Transcript

  1. Audience — You've seen C++ before. — You care about

    elegant, performant code. — The world doesn't end with iOS. — You wanna come to the dark side.
  2. C++ — Actively improved (C++11, C++14, C++17) — Great tooling,

    great compiler, great ecosystem — Cross-Platform — Really fast — Powerful standard library (STL) — Many 3rd-party libraries available0 0 https://github.com/fffaraz/awesome-cpp
  3. This is not your grandmother's C++! — auto — shared_ptr

    — weak — lambdas — move semantics
  4. auto & range-based for loops // C++98 for (vector<CGPoint>::iterator i

    = v.begin(), e = v.end(); i != e; ++i) { reticulateSpline(*i); } // C++11 for (CGPoint& point : v) { reticulateSpline(point); }
  5. auto & range-based for loops // C++98 for (vector<CGPoint>::iterator i

    = v.begin(), e = v.end(); i != e; ++i) { reticulateSpline(*i); } // C++11 for (auto& point : v) { reticulateSpline(point); }
  6. auto & range-based for loops // C++98 for (vector<CGPoint>::iterator i

    = v.begin(), e = v.end(); i != e; ++i) { reticulateSpline(*i); } // C++17 for (point : v) { reticulateSpline(point); }
  7. std::vector<CGPoint> — Continuous block of memory — Stack or Heap

    — Throws exceptions on access out of bounds — powerful mutators like rotate2 2 http://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning
  8. Smart Pointers // Returns all developers. Delete when done. vector<Developer*>

    get_developers(); // cleanup for (vector<Developer*>::iterator i = v.begin(); i != v.end(); ++i) { delete *i; }
  9. Smart Pointers // Returns all developers (C++11) vector<unique_ptr<Developer>> get_developers(); //

    adding a new element (C++11) devs.push_back(unique_ptr<Developer>(new Developer("steipete")));
  10. Smart Pointers // Returns all developers (C++11) vector<unique_ptr<Developer>> get_developers(); //

    adding a new element (C++11, more efficient) devs.emplace_back(unique_ptr<Developer>(new Developer("steipete")));
  11. Smart Pointers // Returns all developers (C++11) vector<unique_ptr<Developer>> get_developers(); //

    adding a new element (C++14) devs.emplace_back(make_unique<Developer>("steipete"));
  12. Smart Pointers // Returns all developers. vector<unique_ptr<Developer>> get_developers(); // later

    on auto developers = get_developers(); shared_ptr<Developer> developer = developers[0];
  13. Move semantics // get all the points vector<CGPoint> points =

    get_points(); vector(const vector& that) { size_t size = strlen(that.data) + 1; data = new char[size]; memcpy(data, that.data, size); }
  14. Move semantics // get all the points vector<CGPoint> points =

    get_points(); vector(vector&& that) { data = that.data; that.data = nullptr; }
  15. Lambdas [] Capture nothing [&] Capture by reference [=] Capture

    by making a copy [this] Capture enclosing class [=, &foo] [bar]
  16. Lambdas void PSPDFParseFont(const char *key, CGPDFObjectRef value, void *info) {

    NSLog(@"key: %s", key); }; // later, in another function CGPDFDictionaryApplyFunction(fontDict, dictIterator, (__bridge void *)self);
  17. Lambdas auto parseFont = [] (const char *key, CGPDFObjectRef value,

    void *info) { NSLog(@"key: %s", key); }; CGPDFDictionaryApplyFunction(fontDict, parseFont, (__bridge void *)self);
  18. Objective-C++ — Freely mix C++ and Objective-C3 — Enable by

    renaming files to .hpp and .mm 3 http://web.archive.org/web/20101203170217/http://developer.apple.com/library/mac/#/ web/20101204020949/http://developer.apple.com/library/mac/documentation/Cocoa/ Conceptual/ObjectiveC/Articles/ocCPlusPlus.html
  19. Why Objective-C++4 [CKStackLayoutComponent newWithStyle:{ .direction = CKStackLayoutComponentDirectionVertical, } children:{ {[HeaderComponent

    newWithArticle:article]}, {[MessageComponent newWithArticle:article]}, {[FooterComponent newWithArticle:article]}, }]; 4 http://componentkit.org/docs/why-cpp.html
  20. Why Objective-C++ [CKStackLayoutComponent newWithStyle:[[CKStackLayoutComponentStyle alloc] initWithDirection:CKStackLayoutComponentDirectionVertical justifyContent:CKStackLayoutComponentJustifyContentStart alignItems:CKStackLayoutComponentAlignItemsStart spacing:0] children:@[

    [CKStackLayoutComponentChild childWithComponent:[HeaderComponent newWithArticle:article] topPadding:0 leftPadding:0 bottomPadding:0], [CKStackLayoutComponentChild childWithComponent:[MessageComponent newWithArticle:article] topPadding:0 leftPadding:0 bottomPadding:0], [CKStackLayoutComponentChild childWithComponent:[FooterComponent newWithArticle:article] topPadding:0 leftPadding:0 bottomPadding:0] ]];
  21. Nil Safety NSArray *array = @[@"a", @"b", (NSString *)nil, @"d"];

    auto vector = vector<NSString*>{@"a", @"b", nullptr, @"d"};
  22. Nil Safety auto vector = vector<NSString*>{@"a", @"b", nullptr, @"d"}; vector.erase(remove_if(begin(vector),

    end(vector), [](NSString *string) { return string == nullptr; }), end(vector));
  23. Nil Safety NSMutableArray *children = [NSMutableArray array]; if (headerComponent) {

    [children addObject:headerComponent]; } if (messageComponent) { [children addObject:messageComponent]; } if (attachmentComponent) { [children addObject:attachmentComponent]; } if (footerComponent) { [children addObject:footerComponent]; }
  24. Inline blocks void (^handler)(NSData *data, NSURLResponse *response, NSError *error) =

    ^(NSData *data, NSURLResponse *response, NSError *error) { // parse data }; [NSURLSession sharedSession] dataTaskWithURL:URL completionHandler:handler];
  25. Inline blocks auto handler = ^(NSData *data, NSURLResponse *response, NSError

    *error) { // parse data }; [NSURLSession sharedSession] dataTaskWithURL:URL completionHandler:handler];
  26. Universal comparison function for value types template <typename T> inline

    NSComparisonResult PSPDFCompare(const T value1, const T value2) { if (value1 < value2) return (NSComparisonResult)NSOrderedAscending; else if (value1 > value2) return (NSComparisonResult)NSOrderedDescending; else return (NSComparisonResult)NSOrderedSame; }
  27. Operator overloading for CGPoint inline CGPoint operator+(const CGPoint &p1, const

    CGPoint &p2) { return { p1.x + p2.x, p1.y + p2.y }; } inline CGPoint operator-(const CGPoint &p1, const CGPoint &p2) { return { p1.x - p2.x, p1.y - p2.y }; }
  28. Practical Example void CreatePathsForLineEndType(PSPDFLineEndType const endType, CGPoint const* points, NSUInteger

    const pointsCount, CGFloat const lineWidth, CGPathRef *storedFillPath, CGPathRef *storedStrokePath);
  29. Convert raw pointer to a vector reference void CreatePathsForLineEndType(PSPDFLineEndType const

    endType, std::vector<CGPoint> const& points, CGFloat const lineWidth, CGPathRef *storedFillPath, CGPathRef *storedStrokePath); // copy points into a vector auto vector = std::vector<CGPoint>(points, points+pointsCount); auto vector = std::vector<CGPoint>{point1, point2, point3};
  30. // old void CreatePathsForLineEndType(PSPDFLineEndType endType, CGPoint const* points, NSUInteger pointsCount,

    CGFloat lineWidth, CGPathRef *storedFillPath, CGPathRef *storedStrokePath); // new tuple<CFPointer<CGPathRef>, CFPointer<CGPathRef>> FillAndStrokePathForLineEndType(PSPDFLineEndType endType, std::vector<CGPoint> const& points, CGFloat lineWidth);
  31. Thanks! Peter Steinberger, @steipete References - http://blog.petrzemek.net/2014/12/07/improving-cpp98-code-with-cpp11 - http://componentkit.org/docs/why-cpp.html -

    http://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom - http://en.cppreference.com/w/cpp/language/aggregate_initialization - http://stackoverflow.com/questions/3106110/what-are-move-semantics - http://web.archive.org/web/20101203170217/http://developer.apple.com/library/ mac/#/web/20101204020949/http://developer.apple.com/library/mac/documentation/Cocoa/ Conceptual/ObjectiveC/Articles/ocCPlusPlus.html - http://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning - https://developer.apple.com/library/ios/documentation/DeveloperTools/ Conceptual/WhatsNewXcode/Articles/xcode_5_0.html - https://gist.github.com/steipete/0f65c234ee843ed514ff