XCTest self measureBlock modification? - xcode

It appears that XCtest "self measureBlock" is limited to milliseconds and 10 runs of the test code. Are there any ways to modify the behavior of measureBlock for more runs and/or nano or microsecond accuracy?

TL;DR
Apple provides a way to modify the behavior of measureBlock: by providing extra string constants but they don't support any string constants other than the default.
Long explanation
measureBlock calls the following function
- (void)measureMetrics:(NSArray *)metrics automaticallyStartMeasuring:(BOOL)automaticallyStartMeasuring withBlock:(void (^)(void))block;
//The implementation looks something like this (I can't say 100% but i'm pretty sure):
- (void)measureBlock:(void (^)(void))block {
NSArray<NSString *> *metrics = [[self class] defaultPerformanceMetrics];
[self measureMetrics:metrics automaticallyStartMeasure:YES withBlock:block];
}
defaultPerformanceMetrics is a class function that returns an array of strings.
From the Xcode source
"Subclasses can override this to change the behavior of
-measureBlock:"
Lovely, that sounds promising; we have customization behavior right? Well, they don't give you any strings to return. The default is XCTPerformanceMetric_WallClockTime ("com.apple.XCTPerformanceMetric_WallClockTime")
It turns out there aren't any string constants to return besides that one.
See the slides for WWDC 2014 Session 414 Testing in Xcode 6 (link).
I quote from page 158:
Currently supports one metric: XCTPerformanceMetric_WallClockTime
Nothing else has been added in Xcode 7 so it seems you're out of luck trying to modify measureBlock, sorry.

I've never found measureBlock: very useful. Check out Tidbits.xcodeproj/TidbitsTestBase/TBTestHelpers/comparePerformance https://github.com/tipbit/tidbits if you'd like to look at an alternative.

Related

Reflection Swift 2.0 XCode 7 beta 5

Apple has changed the Swift reflection in XCode 7 beta 5. The global reflect() function is gone, and you'll have to do this:
let mirror = Mirror(reflecting: object)
It gives more or less the same information in a nicer way (no more .1 og .2 for propertyname and value). But I can't find a way to explore if the mirrored item is an instance of a class.
The older implementation you could check the following:
reflectedProperty.1.objectIdentifier != nil || reflectedProperty.1.count > 0
But objectIdentifier seems to be gone and the count is always 2 regardless of type.
Help anyone?
Ok so I found a workaround. I was iterating over mirror.children.enumerate() which seemed to make all the properties of type String. Instead I dug into Apple preliminary documentation, and read that it could be a good idea to "upgrade" children to e.g. AnyRandomAccessCollection. Which made it possible to rely on the count of an objects children to determine if it's an object (after testing whether it's an array)
Currently I have a functioning Swift class to JSON Serializer working here on this gist if you are interested in the code:
https://gist.github.com/peheje/cc3618253d4f38ea4885
I am not sure if you are looking for this, but the output for the following is "Class"
mirror.displayStyle

Using termios in Swift

Now that we've reached Swift 2.0, I've decided to convert my, as yet unfinished, OS X app to Swift. Making progress but I've run into some issues with using termios and could use some clarification and advice.
The termios struct is treated as a struct in Swift, no surprise there, but what is surprising is that the array of control characters in the struct is now a tuple. I was expecting it to just be an array. As you might imagine it took me a while to figure this out. Working in a Playground if I do:
var settings:termios = termios()
print(settings)
then I get the correct details printed for the struct.
In Obj-C to set the control characters you would use, say,
cfmakeraw(&settings);
settings.c_cc[VMIN] = 1;
where VMIN is a #define equal to 16 in termios.h. In Swift I have to do
cfmakeraw(&settings)
settings.c_cc.16 = 1
which works, but is a bit more opaque. I would prefer to use something along the lines of
settings.c_cc.vim = 1
instead, but can't seem to find any documentation describing the Swift "version" of termios. Does anyone know if the tuple has pre-assigned names for it's elements, or if not, is there a way to assign names after the fact? Should I just create my own tuple with named elements and then assign it to settings.c_cc?
Interestingly, despite the fact that pre-processor directives are not supposed to work in Swift, if I do
print(VMIN)
print(VTIME)
then the correct values are printed and no compiler errors are produced. I'd be interested in any clarification or comments on that. Is it a bug?
The remaining issues have to do with further configuration of the termios.
The definition of cfsetspeed is given as
func cfsetspeed(_: UnsafeMutablePointer<termios>, _: speed_t) -> Int32
and speed_t is typedef'ed as an unsigned long. In Obj-C we'd do
cfsetspeed(&settings, B38400);
but since B38400 is a #define in termios.h we can no longer do that. Has Apple set up replacement global constants for things like this in Swift, and if so, can anyone tell me where they are documented. The alternative seems to be to just plug in the raw values and lose readability, or to create my own versions of the constants previously defined in termios.h. I'm happy to go that route if there isn't a better choice.
Let's start with your second problem, which is easier to solve.
B38400 is available in Swift, it just has the wrong type.
So you have to convert it explicitly:
var settings = termios()
cfsetspeed(&settings, speed_t(B38400))
Your first problem has no "nice" solution that I know of.
Fixed sized arrays are imported to Swift as tuples, and – as far as I know – you cannot address a tuple element with a variable.
However,Swift preserves the memory layout of structures imported from C, as
confirmed by Apple engineer Joe Groff:. Therefore you can take the address of the tuple and “rebind” it to a pointer to the element type:
var settings = termios()
withUnsafeMutablePointer(to: &settings.c_cc) { (tuplePtr) -> Void in
tuplePtr.withMemoryRebound(to: cc_t.self, capacity: MemoryLayout.size(ofValue: settings.c_cc)) {
$0[Int(VMIN)] = 1
}
}
(Code updated for Swift 4+.)

