motion-prime 0.4.3 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +6 -14
  2. data/CHANGELOG.md +5 -0
  3. data/Gemfile.lock +1 -1
  4. data/ROADMAP.md +9 -4
  5. data/doc/code/getting_started.rb +1 -2
  6. data/doc/code/screens.rb +54 -0
  7. data/doc/docs/getting_started.html +27 -6
  8. data/doc/docs/screens.html +166 -0
  9. data/files/Gemfile +1 -1
  10. data/files/Gemfile.lock +64 -0
  11. data/files/app/environment.rb +10 -0
  12. data/files/app/styles/sidebar.rb +3 -10
  13. data/files/resources/images/menu_button.png +0 -0
  14. data/files/resources/images/menu_button@2x.png +0 -0
  15. data/motion-prime/app_delegate.rb +19 -0
  16. data/motion-prime/core_ext/kernel.rb +4 -0
  17. data/motion-prime/elements/_content_text_mixin.rb +23 -11
  18. data/motion-prime/elements/_text_mixin.rb +54 -0
  19. data/motion-prime/elements/base_element.rb +19 -14
  20. data/motion-prime/elements/draw.rb +22 -1
  21. data/motion-prime/elements/draw/_draw_background_mixin.rb +28 -28
  22. data/motion-prime/elements/draw/image.rb +67 -48
  23. data/motion-prime/elements/draw/label.rb +59 -49
  24. data/motion-prime/elements/draw/view.rb +5 -3
  25. data/motion-prime/helpers/has_style_chain_builder.rb +1 -3
  26. data/motion-prime/models/association_collection.rb +8 -0
  27. data/motion-prime/models/finder.rb +8 -0
  28. data/motion-prime/mp.rb +4 -0
  29. data/motion-prime/screens/_navigation_mixin.rb +4 -0
  30. data/motion-prime/screens/base_screen.rb +7 -0
  31. data/motion-prime/screens/sidebar_container_screen.rb +2 -2
  32. data/motion-prime/sections/_cell_section_mixin.rb +44 -5
  33. data/motion-prime/sections/_draw_section_mixin.rb +120 -0
  34. data/motion-prime/sections/base_section.rb +29 -24
  35. data/motion-prime/sections/form.rb +48 -65
  36. data/motion-prime/sections/form/base_field_section.rb +2 -2
  37. data/motion-prime/sections/table.rb +143 -82
  38. data/motion-prime/sections/table/table_delegate.rb +48 -0
  39. data/motion-prime/styles/form.rb +1 -1
  40. data/motion-prime/support/mp_cell_with_section.rb +6 -2
  41. data/motion-prime/support/mp_view_with_section.rb +1 -1
  42. data/motion-prime/version.rb +1 -1
  43. data/motion-prime/views/_frame_calculator_mixin.rb +4 -8
  44. data/motion-prime/views/layout.rb +1 -0
  45. data/motion-prime/views/view_styler.rb +3 -12
  46. metadata +34 -26
  47. data/motion-prime/sections/_draw_mixin.rb +0 -66
@@ -1,16 +1,16 @@
1
1
  Prime::Styles.define :sidebar do
2
2
  style :screen,
3
- background_color: :clear
3
+ background_color: proc { Prime::Config.color.dark }
4
4
  style :table,
5
5
  top: 150,
6
6
  left: 0,
7
7
  width: 320,
8
8
  bottom: 0,
9
- background_color: :clear,
9
+ background_color: proc { Prime::Config.color.dark },
10
10
  separator_color: :clear
11
11
 
12
12
  style :table_cell,
13
- selection_style: UITableViewCellSelectionStyleNone
13
+ selection_style: :none
14
14
 
15
15
  style :action_title,
16
16
  text_color: :white,
@@ -20,11 +20,4 @@ Prime::Styles.define :sidebar do
20
20
  size_to_fit: true,
21
21
  left: 20,
22
22
  text_color: :white
23
-
24
- style :action_arrow,
25
- width: 9,
26
- height: 14,
27
- right: 150,
28
- top: 17,
29
- image: "images/sidebar/arrow.png"
30
23
  end
@@ -32,6 +32,7 @@ module MotionPrime
32
32
 
33
33
  # TODO: move to private methods
34
34
  def open_root_screen(screen)
