SlideShare une entreprise Scribd logo
1  sur  57
Télécharger pour lire hors ligne
Fake It ’Til You Make It:
Tips and Tricks for Improving
  Interface Responsiveness
     Jonathan Saggau (@jonmarimba)
            Sounds broken inc
Da book
The dude
“Speed is money. How much do you want to spend?”

                          - Old auto racing adage
“Speed is developer time. How much do you have left to
                 spend before release?”

Recall the keynote: "Good cooking takes time. If you are made to wait, it is to
                     serve you better, and to please you."
“Speed is developer time. How much do you have left to
                 spend before release?”

Recall the keynote: "Good cooking takes time. If you are made to wait, it is to
                     serve you better, and to please you."




Yup. This is the car my
dad drives. 2009 Ford
Shelby GT-500. He is,
  so far, still with us.
“death by 1,000 paper cuts”

Displaying Large Amounts of Data Efficiently
The inspiration
The inspiration
(UIWebView is teh suck)
The inspiration
                     (UIWebView is teh suck*)




*Actually, it’s pretty cool. It just doesn’t always stand up under heavy usage.
The inspiration
(UIWebView is teh suck*)
Demo project:
BigViewThing.app
Derived from this sweet sample code from a WWDC
                 scrollview session:

http://developer.apple.com/iphone/library/samplecode/
              ScrollViewSuite/index.html
Demo
or... Julia Child impression
Demo
      or... Julia Child impression



 This might stink like that
      fish over there.
I swear that’s on purpose.
!

I’m doing everything the dumb, slow way.

TODO: Replace this with Instruments run
 TODO: Add a note that shark is dead.
Drawing UI in a background thread.




                                     !
Drawing UI in a background thread.


   Danger, Will Robinson! UIKit is not thread-safe. Try to draw to
   screen from another thread, and bad things might happen. Ugly
  things are almost guaranteed to happen.You can, however, draw
 your images into off-screen buffers (cgContexts work here) and
 then grab the pixels that you need to throw on the screen once
  the buffer is filled with data. There is nothing stopping you from
filling that data asynchronously and reading it from the main thread
                          in order to draw it.
Drawing UI in a background thread.



 1. The first time one of the BigViewPageView objects is asked to
draw, it will create a cgContext into which it will quickly draw a half
        opaque white background as a placeholder when the
                      BigViewPageView is inactive.
Drawing UI in a background thread.




II. It will draw whatever is currently in the off-screen context to the
                         screen in drawRect:
Drawing UI in a background thread.



III. It will generate an NSOperation that will fill a new cgContext in a
         background thread with the image data as it is needed.
Drawing UI in a background thread.


IV. When the NSOperation finishes, it will swap the new buffer in and
   call setNeedsDisplay on the view in the main thread so the view
  knows to draw the image data to screen. Drawing from a buffer is
                               fast(er).
Drawing UI in a background thread.
V. Any time the BigViewPageView is asked to draw, it pulls the image
   data from the current cgContext for drawing; it’s also filling new
 cgContexts in the background if you change the expected drawing
 size of the image through some bizarre action like zooming. Before
 the new buffer is ready, your image will stretch to fill and probably
pixelate for a moment while the NSOperation is preparing new data
                       much like UIWebView.
NSOperation and NSOperationQueue


NSOperationQueue and NSOperation remove much of the pain of
  multithreading. NSOperationQueue is a sort of thread pool that
maintains an array of pending NSOperation objects that it schedules
 to run in a background thread based on a number of factors from
 system hardware to system state to the relative priority of a given
                           NSOperation.
Playing with ^{blocks()}

“Cause it’s gonna be the future soon. And I won't always be this way. When the things that
make me weak and strange get engineered away.”
                                            —Lyrics for The Future Soon by Jonathan Coulton
We used to need a patched Compiler
         Plugin For Xcode
           and a runtime




                                     !


        Now we can target iOS 4.0*
You kids have it so easy.
Demo
I’m doing everything the dumb, slow way.
               In a background thread.
So the user can still use the app without freezing - up.
UIScrollView Zooming
Content
 Offset                   When zooming,
                       Images Get Stretched
                         (affine transform)
                          read: pixellated.

                              Blech.


     ContentView
UIScrollView       !
As the zoom scale changes, the UIScrollView does two things:
                                    by default

 1. It sets an affine transform on the view it is zooming to scale it up or down
