Tuesday, April 26, 2016

Expected size in MB of an AVAssetExportSession

Im doing an awful lot of work at the moment with AVMutableVideoCompositions, and AVAssetExportSessions.  When exporting a video using the latter, its clear that you can affect the size of the mixed video enormously depending on the preset that you use.  For a typical video of around 2 minutes in length, the exported asset can range from 5MB to 400MB in size depending on that setting.  So it would be useful to have an idea of just how big an export might be, right?

To that end, I did some investigation and exported lots of different sizes and varieties of videos.  I ended up with a very consistent ratio between the duration of the video composition, the export setting, and the resultant size in MB of the exported video.

The one really useful thing about this is - you can work out beforehand, whether or not the user is going to run out of disc space when doing an export session.

So the following method will give you an expected size in MB of an exported video composition, based on the supplied bits of info - duration and export session preset.  Its fairly self explanatory, but its been pretty accurate so far.  Hope it is of use to someone :


Wednesday, April 20, 2016

Adding an NSArray in Coredata

Just discovered how to add an NSArray property to Coredata.  I know I know, an NSSet is just fine and does everything you need, and you can convert it to NSArray if you need to.  But I just wanted to try this - I had a situation where I didnt need a whole new managed object class, I just wanted to store an array of NSNumbers.  Heres what you do :

First, add your property to the data model as usual, and make it a 'transformable' property (in my case the property is called actionRules) :

Then add the normal attribute to your coredata managed object header file (and here you can actually refer to it as an array)  :

And add the @dynamic to the main file :

Then some slightly more weird stuff.   You add an entirely separate @interface to the same header file, using the name of the new property, and setting it to NSValueTransformer (you literally put this after the @end of the normal interface) :


Finally, add this entirely new @implementation in the main file.  Before or after the other normal implementation is fine (obviously you need to change the 'ActionRules' for the name of your array) :

And thats it - you have an NSArray that you can use throughout your application as usual.  Obviously its not mutable, so to add properties, create a mutableCopy of it, change it as required, then set the property as this mutableArray.  Still, its quite handy I find, and theres the additional bonus of quickly organised indexing.





Tuesday, April 19, 2016

UIButton with animating colours - new public repo

I recently needed a flashing UIButton, specifically for a record button for a video recorder.  Theres a nice easy way to do animation of such things using UIView, eg :

Unfortunately, with a UIButton, this causes issues.  I found that the button would become slower to respond, and seem sluggish - it just doesnt seem to work well.  So I had to go back to an older method of animation, using a CAAnimation on the layer of the UIButton.

As it took a little fiddling to get this right, I thought I would share the class in a github repo.  Its here :
https://github.com/lukecsmith/LSAnimatingColourButton

And it now uses a CAAnimation that looks like this :


Any feedback or improvement requests welcome.



Monday, April 18, 2016

iOS UITableview - improving performance with AutomaticDimension

A significant improvement was made to UITableview and the process of calculated cell heights with autolayout, in iOS8. With the introduction of using AutomaticDimension for row height, you can now use proper autolayout for each cell, and you can have all sorts of dynamic stuff happening to the height of a cell, and the UITableView responds as you would hope.


There are various things to do to make this work, but this post is not about that, and you will find plenty of others that cover that well.

This is about the performance of your tableview, while using this technique.  Because I was finding my performance was not great - and I didn't know why.

The great advantage of a UITableView of course, is that only what you see on the screen is being created and managed by the view.  It looks like you have a big long table full of stuff, but you don't - its all being moved around with magical smoke and mirrors.

Now you would expect that only enough cells are being created at any one time - but you would be wrong.  What is happening when using this particular technique, is that the value you set for estimatedRowHeight is used to calculate how many cells are required (because the UITableView cannot know, until after drawing has taken place, how high a cell actually is, and therefore, how many cells are needed to fill the visible part of the table).

So imagine your tableview is 400 px high.  You have set estimatedRowHeight to 40.0.  This means that the UITableView will go and prepare (400 / 40 =) 10 cells to be shown on the screen.  Even if actually, after autolayout, it turned out we only needed 5 cells - still, it went and made those cells.

SO its this estimatedRowHeight value that can play a key part in the speed of your tableview.  If you set it to a high value, eg in this case, 100 px, then only 4 cells are built for the view.  If later the tableview realises that more cells are required, then more can be built as required.

But ultimately, it pays to be as accurate as you possibly can with this value for estimatedRowHeight.  In my case, my estimate was too low, and I was building way more cells that I ever needed.  So I was wasting valuable processor time, on the main thread of course, and the app was slowing down.


Unresponsive UIButton, and the OTHER enable button!

Just spent a couple of hours with the simplest of issues - a UIButton that was not responding to clicks.  This is almost the most frustrating kind of issue.  A seemingly really simple thing, and Ive been doing iOS for 5 years now, and must have implemented 1000 UIButtons succesfully.

There are several very common reasons why a UIButton can be unresponsive, such as : userInteractionEnabled is not set to YES (either in NIB or code).  Theres an invisible UIView of some kind above the button in the view hierarchy, and it is not passing on touches to objects below it.  Then theres more obscure ones such as : you have implemented an animating image on the button, and it is interfering with touches.  Yes - Ive had that issue too.

But Ive never before had this one.  Theres another tick box, in the storyboard's UIButton panel, in the 'Control' section.  Here you set the alignment of the text content - and just under there, a separate 3 booleans are titled : Selected, Enabled and Highlighted.

And my issue, after two hours of fiddling, turned out to be : that Enabled tick box must be ticked.

I have never come across that issue before.  I dont actually know why this is suddenley having an effect on my UIButton.  If anyone would care to enlighten me more about this (almost) hidden but essential little tick box, I am all ears!

Meanwhile, make sure this is ticked.


Social Network with Firebase 3 - Infinitely scrolling UITableView of Firebase Items

Ive already talked about the basics of a Firebase social network project , and adding posts in two other articles. Here I want to explain ...