iOS6
V205
UICollectionView

Screen Shot 2014-07-22 at 12.30.52

UICollectionViewCell

Screen Shot 2014-07-22 at 12.08.55

UICollectionViewLayout

UICollectionViewLayoutAttributes (some)
– Position
– Size
– Opacity
– zIndex
– Transform
– …

Customization of Layout
– Size
– line spacing
– Inter cell spacing
– Scrolling direction
– Header Footer size
– Section inset

Flowlayout
– Want single line -> play with insets

iOS6
V219
Supplementary views are data driven
Decoration views are layout driven -> independent from the data e.g: Background

UICollectionViewLayoutAttributes
Carries information from a Layout to a Collection view and gets supplied to all the views in the collection view. One instance per view. Attributes: center, size, frame, alpha, transform, zIndex (to indicate how cells are stacked on top of each other)

Layout that get information from the CollectionViewDelegate

– When a change is done in a layout, the layout gets invalidate via -invalidateLayout
– If you want to change a a property on the layout but you want it to be done with animation performBatchUpdates:completion: to begin updates and end updates on a TableView (CollectionView). E.g: Item size on the layout
– CoverFlow we want to change transforms the view which means changing layout attributes, respond to method shouldInvalidateForBoundsChange: Flowlayout implements this method on the rotation of the device

When implementing a CollectionView with custom Layout, think first if it can be solved by sublcassing UICollectinViewFlowLayout

– Customise and add new kinds of views (decoration view, etc)
– Tweak layout attributes: To transform, alpha, etc.
– Add new layout attributes. Subclassing UICollectionViewLayoutAttributes to add additional layout attributes. E.g: to adjust some visual property on the cell to depend on the column.
– Gesture support, gesture to a specific cell.
– Custom insert and delete animations

Fully customizing UICollectionViewLayout
UICollectionViewLayout is an abstract class that needs to be extended in order to create a custom layout

Required overrides
- collectionViewContentSize
tells the user scrollable area in the collection view, where the content is going to be layout
- layoutAttributesForElementsInRect:
called to ask how to lay things out returns an array of LayoutAttributes
- layoutAttributesForItemAtIndexPath:
Additionally sometimes this is required as well.
- layoutAttributesForSupplementaryViewOfKind:atIndexPath:
- layoutAttributesForDecorationViewOfKind:atIndexPath:

Order of operation to call those methods
– prepareLayout
to do upfront calcs for layout e.g: circle layout, etc.
collectinViewContentSize
layoutAttributesForElementsInRect
– others
invalidateLayout (like in coverflow, when sizes need to change. Says to collection view to start over again)
prepareLayout
– cycle continues

Strategy for great Work V237
What I take with me:
– A good engineer knows when to ask for help
– Knows where is your boundaries of knowledge
– Knows when to simplify
– when to copy/inspire in others work.
– Failure is ok
Phrases:
– Choose the simplest thing which might work
– Only show your best work don’t show the second best one
– Separate yourself from your work. Accept Criticism
– Work should explain itself

Design Information Flow (Truth, derived value, creation of new truth)

Think about of system in terms of how information is moving through. Considering first where is truth, who really knows that state.

Derived values
– It computes from inputs
– Needs to recompute when input change
Similar to a cache (not so sure about this one… cache doesn’t recompute with input changes?!)
let the model control the derived values
– Create new truth for updating model, creating a working copy of the original model. Once the “suggested” changes are validated, they are copied over to the original one.

Define Clear Responsibilities and use composition of smaller peaces that hold responsibility inside a bigger responsibility

Simplify with Immutability.
Mutability increases dependencies, object references moving through different controllers makes those controllers dependant on how they work with the object

Swift Structs are passed by value to functions, an implicit copy is made.

New in iOS8

new “AlertViews” and “ActionSheets” are presented using UIAlertController

