Showing posts with label xcode. Show all posts
Showing posts with label xcode. Show all posts

Thursday, December 08, 2016

Operator overloading in Swift

After years of having to write [@"bar" isEqualToString:@"foo"] I’m delighted that in swift we can simplify things and just write “bar” == “foo”.

However there is an important thing to note. Swift will match the overloaded operator to function that takes the same arguments. Simple.

So if I follow the example set by the equatable protocol, and wanted to compare two NSObject subclasses, I could create a function that looks something like:

And this would work everywhere as expected and print “hello world” …

Well, no. Remember I said exactly the same arguments.

So, If I was to change the optionality of one of the variables:

let a = Object(name: "foo")
var b:Object?

b = Object(name: "foo")

Our custom equality function will no longer be called, as it only expects unwrapped values. This means that the equality would fail, as the pointers do not match, and the test would fail and doSomethingWhenTheStringChanges would never be called.

The solution is fairly simple, you need to create a version of the overridden operator that accepts optionals, but again remember that the compiler is trying to match parameters, so you also need to cover the case where you have one/two unwrapped parameters.

What will now happen, is that when we have unwrapped parameters it will go directly to the first overridden operator, while optionals will use the second. We use the guard to ensure that we can unwrap both, and then do a pointer equality check which will return the correct result if one, or both are nil.

What makes this behaviour particularly “special” is that it will only happen with NSObject subclasses. When using doing the same thing with a pure Swift class, if you are missing the optional variation of the overridden operator the compiler will require you to explicitly unwrap the variable.

Ultimately I think the best way to avoid this mess is to just do things the old fashioned way and override isEqual: in your subclass.

It should also be noted that Xcode correctly syntax highlights the operator depending on whether you will use NSObject’s version of isEqual: or your own at runtime, but there is no warning.

Monday, January 11, 2016

Taking back disk space from Xcode

I have 256 GB SSD in my Macbook Pro, I have no external disks, and no cloud storage other than a Dropbox's free tier. So I think it's fair to say that I'm not a data hoarder. I live my digital life, much like I live my real life, lean and light.

In the last few months I've been constantly hovering around ~8GB of available space, and more recently I've opened my Macbook to messages of "No available disk space". Considering that I dilligently manage my storage I've been a little confused as to why this is the case.

After digging around a little, I discovered that the ~/Library/Developer folder is weighing in at 35.75GB, thats 13% of my disk space!

Digging a little deeper, ~/Library/Developer/Xcode/iOS DeviceSupport/ contains the symbols for every iOS version that you've connected to your machine. If you are like me, and have been doing development for a while, you'll probably have a few, I had 12, going as far back as 7.1.2. They range in size from 600MB, all the way upto 3.36 GB. For my development needs I only need the last two versions; 9.2 & 8.4.1. Removing the unused symbols, as well some dervived data from some old projects helped me recover around 13GB.

If you've installed Xcode Betas you may have had the issue where you have duplicate simulators, sometimes even 3 copies. Each simulator is usually 1GB+ so removing excess ones can save you some additional space. On the advice of this stackoverflow post I installed the snapshot tool, which is part of the fastlane toolkit. It has a handy command called "reset_simulators" which will remove all the simulators, and recreate only the simulators for the current primary SDK you have installed.

The above tips helped me recover 22 GB just from Xcode.


Thursday, October 18, 2012

Drawing UIImage's with blocks

I have a slight love affair with Quartz's drawing routines. I don't know what it is about them, but there is something I love about stroking rects and filling paths. It's like OpenGL for stupid people.

Anyways, during my love affair I got bit annoyed at having to subclass UIView every time i wanted to make a quick sprite, or overlay a one image on top of another.

CALayer's a are awesome and everything, but i still need to subclass UIView unless i want a bunch of layout mess every where.

So I thought wouldn't it be cool to be able to create UIImage's quickly and then just throw them into a CALayers or UIImageView's and worry about the rest later.
The above does just that, you give it a canvas size or more informally the size of the UIImage that you wish to generate.

It will create the CGBitmapContext with a RGB colorspace, and then you can draw to your hearts content.