How to set the width of an NSTableColumn in Swift

I'd like to programmatically set the width of some NSTableColumns in code (so that I can restore the widths on startup), but I don't really know how to apply what's written in the docs
for column in table.tableColumns {
var w: CGFloat = 125
column.setWidth(w)
println("\(column.identifier!)") // this prints my identifiers, so I know these are my columns and not something else I'm not interested in
}
The error I get is as follows: '(#lvalue CGFloat) -> $T3' is not identical to 'CGFloat'
With just 125 as the argument to setWidth the error says '(IntegerLiteralConvertable) -> etc...'
Code completion in XCode shows four versions of setWidth() each of which take at least two arguments, and none with just the width which is all I care about. My guess is that the docs don't match XCode 6.1.1, perhaps? It suggests there's just a setWidth() method, but in real life I have to choose between four equally confusing versions.
One Quincey_Morris gave me this answer in the Apple developer forums (I hope this isn't a breach of Apple's terms and conditions). I had to cast column "as [NSTableColumn]" before the opening brace of my for loop before I could just call "column.width = 125".

How to force a raw value of 7 into a UIViewAnimationCurve enum?

The key UIKeyboardAnimationCurveUserInfoKey in the userInfo dictionary of a UIKeyboardWillShowNotification contains an Int with the value 7.
Now I need to pass this Int into UIView.setAnimationCurve(<here>). I tried to create the required UIViewAnimationCurve enum like this UIViewAnimationCurve(rawValue: 7). Because the raw value 7 is undocumented, the result is always nil.
It works fine this way in Objective-C. Any idea how to get this animation curve from the notification into a UIView animation using Swift?
Update:
As pointed out by Martin, this is no longer a problem since Xcode 6.3.
From the Xcode 6.3 Release Notes:
Imported NS_ENUM types with undocumented values, such as UIViewAnimationCurve, can now be converted from their raw integer values using the init(rawValue:) initializer without being reset to nil. Code that used unsafeBitCast as a workaround for this issue can be written to use the raw value initializer.
I think I figured it out, but I'm not sure if this is the way it's supposed to be done.
let animationCurve = unsafeBitCast(7, UIViewAnimationCurve.self)
UIView.setAnimationCurve(animationCurve)
Update: The solution contained in this question works as well.
var animationCurve = UIViewAnimationCurve.EaseInOut
NSNumber(integer: 7).getValue(&animationCurve)

Why doesn't com.canon.cr2-raw-image conform to public.camera-raw-image according to UTTypeConformsTo?

I am try to see whether a certain image is a RAW image file by getting the UTI for the file, then using UTTypeConformsTo() to see if the image's UTI conforms to "public.camera-raw-image", but when I try doing so, UTTypeConformsTo() returns false. Here is the code in question:
- (NSNumber*)bw_conformsToUTI:(NSString*)otherString
{
Boolean conformsBoolean = UTTypeConformsTo((CFStringRef)self, (CFStringRef)otherString);
NSNumber* conforms = [NSNumber numberWithBool:conformsBoolean];
return conforms;
}
(the method is written as a category on NSString, and the lines are split apart like that because I was making sure in the debugger that there wasn't anything funny going on with converting from a Boolean to a BOOL and losing bits; conformsBoolean definitely comes back as all 0 bits)
If self is "com.canon.cr2-raw-image" and otherString is "public.camera-raw-image", I would expect this to return YES, but instead it results in NO. I tracked down where the "com.canon.cr2-raw-image" UTI is defined, and found it in /System/Library/CoreServices/CoreTypes.bundle/Contents/Library/RawCameraTypes.bundle/Info.plist where it does indeed specify that com.canon.cr2-raw-image conforms directly to public.camera-raw-image. I did notice that this is declare as an imported UTI and not an exported UTI, but since my application does recognize the declaration (as evidenced that I got that string in the first place via UTTypeCreatePreferredIdentifierForTag()), I don't think that should make a difference.
Is there anything obviously wrong that I'm doing or misunderstanding here?

Resources