35
+ close_current_screens
35
36
  screen.send(:on_screen_load) if screen.respond_to?(:on_screen_load)
36
37
  screen.wrap_in_navigation if screen.respond_to?(:wrap_in_navigation)
37
38
 
@@ -46,6 +47,7 @@ module MotionPrime
46
47
  # TODO: move to private methods
47
48
  def open_content_screen(screen)
48
49
  if sidebar?
50
+ close_current_screens
49
51
  sidebar_container.content_controller = screen
50
52
  else
51
53
  open_root_screen(screen)
@@ -83,7 +85,24 @@ module MotionPrime
83
85
  NSNotificationCenter.defaultCenter.postNotificationName(:on_current_user_reset, object: user_was)
84
86
  end
85
87
 
88
+ def close_screens(screens)
89
+ Array.wrap(screens).each { |screen| screen.on_destroy if screen.respond_to?(:on_destroy) }
90
+ end
91
+
86
92
  private
93
+ def close_current_screens
94
+ return unless self.window
95
+
96
+ screens = if sidebar? && sidebar_container.content_controller.is_a?(UINavigationController)
97
+ sidebar_container.content_controller.childViewControllers
98
+ elsif sidebar?
99
+ sidebar_container.content_controller
100
+ else
101
+ window.rootViewController
102
+ end
103
+ close_screens(screens)
104
+ end
105
+
87
106
  def create_tab_bar(screens)
88
107
  MotionPrime::TabBarController.new(screens)
89
108
  end
@@ -6,4 +6,8 @@ class Kernel
6
6
  def class_name_without_kvo
7
7
  self.class.name.gsub(/^NSKVONotifying_/, '')
8
8
  end
9
+
10
+ def weak_ref
11
+ WeakRef.new(self)
12
+ end
9
13
  end
@@ -1,5 +1,8 @@
1
+ motion_require './_text_mixin.rb'
1
2
  module MotionPrime
2
3
  module ElementContentTextMixin
4
+ include ElementTextMixin
5
+
3
6
  def content_text
4
7
  is_a?(ButtonElement) ? button_content_text : input_content_text
5
8
  end
@@ -8,6 +11,21 @@ module MotionPrime
8
11
  (is_a?(ButtonElement) ? button_content_font : input_content_font) || :system.uifont
9
12
  end
10
13
 
14
+ def content_attributed_text
15
+ if view.try(:is_a?, UITextView) && view.text.present?
16
+ text = view.attributedText
17
+ text += ' ' if text.to_s.end_with?("\n") # does not respect \n at the end by default
18
+ return text
19
+ end
20
+
21
+ options = {
22
+ text: content_text,
23
+ font: content_font,
24
+ line_spacing: computed_options[:line_spacing]
25
+ }
26
+ computed_options[:html].present? ? html_string(options) : attributed_string(options)
27
+ end
28
+
11
29
  def content_width
12
30
  min, max = computed_options[:min_width].to_f, computed_options[:max_width]
13
31
  return min if content_text.blank?
@@ -23,7 +41,7 @@ module MotionPrime
23
41
  def content_height
24
42
  min, max = computed_options[:min_height].to_f, computed_options[:max_height]
25
43
  return min if content_text.blank?
26
- rect = get_content_rect(computed_options[:width])
44
+ rect = get_content_rect(computed_options[:width] - content_padding_width)
27
45
  @content_height = [[rect.size.height.ceil, max].compact.min, min].max.ceil
28
46
  end
29
47
 
@@ -34,15 +52,9 @@ module MotionPrime
34
52
  private
35
53
  def get_content_rect(width)
36
54
  raise "Please set element width for content size calculation" unless width
