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.

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