without redrawing. It’s a “square” transform that maintains aspect ratio, so there
                                 is no distortion.

2. It resets its own contentSize, contentOffset, and zoomScale so as to hold the
 content in place relative to the point about which it is zooming (in the case of
              pinching, that point was halfway between your fingers).




We have to do some work to get the pixellated images to redraw at their new
                                  size.
Resetting Resolution in a UIScrollView after a Zoom
                    Operation




           Here is how I prefer to do this.
    It’s the only way I can get my head around.
Resetting Resolution in a UIScrollView after a Zoom
                    Operation

     1. Take a snapshot of the current (scaled)
          contentSize and contentOffset.
Resetting Resolution in a UIScrollView after a Zoom
                    Operation

     1. Take a snapshot of the current (scaled)
          contentSize and contentOffset.
    2. Take a snapshot of the current (unscaled)
  content view’s frame size; it’s being scaled by an
   affine transform, so its actual frame size is the
          same as it was before zooming.
Resetting Resolution in a UIScrollView after a Zoom
                    Operation

     1. Take a snapshot of the current (scaled)
          contentSize and contentOffset.
    2. Take a snapshot of the current (unscaled)
  content view’s frame size; it’s being scaled by an
   affine transform, so its actual frame size is the
          same as it was before zooming.
  3. Take a snapshot of the current minimum and
              maximum zoom scales.
Resetting Resolution in a UIScrollView after a Zoom
                    Operation
    2. Take a snapshot of the current (unscaled)
  content view’s frame size; it’s being scaled by an
   affine transform, so its actual frame size is the
          same as it was before zooming.
  3. Take a snapshot of the current minimum and
              maximum zoom scales.
 4. If your scroll view is its own delegate as it is in
  BigViewThing, call super to set the minimum and
 maximum zoom scales both to 1.0 because setting
 zoom on self will eventually call updateResolution
        again; infinite recursion is so last year.
Resetting Resolution in a UIScrollView after a Zoom
                    Operation
  3. Take a snapshot of the current minimum and
              maximum zoom scales.
 4. If your scroll view is its own delegate as it is in
  BigViewThing, call super to set the minimum and
 maximum zoom scales both to 1.0 because setting
 zoom on self will eventually call updateResolution
        again; infinite recursion is so last year.
  5. Set the current zoom scale to 1.0, which will
 rescale the content size internally back to the size
 of the content view, and reset the affine transform
            on the content view to unity.
Resetting Resolution in a UIScrollView after a Zoom
                      Operation
    5. Set the current zoom scale to 1.0, which will
   rescale the content size internally back to the size
   of the content view, and reset the affine transform
              on the content view to unity.
 6. Calculate new content offset by scaling the stretched/
zoomed offset you took a snapshot of in step 1. You want
the new content to appear in the same place in the scroll
                         view:
Resetting Resolution in a UIScrollView after a Zoom
                      Operation
 6. Calculate new content offset by scaling the stretched/
zoomed offset you took a snapshot of in step 1. You want
the new content to appear in the same place in the scroll
                          view:
    7. newContentOffset.x *= (oldContentSize.width /
                 contentViewSize.width);
    8. newContentOffset.y *= (oldContentSize.height /
                contentViewSize.height);
Resetting Resolution in a UIScrollView after a Zoom
                      Operation
   7. newContentOffset.x *= (oldContentSize.width /
              contentViewSize.width);
   8. newContentOffset.y *= (oldContentSize.height /
              contentViewSize.height);
 9. Divide the old minimum and maximum zoomScale by
the new zoom scale. This scales the original minimum and
   maximum zooms relative to the new content size. If
 minimum zoom were 1.0 and maximum zoom were 2.0,
when the user zooms to 2.0 and I reset, my new minimum
zoom would be .5, and my new maximum zoom would be
                          1.0.
Resetting Resolution in a UIScrollView after a Zoom
                      Operation
 9. Divide the old minimum and maximum zoomScale by
the new zoom scale. This scales the original minimum and
   maximum zooms relative to the new content size. If
 minimum zoom were 1.0 and maximum zoom were 2.0,
when the user zooms to 2.0 and I reset, my new minimum
zoom would be .5, and my new maximum zoom would be
                          1.0.

 10. Set the content view’s frame.size to the contentSize
             you took a snapshot of in step 1.