You can treat the block almost like a you would drawRect. I say almost because it's not inserted into the graphics context stack, so some of the helper methods like [[UIColor blackColor] setFill] will not work, and you'll have to learn how to do it the 'proper way' (CGColorSetFillColor()). Just consider it a general rule, that if it renders something and doesn't take a CGContextRef you need an alternative method to use it inside this block.

Saturday, July 30, 2011

Auto incrementing version numbers in Xcode

Over the last month or so i've had to kick out a lot of betas for a project. Seeing as i use the fantastic Test Flight. I have to change the version number before i upload each build otherwise Test Flight will overwrite an existing build which is the last thing that we want.

I don't think anyone actually enjoys editing a plists, whether its in Xcode plist editor or the down and dirty XML. So has a result it was the perfect opportunity to get familiar with xcode's build process, and how to tie external scripts into it.

I use 3 segment version numbers (1.1.1), where the first digit is the major version, second digit is the minor version, and the 3rd digit is the build. For the benefit of the team, i wanted to have the latest commit hash in the build number so that people could quickly reference it and know whats going on.

With some direction from this post by Duane Sibilly i was able to hack together the below.

Tuesday, April 12, 2011

Animating a series of images with CALayer

So you want a to animate a series of images, flip book style. While it is true you can use UIImageView, everyone knows that is for wimps. Real men (& ladies ;) ) use CALayer (like a boss)...

But how? Well you might have some how got in your head that CALayer's contents property supports a NSArray of CGImages. Well this is not the answer, remember that the contents property takes an 'id'as a argument so it supports virtually everything under the sun and then some. Hell, if you felt like making crazy things happen you could just throw a NSData object in there.

Anyways, the actual solution is to use a CAKeyFrameAnimation, to manage the rotation of your images, control the frame rate, and ultimately the duration.

Well all is said and done it should look at this

Sunday, April 10, 2011

Drawing text with a Gradient

Problem

You want to draw (unicode) text with filled with a gradient.

Solution

Since my middle name is now "Core Graphics", let me help you out. It's actually pretty simple. Create your desired gradient in a your image editor of choice, and save it as a PNG. Import it into your project and then ...

Yep folks thats it. Now if you find that your gradient is slightly out of place, you can use CGContextSetPatternPhase to help. You of course would use this before your drawing statement. The docs say:

The pattern phase is a translation that Quartz applies prior to drawing a pattern in the context. The pattern phase is part of the graphics state of a context, and the default pattern phase is (0,0). Setting the pattern phase has the effect of temporarily changing the pattern matrix of any pattern you draw. For example, setting the context’s pattern phase to (2,3) has the effect of moving the start of pattern cell tiling to the point (2,3) in default user space.

So when all is said and done you get this lovely effect

text drawn with a gradient Best of all this effect works all the back to iOS 2.0!

Saturday, April 02, 2011

Problem: Symbolicate won't ... um symbolicate.

Long live Crash reports, Crash reports are dead. We all love em right, couldn't live without them. But what happens when crash reports go bad. Sadly this isn't a lead up to a blockbuster movie but in fact a real life issue.

As much as a i love Xcode 4, (and i really love it) it swallows errors that symbolicatecrash script spits out. This caused me to send loads of time trying to fix an issue that i knew nothing about.

Well here's the solution. 

1. Do a project clean in Xcode (cmd+shift+K)
2. Delete the entire 'PROJECT/build' directory
3. Go to ~/Library/Application Support/iPhone Simulator/VERSION/Applications/UUID and delete each folder that contains your application name. Be sure to do so for each Version of the SDK.

And then attempt to symbolicate your reports.

I'm led to believe that some genius (who i'll target at WWDC and buy him/her a beer) thought it would be a great idea to use Spotlight to find dSYM files. Sadly i don't believe they thought (or could) apply any sort of search order, leading to spotlight returning random binaries. (When good ideas go wrong).

FYI. If your a member of the Xcode Team, i genuinely appreciate all the work that you folks put into 4.x.  

Friday, January 14, 2011

OpenGL Docs

I was about to dabble with OpenGL in recently, when i made a horrific discovery.


Happy Friday :D