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

Еще раз про Objective-C++

CocoaHeads
April 26, 2018
42

Еще раз про Objective-C++

CocoaHeads

April 26, 2018
Tweet

More Decks by CocoaHeads

Transcript

  1. Why Objective-C++? A.Compile time B.Efficiency C.More expressive and flexible syntax

    D.Powerful standard library and a lot of 3party* 8 *https://github.com/fffaraz/awesome-cpp
  2. Write shorter typedef NS_ENUM(NSInteger, XXXPointType) { XXXPointTypeStart, XXXPointTypeIntermediate, XXXPointTypeEnd };

    @interface XXXPoint : NSObject @property (nonatomic) XXXPointType type; @property (nonatomic) CLLocationCoordinate2D location; @property (nonatomic) NSString * title; - (instancetype)initWithType:(XXXPointType)type location:(CLLocationCoordinate2D)location title:(NSString *)title; @end 9
  3. Write shorter @implementation XXXPoint - (instancetype)initWithType:(XXXPointType)type location:(CLLocationCoordinate2D)location title:(NSString *)title {

    self = [super init]; if (self) { _type = type; _location = location; _title = title; } return self; } @end 10
  4. Write shorter XXXPoint * start = [[XXXPoint alloc] initWithType:XXXPointTypeStart location:CLLocationCoordinate2DMake(startLat,

    startLon) title:startTitle]; XXXPoint * intermediate = ...; XXXPoint * end = ...; NSArray<XXXPoint *> * points = @[start, intermediate, end]; [XXXRouter build:points]; 11
  5. Write shorter Too many symbols, huh? 13 XXXPoint * start

    = [[XXXPoint alloc] initWithType:XXXPointTypeStart location:CLLocationCoordinate2DMake(startLat, startLon) title:startTitle];
  6. Write shorter Too many symbols, huh? 14 XXXPoint * start

    = [[XXXPoint alloc] initWithType:XXXPointTypeStart location:CLLocationCoordinate2DMake(startLat, startLon) title:startTitle];
  7. Write shorter Too many symbols, huh? 15 XXXPoint * start

    = [[XXXPoint alloc] initWithType:XXXPointTypeStart location:CLLocationCoordinate2DMake(startLat, startLon) title:startTitle];
  8. Write shorter using namespace xxx; Point start{Point::Type::Start, {startLat, startLon}, startTitle};

    Point intermediate... Point end... [XXXRouter build:{start, intermediate, end}]; 16
  9. Write shorter using namespace xxx; Point start{Point::Type::Start, {startLat, startLon}, startTitle};

    Point intermediate... Point end... [XXXRouter build:{start, intermediate, end}]; 17
  10. Write shorter using namespace xxx; Point start{Point::Type::Start, {startLat, startLon}, startTitle};

    Point intermediate... Point end... [XXXRouter build:{start, intermediate, end}]; 18
  11. Write shorter using namespace xxx; Point start{Point::Type::Start, {startLat, startLon}, startTitle};

    Point intermediate... Point end... [XXXRouter build:{start, intermediate, end}]; 19
  12. Write shorter namespace xxx { struct Point { enum class

    Type { Start, Intermediate, End }; }; } 22
  13. Write shorter namespace xxx { struct Point { enum class

    Type { Start, Intermediate, End }; Type _type; CLLocationCoordinate2D _location; NSString * _title; }; } 23
  14. Write shorter namespace xxx { struct Point { enum class

    Type { Start, Intermediate, End }; Point(Type type, CLLocationCoordinate2D location, NSString * title) : _type(type), _location(location), _title(title) {} Type _type; CLLocationCoordinate2D _location; NSString * _title; }; } 24
  15. Aggregate initialization CGPoint point = CGPointMake(x, y); CGRect rect =

    CGRectMake(x, y, width, height); UIEdgeInsets inset = UIEdgeInsetsMake(top, left, bottom, right); CGSize size = CGSizeMake(width, height); 25
  16. Aggregate initialization CGPoint point = CGPointMake(x, y); CGSize size =

    CGSizeMake(width, height); CGRect rect = CGRectMake(x, y, width, height); UIEdgeInsets inset = UIEdgeInsetsMake(top, left, bottom, right); CGPoint point{x, y}; CGSize size{width, height}; CGRect rect{{x, y}, {width, height}}; UIEdgeInsets insets{top, left, bottom, right}; vs 26
  17. About arrays typedef NS_ENUM(NSInteger, Color) { Red, Green, Blue, Alpha

    }; NSMutableArray<NSNumber *> * colors = @[@(Red), @(Green), @(Blue), @(Alpha)]; // ... Color red = colors.firstObject.integerValue; 27
  18. About arrays typedef NS_ENUM(NSInteger, Color) { Red, Green, Blue, Alpha

    }; std::vector<Color> colors{Red, Green, Blue, Alpha}; //... Color red = colors.front(); 28
  19. std::vector<T> A. Implements dynamic array (like NSMutableArray) B. Is able

    to contain any types (pointer to Objective-C object, plain old data, enum etc) 30
  20. std::vector<T> 31 std::vector<NSString *> strings{@"some string", @"and another one"}; std::vector<int>

    numbers; numbers.emplace_back(1); for (auto const element : vector) {} auto const firstString = strings[0];
  21. std::vector<T> #include <vector> typedef NS_ENUM(NSInteger, Section) { Top, Middle, Bottom

    }; typedef NS_ENUM(NSInteger, TopRow) { /*...*/ }; typedef NS_ENUM(NSInteger, MiddleRow) { /*...*/ }; typedef NS_ENUM(NSInteger, BottomRow) { /*...*/ }; @interface TableData : NSObject - (std::vector<Section> const &)sections; - (std::vector<TopRow> const &)topRows; - (std::vector<MiddleRow> const &)middleRows; - (std::vector<BottomRow> const &)bottomRows; @end 32
  22. std::vector<T> @implementation TableData { std::vector<Section> _sections; std::vector<TopRow> _topRows; std::vector<MiddleRow> _middleRows;

    std::vector<BottomRow> _bottomRows; } - (void)fillRows { _sections.emplace_back(Top, Bottom); _topRows.emplace_back(/*...*/); // ... } - (std::vector<Section> const &)sections { return _sections; } // ... @end 33
  23. std::vector<T> - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section { switch (self.data.sections[section]) {

    case Top: return self.data.topRows.size(); //... } } -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.data.sections.size(); } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { switch (self.data.sections[indexPath.section]) { case Top: switch (self.data.topRows[indexPath.row]) { case Row: //.. 35
  24. But what if I don’t need a dynamic array? 37

    static NSArray<NSString *> * categories = @[@"Cafe", @"Shop", @"Mall"];
  25. But what if I don’t need a dynamic array? 38

    static NSArray<NSString *> * categories = @[@"Cafe", @"Shop", @"Mall"];
  26. But what if I don’t need a dynamic array? 39

    static NSArray<NSString *> * categories = @[@"Cafe", @"Shop", @"Mall"]; + (NSArray<NSString *> *)colors { return @[@"Red", @"Green", @"Blue"]; } so
  27. Let’s rename it to .mm 41 static NSArray<NSString *> *

    categories = @[@"Cafe", @"Shop", @"Mall"]; // now compiles
  28. Let’s rename it to .mm 42 static NSArray<NSString *> *

    categories = @[@"Cafe", @"Shop", @"Mall"]; // now compiles But we can do it better!
  29. Let’s rename it to .mm 43 static NSArray<NSString *> *

    categories = @[@"Cafe", @"Shop", @"Mall"]; // now compiles But we can do it better! #include <array> static std::array<NSString *, 3> categories{@"Cafe", @"Shop", @"Mall"};
  30. std::array<NSString *, size> A. Implements static array B. Size must

    be known at compile time C.Zero overhead 46
  31. Other useful types A. std::unordered_map (like NSMutableDictionary) B. std::unordered_set (like

    NSMutableSet) C.std::list (doubled linked list) D.std::deque (similar to std::vector but you can also do emplace_front()) 50
  32. Other useful types A. std::unordered_map (like NSMutableDictionary) B. std::unordered_set (like

    NSMutableSet) C.std::list (doubled linked list) D.std::deque (similar to std::vector but you can also do emplace_front()) E. std::pair 51
  33. Other useful types A. std::unordered_map (like NSMutableDictionary) B. std::unordered_set (like

    NSMutableSet) C.std::list (doubled linked list) D.std::deque (similar to std::vector but you can also do emplace_front()) E. std::pair F. std::tuple 52
  34. Other useful types A. std::unordered_map (like NSMutableDictionary) B. std::unordered_set (like

    NSMutableSet) C.std::list (doubled linked list) D.std::deque (similar to std::vector but you can also do emplace_front()) E. std::pair F. std::tuple G.std::any 53
  35. Other useful types A. std::unordered_map (like NSMutableDictionary) B. std::unordered_set (like

    NSMutableSet) C.std::list (doubled linked list) D.std::deque (similar to std::vector but you can also do emplace_front()) E. std::pair F. std::tuple G.std::any and so on… 54
  36. About type safety NSDictionary<NSString *, NSString *> * metadata; -

    (NSURL *)url { NSURL * u = metadata[@"url"]; if (u) { return u; } return [NSURL URLWithString:@"..."]; } 55
  37. About type safety NSDictionary<NSString *, NSString *> * metadata; -

    (NSURL *)url { NSURL * u = metadata[@"url"]; if (u) { return u; } return [NSURL URLWithString:@"..."]; } 56
  38. About type safety NSDictionary<NSString *, NSString *> * metadata; -

    (NSURL *)url { NSString * u = metadata[@"url"]; if (u) { return [NSURL URLWithString:u]; } return [NSURL URLWithString:@"..."]; } 57
  39. About type safety NSDictionary<NSString *, NSString *> * metadata; -

    (NSURL *)url { if (NSURL * url = metadata[@"url"]) { return url; } return [NSURL URLWithString:@"..."]; } 58
  40. About type safety NSDictionary<NSString *, NSString *> * metadata; -

    (NSURL *)url { if (NSURL * url = metadata[@"url"]) { return url; } return [NSURL URLWithString:@"..."]; } 59
  41. About type safety NSDictionary<NSString *, NSString *> * metadata; -

    (NSURL *)url { if (NSString * url = metadata[@"url"]) { return [NSURL URLWithString:url]; } return [NSURL URLWithString:@"..."]; } 60
  42. About type safety NSDictionary<NSString *, NSString *> * metadata; -

    (NSURL *)url { if (auto const url = metadata[@"url"]) { return [NSURL URLWithString:url]; } return [NSURL URLWithString:@"..."]; } 61
  43. Get Swifty with if-let #define let auto const #define var

    auto NSDictionary<NSString *, NSString *> * metadata; - (NSURL *)url { if (let url = metadata[@"url"]) { return [NSURL URLWithString:url]; } return [NSURL URLWithString:@"..."]; } 62
  44. auto NSData * data = [[NSData alloc] init]; NSString *

    string = @"str"; NSArray * array = @[]; NSDictionary * dictionary = @{}; 63
  45. auto NSData * data = [[NSData alloc] init]; NSString *

    string = @"str"; NSArray * array = @[]; NSDictionary * dictionary = @{}; 64 Do u see redundancy?
  46. auto NSData * data = [[NSData alloc] init]; NSString *

    string = @"str"; NSArray * array = @[]; NSDictionary * dictionary = @{}; 65 Do u see redundancy? How about this, Elon Musk? auto data = [[NSData alloc] init]; auto string = @"str"; auto array = @[]; auto dictionary = @{};
  47. auto NSString * (^block)(NSData * result, NSUInteger resultCode, NSDictionary *

    info) = ^NSString * (NSData * result, NSUInteger resultCode, NSDictionary * info) { // ... }; 66
  48. auto typedef NSString * (^Block)(NSData * result, NSUInteger resultCode, NSDictionary

    * info); Block block = ^NSString * (NSData * result, NSUInteger resultCode, NSDictionary * info) { // ... }; 67
  49. auto auto block = ^NSString * (NSData * result, NSUInteger

    resultCode, NSDictionary * info) { // ... }; 68
  50. About lambdas auto l = [](NSData * result, NSUInteger resultCode,

    NSDictionary * info) -> NSString * { // … }; 69
  51. About lambdas 70 [ capture ] ( params ) ->

    ret { body } [] - capture nothing [&] - capture all by reference [=] - capture all by making copy [&a] - capture a by reference [a] - capture a by copy *for additional info read about std::function auto l = [](NSData * result, NSUInteger resultCode, NSDictionary * info) -> NSString * { // … };
  52. Smart pointers auto del = [](CGContextRef ref) { CGContextRelease(ref); };

    std::unique_ptr<CGContext, decltype(del)> context{CGBitmapContextCreate(/ *...*/), del}; CGContextBeginPath(context.get()); //… CGContextClosePath(context.get()); CGContextFillPath(context.get()); 72 *for additional info read about std::unique_ptr, std::shared_ptr, std::weak_ptr
  53. Optionals static CGFloat const kInvalidCoordinate; - (CGPoint)point { if (pointIsValid)

    { return CGPointMake(x, y); } return {kInvalidCoordinate, kInvalidCoordinate}; } CGPoint point = self.point; if (point.x != kInvalidCoordinate && point.y != kInvalidCoordinate) { // do something with point } else { // handle invalid point } 73
  54. Optionals - (std::optional<CGPoint>)point { if (pointIsValid) { return {{x, y}};

    } return std::nullopt; // or just {} } if (auto const point = self.point) { // do something with point } else { // handle invalid point } CGPoint point = *self.point; // which is equal to point! 74
  55. Operator overloading CGPoint operator+(CGPoint const & pt, CGFloat value) {

    return {pt.x + value, pt.y + value}; } CGPoint operator+(CGPoint const & lhs, CGPoint const & rhs) { return {lhs.x + rhs.x, lhs.y + rhs.y}; } BOOL operator==(CGPoint const & lhs, CGPoint const & rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } 75
  56. Operator overloading CGPoint operator+(CGPoint const & pt, CGFloat value) {

    return {pt.x + value, pt.y + value}; } CGPoint operator+(CGPoint const & lhs, CGPoint const & rhs) { return {lhs.x + rhs.x, lhs.y + rhs.y}; } BOOL operator==(CGPoint const & lhs, CGPoint const & rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } CGSize operator+(CGSize const & sz, CGFloat value) { return {sz.width + value, sz.height + value}; } CGSize operator+(CGSize const & lhs, CGSize const & rhs) { return {lhs.width + rhs.width, lhs.height + rhs.height}; } 76
  57. 78

  58. 79

  59. Beware of A.Using C++ objects as a property B.Expensive copying

    C.Just try to be more careful and concentrated (or you will end like Neo) :) 82
  60. Where can I see good Objective-C++? A. MAPS.ME :) B.

    Objective-C Runtime C. Facebook Pop 86
  61. Where can I see good Objective-C++? A. MAPS.ME :) B.

    Objective-C Runtime C. Facebook Pop D. Facebook ComponentKit 87
  62. Where can I see good Objective-C++? A. MAPS.ME :) B.

    Objective-C Runtime C. Facebook Pop D. Facebook ComponentKit E. Realm 88
  63. Сonclusions A. Don’t be afraid of C++ B. Write more

    expressive code using Objective-C++ 90
  64. Сonclusions A. Don’t be afraid of C++ B. Write more

    expressive code using Objective-C++ C. Allow your compiler to help you better by renaming a file to .mm 91