Resetting Resolution in a UIScrollView after a Zoom
                       Operation
 10. Set the content view’s frame.size to the contentSize
             you took a snapshot of in step 1.

    11. Set the scroll view’s contentSize to the scaled
contentSize you took a snapshot of in step 1. This stretches
 the overall size of the view to match the new zoom level
        (but without any affine transform applied).
Resetting Resolution in a UIScrollView after a Zoom
                       Operation
 10. Set the content view’s frame.size to the contentSize
             you took a snapshot of in step 1.

    11. Set the scroll view’s contentSize to the scaled
contentSize you took a snapshot of in step 1. This stretches
 the overall size of the view to match the new zoom level
        (but without any affine transform applied).

 12. Call the setNeedsLayout method on the scroll view.
This will cause layoutSubviews to be called where you can
   reset the content view’s internal subview geometry.
Demo
Why do it this way?
NSOperation Cancellation
                 In a category on NSOperationQueue:
      - (void)cancelOperationsFilteredByPredicate:(NSPredicate *)predicate;
      {
         NSArray *ops = [[self operations]
      filteredArrayUsingPredicate:predicate];
         for (NSOperation *op in ops)
         {
            if(![op isExecuting] && ![op isFinished] && ![op isCancelled])
            {
                [op cancel];
            }
         }
      }


We can use this to cancel old, not yet performed, redraws for when the user is zooming in and out rapidly.
Demo
You can find more information on NSPredicate in Apple’s
    Predicate Programming Guide available at http://
developer.apple.com/mac/library/documentation/Cocoa/
      Conceptual/Predicates/Articles/pUsing.html.
Caching tradeoffs

• Staleness (cached data is old data)
• User interface responsiveness (cached
  data is faster data)
• Memory usage (cached data takes up
  space somewhere)
Different types of iPhone apps
 require different strategies
    • Where does your data live?
     • On-disk read-only
     • On-disk read-write
     • Client-server read-only
     • Client-server read-write
Data Request Overhead
•   On-disk

•   Cloud data

•   How much data is optimal per request?