UIAlertController *sheet = [UIAlertController alertControllerWithTitle:...];
[sheet addAction:[UIAlertAction actionWithtTitle:@"Reply"
style:UIAlertActionStyleDefault handler:^void (UIAlertAction *action){

}];

[self presentViewController:sheet ...];

New UISearchController

MyResultsController *resultsController = [[MyResultsController alloc] init];

UISearchController *searchController = [[UISearchController alloc] initWithSearchResultsController:resultsController];
searchController.searchResultsUpdater = resultsController;
self.tableView.tableHeaderView = searchController.searchBar;
self.definesPresentationContext = YES

self.definesPresentationContext
Tells the searchController where to present the resultsController. If this one is not defined, it searches the next closest parent controller that is defined as presentation context. In case no one is found, it uses the rootViewController

User Notifications:
Appear on screen are triggered by APN server or Local notifications. Can appear in lock screen, modal presentation (alert), in Notification Center and as a sound

Silent Notifications
From APN server app wakes up in background and can do any processing. Can even get information on the background from a server

New in iOS8

Notification Actions:
Different actions available on the notification: View Accept Maybe Decline Close

With UIMutableUserNotificationAction you respond to the action. If chosen UIUserNotificationActivationModeBackground only seconds are available to execute any code in background

destructive: if it should be shown blue or red

authentication required: if the notification is on the lock screen and the user needs to unlock.

Location Notification:
Notification when entered or exit a region

Define in info.plist NSLocationWhenInUseUsageDescription -> Any text explaining

NodeJS
PDF-JS (Mozilla) https://github.com/mozilla/pdf.js/
Really good one, generates HTML problem in my case that the information is not structured and I need to be able to parse it and extract information
PDF2JSON https://github.com/modesty/pdf2json

PHP
http://www.pdfparser.org/
http://www.tcpdf.org/doc/code/classTCPDF__PARSER.html

PYTHON
http://www.unixuser.org/~euske/python/pdfminer/
Really good one, generates HTML problem in my case that the information is not structured and I need to be able to parse it and extract information

JAVA
http://stackoverflow.com/questions/3203790/parsing-pdf-files-especially-with-tables-with-pdfbox
http://www.idrsolutions.com/java-code-examples-for-pdf-files/
Tabular data
https://github.com/jazzido/tabula
http://opendata.stackexchange.com/questions/127/extracting-tables-from-multiple-pdfs
Ruby? https://github.com/jazzido/tabula-extractor

Recopilation
https://github.com/okfn/ideas/issues/52

Project Technologies Setup:

Screen Shot 2014-03-12 at 10.17.02

Parts:
JS: CoffeeScript – ChaplinJS – BackboneJS – jQuery – Lodash – RequireJS
HTML: Handlebars
CSS: SASS – Compass
 

FAQ:

Why the heck can’t I store the user in Chaplin.mediator.user?

Error:

"Uncaught TypeError: Can't add property user, object is not extensible"

Googling I get this: Object.preventExtensions() but couldn’t find any reference to this method in Chaplin’s code. But I do see a method called

seal

What’s this? –> Google: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal

Attempting to add new properties to a non-extensible object will fail

Well… ok but I would have thought that Chaplin has already the user property set. No, it isn’t set.

I was following the Chaplin project example of: https://github.com/chaplinjs/facebook-example

And there I found the piece of code, inside facebook_application.coffee

initMediator: ->
# Create a user property
Chaplin.mediator.user = null
# Seal the mediator
Chaplin.mediator.seal()

 
 
 
————————————————————————————————
Chaplin seems to be routing twice – Controllers actions seems to be called twice when clicked on links
Navigation setup:

<ul>
  <li><a class="header-link new" href="new">New</a></li>
  <li><a class="header-link approved" href="approved">Approved</a></li>
</ul>

 

No listener is attached to a to control it internally in the Chaplin.View

On a latest change a Chaplin.Layout had been attached:

      options.title ?= @title
      options.routeLinks = false
      @layout = new Layout options

Inside the controller:

    new: (params) -&gt;
      console.log 'ListController::new'
    approved: (params) -&gt;
      console.log 'ListController::approved'

This ended up logging twice when clicked on any link on the navigation

'ListController::new'
'ListController::new'

Googling “Chaplin internal links” -> http://docs.chaplinjs.org/chaplin.layout.html at first sight a big fat bold “routeLinks”

Set to false to deactivate internal routing. If false, chaplin won’t route links at all.

Changed Layout instantiation to:

      options.title ?= @title
      options.routeLinks = false
      @layout = new Layout options

I haven’t decided yet to use Chaplin’s internal routing or not, but at least nothing is called twice 🙂

http://thecodinglove.com/post/56797907621/when-i-learn-a-new-framework

————————————————————————————————
Chaplin.mediator.suscribe handlers are called twice in a controller

  Chaplin.mediator.subscribe 'logout', @onLogout
  Chaplin.mediator.subscribe 'login', @onLogin

Handler

  onLogin: ->
    console.log("AuthController::onLogin")

Each time I logged in and out I got a saw the console calling the log several times.

Screen Shot 2014-03-13 at 13.07.49

Something was not disposed or unsuscribed correctly.

Test 1:
Unsuscribe on dispose of the controller:

   dispose:()->
      Chaplin.mediator.unsubscribe 'logout'
      Chaplin.mediator.unsubscribe 'login'
      super

Which works… but I had other controllers running with similar event suscription but those where working correctly. Difference? Adding the context on the suscription call:

Looking like this

  Chaplin.mediator.subscribe 'logout', @onLogout, @
  Chaplin.mediator.subscribe 'login', @onLogin, @

Might be obvious for most… wasn’t for me ^^

Ok, so I have a pretty heavy app that does a sync process with a webservice to get a complete content of the app. It is going to be an Enterprise app, view products, order products, etc. The complete sync process (only the first one) takes around 30-40 minutes, lots of images, lots of data… I was getting Memory warnings at the end of the sync, of course it had to be at the end of the sync…. I have various sync services running, to do a propper analysis I isolated just one sync process.

Begin:

So I am having a nice heap growth of 1.08MB. Trying to find out what that is. I am doing a sync process over and over again with a json file of 41KB and downloading 130 images, 39 between 5-8KB and 97 from 60-400KBS

Begin status – Heap Growth of 1.08MB on each

 

Screen Shot 2013-08-24 at 10.43.25

Following the highest percentage on the Call Trees view, I see many things but the first one I find strange is the 4.6% for getting the path to the document directory.

Screen Shot 2013-08-24 at 10.41.43
This is the evil code:

- (NSString *)pathInDocumentDirectory:(NSString *)fileName
{
NSArray *documentDirectories =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);

NSString *baseDocPath = [documentDirectories objectAtIndex:0];

// Append passed in file name to that directory, return it
return [baseDocPath stringByAppendingPathComponent:fileName];
}