37
- attributes = {NSFontAttributeName => content_font }
38
- if computed_options[:line_spacing]
39
- paragrahStyle = NSMutableParagraphStyle.alloc.init
40
- paragrahStyle.setLineSpacing(computed_options[:line_spacing])
41
- attributes[NSParagraphStyleAttributeName] = paragrahStyle
42
- end
43
- attributed_text = NSAttributedString.alloc.initWithString(content_text, attributes: attributes)
44
- attributed_text.boundingRectWithSize(
45
- [width, Float::MAX], options:NSStringDrawingUsesLineFragmentOrigin, context:nil
55
+
56
+ content_attributed_text.boundingRectWithSize(
57
+ [width, Float::MAX], options: NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine, context:nil
46
58
  )
47
59
  end
48
60
 
@@ -63,7 +75,7 @@ module MotionPrime
63
75
  end
64
76
 
65
77
  def input_value_text
66
- view && !is_a?(DrawElement) ? view.text : computed_options[:text]
78
+ view && !is_a?(DrawElement) ? view.text : (computed_options[:html] || computed_options[:text])
67
79
  end
68
80
 
69
81
  def input_placeholder_text
@@ -0,0 +1,54 @@
1
+ module MotionPrime
2
+ module ElementTextMixin
3
+ # Options
4
+ # text
5
+ # text_color
6
+ # font
7
+ # line_spacing
8
+ # text_alignment
9
+ # text_alignment_name
10
+ # line_break_mode
11
+ # underline (range)
12
+
13
+ def html_string(options)
14
+ styles = []
15
+ styles << "color: #{options[:text_color].hex};" if options[:text_color]
16
+ styles << "line-height: #{options[:line_spacing].to_f + options[:font].pointSize}px;"
17
+ styles << "font-family: '#{options[:font].familyName}';"
18
+ styles << "font-size: #{options[:font].pointSize}px;"
19
+ styles << "text-align: #{options[:text_alignment_name]};" if options[:text_alignment_name]
20
+
21
+ html_options = {
22
+ NSDocumentTypeDocumentAttribute => NSHTMLTextDocumentType,
23
+ NSCharacterEncodingDocumentAttribute => NSNumber.numberWithInt(NSUTF8StringEncoding)
24
+ }
25
+ # DTCoreTextFontDescriptor.setOverrideFontName(Prime::Config.font.light, forFontFamily: 'Calibri', bold: false, italic: false)
26
+ # DTCoreTextFontDescriptor.setOverrideFontName(Prime::Config.font.bold, forFontFamily: 'Calibri', bold: true, italic: false)
27
+ # DTCoreTextFontDescriptor.setOverrideFontName(Prime::Config.font.light_italic, forFontFamily: 'Calibri', bold: false, italic: true)
28
+ # DTCoreTextFontDescriptor.setOverrideFontName(Prime::Config.font.bold_italic, forFontFamily: 'Calibri', bold: true, italic: true)
29
+
30
+ text = "#{options[:text]}<style>* { #{styles.join} }</style>"
31
+ NSAttributedString.alloc.initWithData(text.dataUsingEncoding(NSString.defaultCStringEncoding), options: html_options, documentAttributes: nil, error: nil)
32
+ end
33
+
34
+ def attributed_string(options)
35
+ paragrahStyle = NSMutableParagraphStyle.alloc.init
36
+
37
+ paragrahStyle.setLineSpacing(options[:line_spacing]) if options[:line_spacing]
38
+ paragrahStyle.setAlignment(options[:text_alignment]) if options[:text_alignment]
39
+ paragrahStyle.setLineBreakMode(options[:line_break_mode]) if options[:line_break_mode]
40
+ attributes = {}
41
+ attributes[NSParagraphStyleAttributeName] = paragrahStyle
42
+ attributes[NSForegroundColorAttributeName] = options[:text_color]
43
+ attributes[NSFontAttributeName] = options[:font]
44
+
45
+ prepared_text = NSMutableAttributedString.alloc.initWithString(options[:text], attributes: attributes)
46
+ if underline_range = options[:underline]
47
+ # FIXME
48
+ # prepared_text = NSMutableAttributedString.alloc.initWithAttributedString(prepared_text)
49
+ # prepared_text.addAttributes({NSUnderlineStyleAttributeName => NSUnderlineStyleSingle}, range: underline_range)
50
+ end
51
+ prepared_text
52
+ end
53
+ end
54
+ end
@@ -21,12 +21,17 @@ module MotionPrime
21
21
  @options = options
22
22
  @screen = options[:screen]
23
23
  @section = options[:section]
24
+ @view_class = options[:view_class] || 'UIView'
24
25
  @name = options[:name]
25
26
  @block = options[:block]
26
- @view_class = options[:view_class] || 'UIView'
27
27
  @view_name = self.class_name_without_kvo.demodulize.underscore.gsub(/(_draw)?_element/, '')
28
28
  end
29
29
 
30
+ def dealloc
31
+ pp 'deallocating elemenet', self.name
32
+ super
33
+ end
34
+
30
35
  def render(options = {}, &block)
31
36
  run_callbacks :render do
32
37
  render!(&block)
@@ -46,6 +51,15 @@ module MotionPrime
46
51
  @computed_options
47
52
  end
48
53
 
54
+ def compute_options!
55
+ block_options = compute_block_options || {}
56
+ raw_options = self.options.except(:screen, :name, :block, :view_class).merge(block_options)
57
+ compute_style_options(raw_options)
58
+ raw_options = Styles.for(styles).merge(raw_options)
59
+ @computed_options = raw_options
60
+ normalize_options(@computed_options, section, %w[text placeholder font title_label padding padding_left padding_right min_width min_outer_width max_width max_outer_width width left right])
61
+ end
62
+
49
63
  def update_with_options(new_options = {})
50
64
  options.merge!(new_options)
51
65
  compute_options!
@@ -70,15 +84,6 @@ module MotionPrime
70
84
  end
71
85
 
72
86
  protected
73
- def compute_options!
74
- block_options = compute_block_options || {}
75
- raw_options = self.options.except(:screen, :name, :block, :view_class).merge(block_options)
76
- compute_style_options(raw_options)
77
- raw_options = Styles.for(styles).merge(raw_options)
78
-
79
- @computed_options = raw_options
80
- normalize_options(@computed_options, section, %w[text placeholder font title_label padding padding_left padding_right min_width min_outer_width max_width max_outer_width width left right])
81
- end
82
87
 
83
88
  # Compute options sent inside block, e.g.
84
89
  # element :button do
@@ -142,23 +147,23 @@ module MotionPrime
142
147
  # table element: categories_table_cell_icon, categories_table_title_icon
143
148
  @styles += build_styles_chain(base_styles[:specific], suffixes[:specific])
144
149
  end
145
- if section
150
+ if section && section.name.present? && name.present?
146
151
  # using for base sections
147
- @styles << [section.name, name].compact.join('_').to_sym
152
+ @styles << [section.name, name].join('_').to_sym
148
153
  end
149
154
  # custom style (from options or block options), using for TableViews as well
150
155
  custom_styles = style_sources.map do |source|
151
156
  normalize_object(source.delete(:styles), section)
152
157
  end.flatten
153
158
  @styles += custom_styles
154
- #puts @view_class.to_s + @styles.inspect, ''
159
+ # puts @view_class.to_s + @styles.inspect, ''
155
160
  end
156
161
 
157
162
  class << self
158
163
  def factory(type, options = {})
159
164
  element_class = class_factory("#{type}_element", true) || self
160
165
  view_class_name = camelize_factory("ui_#{type}")
161
-
166
+
162
167
  options.merge!(view_class: view_class_name)
163
168
  element_class.new(options)
164
169
  end
@@ -7,6 +7,19 @@ module MotionPrime
7
7
  include FrameCalculatorMixin
8
8
  include ElementContentPaddingMixin
9
9
 
10
+ def draw_options
11
+ options = computed_options
12
+ background_color = options[:background_color].try(:uicolor)
13
+ {
14
+ rect: CGRectMake(computed_left, computed_top, computed_outer_width, computed_outer_height),
15
+ background_color: background_color,
16
+ masks_to_bounds: options[:layer].try(:[], :masks_to_bounds) || options[:clips_to_bounds],
17
+ corner_radius: options[:layer].try(:[], :corner_radius).to_f,
18
+ border_width: options[:layer].try(:[], :border_width).to_f,
19
+ border_color: options[:layer].try(:[], :border_color).try(:uicolor) || background_color
20
+ }
21
+ end
22
+
10
23
  def render!; end
11
24
 
12
25
  def view
@@ -14,7 +27,7 @@ module MotionPrime
14
27
  end
15
28
 
16
29
  def computed_frame
17
- @computed_frame ||= calculate_frome_for(view.bounds, computed_options)
30
+ @computed_frame ||= calculate_frome_for(view.try(:bounds) || section.container_bounds, computed_options)
18
31
  end
19
32
 
20
33
  def default_padding_for(side)
@@ -61,8 +74,16 @@ module MotionPrime
61
74
  view.setNeedsDisplay
62
75
  end
63
76
 
77
+ def update_with_options(new_options = {})
78
+ options.merge!(new_options)
79
+ compute_options!
80
+ view.setNeedsDisplay
81
+ end
82
+
64
83
  private
65
84
  def reset_computed_values
85
+ @content_height = nil
86
+ @content_width = nil
66
87
  @computed_frame = nil
67
88
  end
68
89
 
@@ -1,35 +1,35 @@
1
1
  module MotionPrime
2
2
  module DrawBackgroundMixin
3
- def draw_background_in(draw_rect, options)
4
- bg_color = options[:background_color]
5
- border_radius = options[:layer].try(:[], :corner_radius)
6
- border_width = options[:layer].try(:[], :border_width).to_f
7
- border_color = options[:layer].try(:[], :border_color) || bg_color || :black
3
+ def draw_background_in_context(context = nil)
4
+ context ||= UIGraphicsGetCurrentContext()
5
+ options = draw_options
6
+ rect, background_color, border_width, border_color, corner_radius = options.slice(:rect, :background_color, :border_width, :border_color, :corner_radius).values
8
7
 
9
- if bg_color || border_width > 0
10
- inset = border_width > 0 ? (border_width - 1 )*0.5 : 0
11
- rect = CGRectInset(draw_rect, -inset, -inset)
12
- if border_radius
13
- bezierPath = UIBezierPath.bezierPathWithRoundedRect rect, cornerRadius: border_radius
14
- if border_width > 0
15
- bezierPath.lineWidth = border_width
16
- border_color.uicolor.setStroke
17
- bezierPath.stroke
18
- end
19
- if bg_color
20
- bg_color.uicolor.setFill
21
- bezierPath.fill
22
- end
23
- else
24
- context = UIGraphicsGetCurrentContext()
25
- if border_width > 0 && border_color
26
- CGContextSetLineWidth(context, border_width)
27
- CGContextSetStrokeColorWithColor(context, border_color.uicolor.cgcolor)
28
- CGContextStrokeRect(context, rect)
29
- end
30
- CGContextSetFillColorWithColor(context, bg_color.uicolor.cgcolor) if bg_color
31
- CGContextFillRect(context, rect) if bg_color
8
+ return unless background_color || border_width > 0
9
+
10
+ inset = border_width > 0 ? (border_width - 1 )*0.5 : 0
11
+ rect = CGRectInset(rect, -inset, -inset)
12
+ if corner_radius > 0
13
+ bezierPath = UIBezierPath.bezierPathWithRoundedRect rect, cornerRadius: corner_radius
14
+ UIGraphicsPushContext(context)
15
+ if border_width > 0
16
+ bezierPath.lineWidth = border_width
17
+ border_color.setStroke
18
+ bezierPath.stroke
19
+ end
20
+ if background_color
21
+ background_color.setFill
22
+ bezierPath.fill
23
+ end
24
+ UIGraphicsPopContext()
25
+ else
26
+ if border_width > 0 && border_color
27
+ CGContextSetLineWidth(context, border_width)
28
+ CGContextSetStrokeColorWithColor(context, border_color.uicolor.cgcolor)
29
+ CGContextStrokeRect(context, rect)
32
30
  end
31
+ CGContextSetFillColorWithColor(context, background_color.uicolor.cgcolor) if background_color
32
+ CGContextFillRect(context, rect) if background_color
33
33
  end
34
34
  end
35
35
  end
@@ -4,67 +4,86 @@ module MotionPrime
4
4
  include DrawBackgroundMixin
5
5
  attr_accessor :image_data
6
6
 
7
+ def draw_options
8
+ image = image_data || computed_options[:image]
9
+ image ||= computed_options[:default] if computed_options[:url]
10
+
11
+ # already initialized image or image from resources or default image
12
+ super.merge({image: image.try(:uiimage)})
13
+ end
14
+
7
15
  def draw_in(rect)
8
16
  return if computed_options[:hidden]
9
- options = computed_options
10
- image_rect = CGRectMake(
11
- computed_left,
12
- computed_top,
13
- computed_width,
14
- computed_height
15
- )
16
17
 
17
- image_rect = CGRectInset(image_rect, -0.5, -0.5)
18
- border_width = options[:layer].try(:[], :border_width).to_f
18
+ draw_background_in_context(UIGraphicsGetCurrentContext())
19
+ computed_options[:draw_in_rect] ? draw_in_context(UIGraphicsGetCurrentContext()) : draw_with_layer
20
+ load_image
21
+ end
19
22
 
20
- draw_background_in(image_rect, options)
23
+ def draw_in_context(context)
24
+ return if computed_options[:hidden]
21
25
 
22
- # draw already initialized image
23
- if image_data
24
- draw_with_layer(image_data, image_rect)
25
- # draw image from resources
26
- elsif computed_options[:image]
27
- self.image_data = computed_options[:image].uiimage
28
- draw_with_layer(image_data, image_rect)
29
- # show default image and download image from url
30
- elsif computed_options[:url]
31
- if computed_options[:default]
32
- self.image_data = computed_options[:default].uiimage
33
- draw_with_layer(image_data, image_rect)
34
- end
35
- manager = SDWebImageManager.sharedManager
36
- manager.downloadWithURL(computed_options[:url],
37
- options: 0,
38
- progress: lambda{ |r_size, e_size| },
39
- completed: lambda{ |image, error, type, finished|
40
- if image
41
- self.image_data = image
42
- if type == SDImageCacheTypeNone || type == SDImageCacheTypeDisk
43
- # if it's first call, we should redraw view, because it's async
44
- section.container_view.setNeedsDisplay
45
- else
46
- # if it's second call, we should just draw image
47
- draw_with_layer(image_data, image_rect)
48
- end
49
- end
50
- } )
26
+ draw_background_in_context(context)
27
+ options = draw_options
28
+ return unless image = options[:image]
29
+
30
+ border_width = options[:border_width]
31
+ inset = border_width > 0 ? (border_width - 1 ).abs*0.5 : 0
32
+ rect = CGRectInset(options[:rect], inset, inset)
33
+ radius = options[:corner_radius].to_f if options[:corner_radius] && options[:masks_to_bounds]
34
+
35
+ UIGraphicsPushContext(context)
36
+ if radius
37
+ CGContextBeginPath(context)
38
+ CGContextAddArc(context, rect.origin.x + rect.size.width/2, rect.origin.y + rect.size.height/2, radius, 0, 2*Math::PI, 0) # FIXME
39
+ CGContextClosePath(context)
40
+ CGContextSaveGState(context)
41
+ CGContextClip(context)
42
+ image.drawInRect(rect)
43
+ CGContextRestoreGState(context)
44
+ else
45
+ image.drawInRect(rect)
51
46
  end
47
+ UIGraphicsPopContext()
52
48
  end
53
49
 
54
- def draw_with_layer(image, rect)
50
+ def draw_with_layer
51
+ options = draw_options
52
+ return unless image = options[:image]
53
+ rect = options[:rect]
54
+ radius = options[:corner_radius].to_f if options[:corner_radius] && options[:masks_to_bounds]
55
+
55
56
  layer = CALayer.layer
56
57
  layer.contents = image.CGImage
57
58
  layer.frame = rect
58
59
  layer.bounds = rect
59
- if computed_options[:layer]
60
- layer.masksToBounds = computed_options[:layer][:masks_to_bounds] || computed_options[:clips_to_bounds]
61
- if radius = computed_options[:layer][:corner_radius]
62
- k = image.size.width / rect.size.width
63
- radius = radius * k
64
- layer.cornerRadius = radius
65
- end
60
+
61
+ layer.masksToBounds = options[:masks_to_bounds]
62
+ layer.cornerRadius = radius if radius
63
+
64
+ view.layer.addSublayer(layer)
65
+ end
66
+
67
+ def load_image
68
+ return if image_data || !computed_options[:url]
69
+ BW::Reactor.schedule do
70
+ manager = SDWebImageManager.sharedManager
71
+ manager.downloadWithURL(computed_options[:url],
72
+ options: 0,
73
+ progress: lambda{ |r_size, e_size| },
74
+ completed: lambda{ |image, error, type, finished|
75
+ break unless image && section
76
+ self.image_data = image
77
+
78
+ section.cached_draw_image = nil
79
+ if section.respond_to?(:cell_name)
80
+ section.pending_display!
81
+ else
82
+ self.view.performSelectorOnMainThread :setNeedsDisplay, withObject: nil, waitUntilDone: false
83
+ end
84
+ }
85
+ )
66
86
  end
67
- view.layer.addSublayer layer
68
87
  end
69
88
  end
70
89
  end