•   Parsing and memory overhead (why
    NSXMLDocument doesn't exist on the iPhone)

•   Limited memory workspace - working in chunks

•   How to distribute pauses in UI responsiveness as a
    result of requesting data to avoid giving the
    appearance of a "slow" application
If it might take a while (you did use Shark, right?)...

         Stay off the main thread. Please.
Further Reading
   http://github.com/landonf/block_samples/tree/master
      http://www.mikeash.com/?page=pyblog/friday-
                  qa-2008-12-26.html
http://cocoasamurai.blogspot.com/2009/09/guide-to-blocks-
               grand-central-dispatch.html
http://macresearch.org/cocoa-scientists-part-xxvii-getting-
                   closure-objective-c
            http://developer.apple.com/Cocoa/
                managingconcurrency.html.
Look for gogoDocs Google Docs
        reader for iPhone and iPad. It’s in an
            the app store in your pocket.
              (Pay for my flight, please)




jonathan@jonathansaggau.com
http://jonathansaggau.com/blog
       twit: @jonmarimba
Will Code for food.




                      jonathan@jonathansaggau.com
                      http://jonathansaggau.com/blog
                             twit: @jonmarimba


Nerds for hire // Hiring nerds // Working with Big Nerds
Recommended Reading
   http://github.com/landonf/block_samples/tree/master
      http://www.mikeash.com/?page=pyblog/friday-
                  qa-2008-12-26.html
http://cocoasamurai.blogspot.com/2009/09/guide-to-blocks-
               grand-central-dispatch.html
http://macresearch.org/cocoa-scientists-part-xxvii-getting-
                   closure-objective-c
            http://developer.apple.com/Cocoa/
                managingconcurrency.html.
Next up...
             Meed, um, me.
Apress authors gonna be right over there >

Contenu connexe

En vedette

interior design lectures - measure drawing building study
interior design lectures - measure drawing building study interior design lectures - measure drawing building study
interior design lectures - measure drawing building study designcube6
 
Interior design
Interior designInterior design
Interior designItsRyne
 
Interior design seminar presentation
Interior design seminar presentationInterior design seminar presentation
Interior design seminar presentationhighcraft
 
Architecture drawing presentation
Architecture drawing presentationArchitecture drawing presentation
Architecture drawing presentationCarlson Ko
 
What slide dimensions should you use for your presentations?
What slide dimensions should you use for your presentations?What slide dimensions should you use for your presentations?
What slide dimensions should you use for your presentations?Presentitude
 
Plan symbols
Plan symbolsPlan symbols
Plan symbolsgopaltry
 

En vedette (7)

interior design lectures - measure drawing building study
interior design lectures - measure drawing building study interior design lectures - measure drawing building study
interior design lectures - measure drawing building study
 
Interior design
Interior designInterior design
Interior design
 
Interior design seminar presentation
Interior design seminar presentationInterior design seminar presentation
Interior design seminar presentation
 
Plan, section, elevation revised
Plan, section, elevation revisedPlan, section, elevation revised
Plan, section, elevation revised
 
Architecture drawing presentation
Architecture drawing presentationArchitecture drawing presentation
Architecture drawing presentation
 
What slide dimensions should you use for your presentations?
What slide dimensions should you use for your presentations?What slide dimensions should you use for your presentations?
What slide dimensions should you use for your presentations?
 
Plan symbols
Plan symbolsPlan symbols
Plan symbols
 

Dernier

Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfSeasiaInfotech2
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 

Dernier (20)

Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdf
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 

103 Optimizing Data Caching for iPhone App Responsiveness

  • 1. Fake It ’Til You Make It: Tips and Tricks for Improving Interface Responsiveness Jonathan Saggau (@jonmarimba) Sounds broken inc
  • 4. “Speed is money. How much do you want to spend?” - Old auto racing adage
  • 5. “Speed is developer time. How much do you have left to spend before release?” Recall the keynote: "Good cooking takes time. If you are made to wait, it is to serve you better, and to please you."
  • 6. “Speed is developer time. How much do you have left to spend before release?” Recall the keynote: "Good cooking takes time. If you are made to wait, it is to serve you better, and to please you." Yup. This is the car my dad drives. 2009 Ford Shelby GT-500. He is, so far, still with us.
  • 7. “death by 1,000 paper cuts” Displaying Large Amounts of Data Efficiently
  • 10. The inspiration (UIWebView is teh suck*) *Actually, it’s pretty cool. It just doesn’t always stand up under heavy usage.
  • 13. Derived from this sweet sample code from a WWDC scrollview session: http://developer.apple.com/iphone/library/samplecode/ ScrollViewSuite/index.html
  • 15. Demo or... Julia Child impression This might stink like that fish over there. I swear that’s on purpose.
  • 16. ! I’m doing everything the dumb, slow way. TODO: Replace this with Instruments run TODO: Add a note that shark is dead.
  • 17. Drawing UI in a background thread. !
  • 18. Drawing UI in a background thread. Danger, Will Robinson! UIKit is not thread-safe. Try to draw to screen from another thread, and bad things might happen. Ugly things are almost guaranteed to happen.You can, however, draw your images into off-screen buffers (cgContexts work here) and then grab the pixels that you need to throw on the screen once the buffer is filled with data. There is nothing stopping you from filling that data asynchronously and reading it from the main thread in order to draw it.
  • 19. Drawing UI in a background thread. 1. The first time one of the BigViewPageView objects is asked to draw, it will create a cgContext into which it will quickly draw a half opaque white background as a placeholder when the BigViewPageView is inactive.
  • 20. Drawing UI in a background thread. II. It will draw whatever is currently in the off-screen context to the screen in drawRect:
  • 21. Drawing UI in a background thread. III. It will generate an NSOperation that will fill a new cgContext in a background thread with the image data as it is needed.
  • 22. Drawing UI in a background thread. IV. When the NSOperation finishes, it will swap the new buffer in and call setNeedsDisplay on the view in the main thread so the view knows to draw the image data to screen. Drawing from a buffer is fast(er).
  • 23. Drawing UI in a background thread. V. Any time the BigViewPageView is asked to draw, it pulls the image data from the current cgContext for drawing; it’s also filling new cgContexts in the background if you change the expected drawing size of the image through some bizarre action like zooming. Before the new buffer is ready, your image will stretch to fill and probably pixelate for a moment while the NSOperation is preparing new data much like UIWebView.
  • 24. NSOperation and NSOperationQueue NSOperationQueue and NSOperation remove much of the pain of multithreading. NSOperationQueue is a sort of thread pool that maintains an array of pending NSOperation objects that it schedules to run in a background thread based on a number of factors from system hardware to system state to the relative priority of a given NSOperation.
  • 25. Playing with ^{blocks()} “Cause it’s gonna be the future soon. And I won't always be this way. When the things that make me weak and strange get engineered away.” —Lyrics for The Future Soon by Jonathan Coulton
  • 26. We used to need a patched Compiler Plugin For Xcode and a runtime ! Now we can target iOS 4.0*
  • 27. You kids have it so easy.
  • 28. Demo
  • 29. I’m doing everything the dumb, slow way. In a background thread. So the user can still use the app without freezing - up.
  • 30. UIScrollView Zooming Content Offset When zooming, Images Get Stretched (affine transform) read: pixellated. Blech. ContentView UIScrollView !
  • 31. As the zoom scale changes, the UIScrollView does two things: by default 1. It sets an affine transform on the view it is zooming to scale it up or down without redrawing. It’s a “square” transform that maintains aspect ratio, so there is no distortion. 2. It resets its own contentSize, contentOffset, and zoomScale so as to hold the content in place relative to the point about which it is zooming (in the case of pinching, that point was halfway between your fingers). We have to do some work to get the pixellated images to redraw at their new size.
  • 32. Resetting Resolution in a UIScrollView after a Zoom Operation Here is how I prefer to do this. It’s the only way I can get my head around.
  • 33. Resetting Resolution in a UIScrollView after a Zoom Operation 1. Take a snapshot of the current (scaled) contentSize and contentOffset.
  • 34. Resetting Resolution in a UIScrollView after a Zoom Operation 1. Take a snapshot of the current (scaled) contentSize and contentOffset. 2. Take a snapshot of the current (unscaled) content view’s frame size; it’s being scaled by an affine transform, so its actual frame size is the same as it was before zooming.
  • 35. Resetting Resolution in a UIScrollView after a Zoom Operation 1. Take a snapshot of the current (scaled) contentSize and contentOffset. 2. Take a snapshot of the current (unscaled) content view’s frame size; it’s being scaled by an affine transform, so its actual frame size is the same as it was before zooming. 3. Take a snapshot of the current minimum and maximum zoom scales.
  • 36. Resetting Resolution in a UIScrollView after a Zoom Operation 2. Take a snapshot of the current (unscaled) content view’s frame size; it’s being scaled by an affine transform, so its actual frame size is the same as it was before zooming. 3. Take a snapshot of the current minimum and maximum zoom scales. 4. If your scroll view is its own delegate as it is in BigViewThing, call super to set the minimum and maximum zoom scales both to 1.0 because setting zoom on self will eventually call updateResolution again; infinite recursion is so last year.
  • 37. Resetting Resolution in a UIScrollView after a Zoom Operation 3. Take a snapshot of the current minimum and maximum zoom scales. 4. If your scroll view is its own delegate as it is in BigViewThing, call super to set the minimum and maximum zoom scales both to 1.0 because setting zoom on self will eventually call updateResolution again; infinite recursion is so last year. 5. Set the current zoom scale to 1.0, which will rescale the content size internally back to the size of the content view, and reset the affine transform on the content view to unity.
  • 38. Resetting Resolution in a UIScrollView after a Zoom Operation 5. Set the current zoom scale to 1.0, which will rescale the content size internally back to the size of the content view, and reset the affine transform on the content view to unity. 6. Calculate new content offset by scaling the stretched/ zoomed offset you took a snapshot of in step 1. You want the new content to appear in the same place in the scroll view:
  • 39. Resetting Resolution in a UIScrollView after a Zoom Operation 6. Calculate new content offset by scaling the stretched/ zoomed offset you took a snapshot of in step 1. You want the new content to appear in the same place in the scroll view: 7. newContentOffset.x *= (oldContentSize.width / contentViewSize.width); 8. newContentOffset.y *= (oldContentSize.height / contentViewSize.height);
  • 40. Resetting Resolution in a UIScrollView after a Zoom Operation 7. newContentOffset.x *= (oldContentSize.width / contentViewSize.width); 8. newContentOffset.y *= (oldContentSize.height / contentViewSize.height); 9. Divide the old minimum and maximum zoomScale by the new zoom scale. This scales the original minimum and maximum zooms relative to the new content size. If minimum zoom were 1.0 and maximum zoom were 2.0, when the user zooms to 2.0 and I reset, my new minimum zoom would be .5, and my new maximum zoom would be 1.0.
  • 41. Resetting Resolution in a UIScrollView after a Zoom Operation 9. Divide the old minimum and maximum zoomScale by the new zoom scale. This scales the original minimum and maximum zooms relative to the new content size. If minimum zoom were 1.0 and maximum zoom were 2.0, when the user zooms to 2.0 and I reset, my new minimum zoom would be .5, and my new maximum zoom would be 1.0. 10. Set the content view’s frame.size to the contentSize you took a snapshot of in step 1.
  • 42. Resetting Resolution in a UIScrollView after a Zoom Operation 10. Set the content view’s frame.size to the contentSize you took a snapshot of in step 1. 11. Set the scroll view’s contentSize to the scaled contentSize you took a snapshot of in step 1. This stretches the overall size of the view to match the new zoom level (but without any affine transform applied).
  • 43. Resetting Resolution in a UIScrollView after a Zoom Operation 10. Set the content view’s frame.size to the contentSize you took a snapshot of in step 1. 11. Set the scroll view’s contentSize to the scaled contentSize you took a snapshot of in step 1. This stretches the overall size of the view to match the new zoom level (but without any affine transform applied). 12. Call the setNeedsLayout method on the scroll view. This will cause layoutSubviews to be called where you can reset the content view’s internal subview geometry.
  • 44. Demo
  • 45. Why do it this way?
  • 46. NSOperation Cancellation In a category on NSOperationQueue: - (void)cancelOperationsFilteredByPredicate:(NSPredicate *)predicate; { NSArray *ops = [[self operations] filteredArrayUsingPredicate:predicate]; for (NSOperation *op in ops) { if(![op isExecuting] && ![op isFinished] && ![op isCancelled]) { [op cancel]; } } } We can use this to cancel old, not yet performed, redraws for when the user is zooming in and out rapidly.
  • 47. Demo
  • 48. You can find more information on NSPredicate in Apple’s Predicate Programming Guide available at http:// developer.apple.com/mac/library/documentation/Cocoa/ Conceptual/Predicates/Articles/pUsing.html.
  • 49. Caching tradeoffs • Staleness (cached data is old data) • User interface responsiveness (cached data is faster data) • Memory usage (cached data takes up space somewhere)
  • 50. Different types of iPhone apps require different strategies • Where does your data live? • On-disk read-only • On-disk read-write • Client-server read-only • Client-server read-write
  • 51. Data Request Overhead • On-disk • Cloud data • How much data is optimal per request? • Parsing and memory overhead (why NSXMLDocument doesn't exist on the iPhone) • Limited memory workspace - working in chunks • How to distribute pauses in UI responsiveness as a result of requesting data to avoid giving the appearance of a "slow" application
  • 52. If it might take a while (you did use Shark, right?)... Stay off the main thread. Please.
  • 53. Further Reading http://github.com/landonf/block_samples/tree/master http://www.mikeash.com/?page=pyblog/friday- qa-2008-12-26.html http://cocoasamurai.blogspot.com/2009/09/guide-to-blocks- grand-central-dispatch.html http://macresearch.org/cocoa-scientists-part-xxvii-getting- closure-objective-c http://developer.apple.com/Cocoa/ managingconcurrency.html.
  • 54. Look for gogoDocs Google Docs reader for iPhone and iPad. It’s in an the app store in your pocket. (Pay for my flight, please) jonathan@jonathansaggau.com http://jonathansaggau.com/blog twit: @jonmarimba
  • 55. Will Code for food. jonathan@jonathansaggau.com http://jonathansaggau.com/blog twit: @jonmarimba Nerds for hire // Hiring nerds // Working with Big Nerds
  • 56. Recommended Reading http://github.com/landonf/block_samples/tree/master http://www.mikeash.com/?page=pyblog/friday- qa-2008-12-26.html http://cocoasamurai.blogspot.com/2009/09/guide-to-blocks- grand-central-dispatch.html http://macresearch.org/cocoa-scientists-part-xxvii-getting- closure-objective-c http://developer.apple.com/Cocoa/ managingconcurrency.html.
  • 57. Next up... Meed, um, me. Apress authors gonna be right over there >