I am going to try out saving the baseDocPath to an instance variable to see how this affects. Tried out code:

- (NSString *)pathInDocumentDirectory:(NSString *)fileName
{
if (baseDocPath == nil) {
NSArray *documentDirectories =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);

baseDocPath = [documentDirectories objectAtIndex:0];

}
return [baseDocPath stringByAppendingPathComponent:fileName];
}

–> Heap went down almost 100KB (1.08MB to 909KB)
Screen Shot 2013-08-24 at 10.43.25

The call tree below makes me think that the NSManagedObjectContext fetch request stores a cache. But I do reset the NSManagedObjectContext each time I begin a new Sync, I have also tried to reset it each time I finish a sync. But this doesn’t make any difference.

–> No result

Right now I am leaving the app open to see if at some point the memory flushes. Even a simulation of a memory warning doesn’t decrease the memory usage.

Trying to refreshObject:mergeChanges:YES once the image of the correspondant Entity is not needed any more

–> No result

Trying to refreshObject:mergeChanges:NO

Source: stackoverflow

Apple docs

Finally, Core Data does not by default keep strong references to managed objects (unless they have unsaved changes). If you have lots of objects in memory, you should determine the owning references. Managed objects maintain strong references to each other through relationships, which can easily create strong reference cycles. You can break cycles by re-faulting objects (again by using the refreshObject:mergeChanges: method of NSManagedObjectContext).

–> No result

[self.context setStalenessInterval:0.0];
Source apple developer:

Sets the maximum length of time that may have elapsed since the store previously fetched data before fulfilling a fault issues a new fetch rather than using the previously-fetched data.
The maximum length of time that may have elapsed since the store previously fetched data before fulfilling a fault issues a new fetch rather than using the previously-fetched data.
A negative value represents an infinite value; 0.0 represents “no staleness acceptable”.

–> This increased a little bit the memory

Following guidelines:
Source apple developer

NSString *predicateString = [NSString stringWithFormat @"employeeID == $EMPLOYEE_ID"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];

for (NSString *anID in employeeIDs) {
NSDictionary *variables = @{ @"EMPLOYEE_ID" : anID };
NSPredicate *localPredicate = [predicate predicateWithSubstitutionVariables:variables];

–> Won: 30KB
Screen Shot 2013-08-25 at 10.43.29

 

Replacing the stupid way to check the type of the incomming file:

previous:

//    NSMutableSet * matches = [NSMutableSet setWithSet:[CDAFileHelper videoFileTypeExtensions]];

//    NSPredicate *p = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",pathExtension];

//    [matches filterUsingPredicate:p];

–> Win: 175KB!!

 

Screen Shot 2013-08-25 at 11.00.25

 

Replaced calculating always the cache directory by storing it in a instance variable

return [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];

–> Win: 7-8KB

Screen Shot 2013-08-25 at 11.06.13

 

stupidly I was first serializing the json file to store it and then read it in again… removed the storing and just parsing the serialized json file:

–> Win: 72KB

Screen Shot 2013-08-25 at 11.40.36

 

Well… after many many hours…. an epifani… lesson learned

DO NOT ANALYZE HEAP GROWTH WITH ZOMBIES INSTRUMENTS!!!

It fucks everything up…

My new lovely heap growth after using Allocations instrument…

Screen Shot 2013-08-25 at 12.53.16

Apple tip on zombies instruments

Tip: The Zombies template causes memory growth because the zombies are never deallocated. So for iOS apps, use it with iOS Simulator rather than on the device itself. For the same reason, don’t use the Zombies template concurrently with the Leaks instrument.

Should this really be a “Tip” or a whole “Warning”!! I actually read it before… that is why I was using the simulator… but somehow I didn’t realize what the “causes memory growth” meant for my abandoned memory analysis

 

The memory issue was coming from somewhere else, acutally other Sync process. What helped me there, to not having memory warning issues, was to find the correct places, in specific batches, where to save the Core Data context.

– Avoid Capturing JSValues -> mantain a strong reference -> Prefer passing as arguments

– Avoid Captuing JSContexts -> mantain a strong reference to the Global object -> Use +[JSContext currentContext] inside of the blog

 

– JavaScriptCore uses garbage collection -> All references in JS are strong -> It doesn’t matter if you create reference cycles as the GC can handle them

– Memory management is mostly automatic -> JSValue keeps things alive for you as long as you use JSValue

– But attention to:

-> String JS values in Objective-C objects as instance variables -> Use JSManagedValue for that, it is a garbage collected reference.

JSManagedValue by itself  is a weak reference to a JavaScript value.

addMangedReference:withOwner turns JSManagedVAlue into a “garbage collected” reference -> if JS can find the owner it keeps the reference alive otherwise it is released

-> Adding JS fields to Objective-C objects, fields that are added in JS but are not present on the JSExport object

 

Threading:

JSVirtualMachin -> JSVM

– JSVM can contain multipe JSContexts

– you can have multiple JSVM with different multiple JSContexts

– JSValues can be passed between JSContext in the same JSVM

– but can not be passed between different JSVM -> each JSVM has its own heap and GC

– JavaScriptCore API is thread safe

– Locking granularity is at level of the VM, JS can be executed in different threads on the same VM but when one thread is executing JS no other thread can execute JS at the same time on the VM

– Use separate JSVM for concurrency