I uses ARC
NSAttributedString * arString = [self asSchedule:arTimes];
self.lblTimeLeft.attributedText = arString;
Not much information is given. It goes straight to main
int main(int argc, char *argv[])
{
#autoreleasepool {
//int retVal = UIApplicationMain(argc, argv, nil, nil);
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([newIsiKotaAppDelegate class]));
return retVal;
}
}
I manage to spot that the last code executed is this:
self.lblTimeLeft.attributedText = arString;
I provided additional code to test things out
NSAttributedString * arString = [self asSchedule:arTimes];
self.lblTimeLeft.attributedText = arString;
PO1(#"Hello World");
while(false);// Error happen after this code is executed
}
The code is part of the routine that provides UITableViewCell to display. So error happen after
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = indexPath.row;
NSDictionary * rowDictionary = _marManagedObjectArray [row];
BGCinemaScheduleCell * BCS = [[BGCinemaScheduleCell alloc]init];
BCS.dicCinemaDictionary =rowDictionary;
return BCS; //This is where the error happen
}
It seems that the NSAttributedString works fine till it's actually displayed or something.
The error seems to happen on
TAttributes::TAttributes(__CFDictionary const *)
The content of asSchedule is usual
-(NSAttributedString *) asSchedule:(NSArray *) arTimes
{
NSMutableArray * timeBefore = [NSMutableArray array];
NSMutableArray * timeAfter = [NSMutableArray array];
for (NSString * strTime in arTimes) {
NSDate * date = [NSDate dtWithCurrentDateAndProvidedTime: strTime];
NSTimeInterval dblInterval =[date timeIntervalSinceNow];
if (dblInterval>0)
{
[timeAfter addObject:strTime];
}
else{
[timeBefore addObject:strTime];
}
}
NSString * strTimeBefore = [timeBefore componentsJoinedByString:#" "];
NSString * strTimeAfter = [timeAfter componentsJoinedByString:#" "];
NSString *yourString = [NSString stringWithFormat:#"%# %#", strTimeBefore, strTimeAfter];
// start at the end of strTimeBefore and go the length of strTimeAfter
NSRange boldedRange = NSMakeRange([strTimeBefore length] + 1, [strTimeAfter length]);
NSString *boldFontName = [[UIFont boldSystemFontOfSize:12] fontName];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:yourString];
[attrString addAttribute:NSFontAttributeName value:boldFontName range:boldedRange];
PO1(NSStringFromRange(boldedRange));
PO1(#(attrString.length));
return attrString;
}
Update:
I changed self.lblTimeLeft.attributedText = arString; to self.lblTimeLeft.attributedText = arString.copy; to no avail.
I wonder if this could be the problem:
[attrString addAttribute:NSFontAttributeName value:boldFontName range:boldedRange];
I think the original sample use KCFont something instead of NSFontAttributeName
You were almost there:
I wonder if this could be the problem: [attrString addAttribute:NSFontAttributeName value:boldFontName range:boldedRange];
Your code says:
NSString *boldFontName = [[UIFont boldSystemFontOfSize:12] fontName];
...
[attrString addAttribute:NSFontAttributeName value:boldFontName range:boldedRange];
It should say:
UIFont *boldFont = [UIFont boldSystemFontOfSize:12];
...
[attrString addAttribute:NSFontAttributeName value:boldFont range:boldedRange];
According to Table 1 of the docs (link below) and my own app code, you should be passing an NSFont not a font name.
https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/AttributedStrings/Articles/standardAttributes.html#//apple_ref/doc/uid/TP40004903-SW2
Can't tell from the code whether your project uses ARC or not, but it looks like your asSchedule method returns a string with a refcount of 0. It's up to you to retain a reference to that string, either old-school using the retain keyword (probably a bad idea) or by assigning it to a property declared with the strong keyword (or retain, if pre-ARC).
The best tool for debugging this stuff is Instruments, using the Zombies inspection. If I am right that you are trying to use the string after its refcount hits 0 and the memory has been released, you'll see the history of refcount increments and decrements pretty clearly.
Try alloc and initing the Attributedstring and then assign it to the self.lblTimeLeft.attributedText
Related
Thanks in advance for taking your time out for reading and hoping to assist me. I am relatively new to coding and the current problem I am facing is;
I have built a sqlite3 database, with three columns which are respectively stored as; string, float and an int. When trying to read and represent the columns, I am having trouble in finding a method in order to represent the float and int values.
The three properties which are stores in the database are set as;
#property (nonatomic, strong) NSString *name;
#property (nonaomtic, strong) NSNumber *price;
#property (nonaomtic, strong) NSNumber *quantity;
I'm not sure if maybe changing the latter two properties into float and int would make a difference?
However, the main confusion for me lies in the following code I have made in order to call on the data base;
-(void)readDataFromDatabase{
[self.stock removeAllObjects];
sqlite3 *database;
if (sqlite_open([self.databasePath UTF8String], &database) == SQLITE_OK) {
char *sqlStatement = "select * from entries";
sqlite3_stmt *compiledStatement;
if (sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK){
while(sqlite3_step(compiledStatement) == SQLITE_ROW{
char *n = sqlite3_column_text(compiledStatement, 1);
char *p = sqlite3_column_int(compiledStatement, 2);
chat *q = sqlite3_column_int(compiledStatement, 3);
NSString *name = [NSString stringWithUTF8String:n];
NSNumber *price = [NSString stringWithUTF8String:p];
NSNumber *quantity = [NSString stringWithUTF8String:q];
Data *data = [[Data alloc] initWithData:name thePrice: price theQuantity:quantity];
[self.stock addObject:data];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
My common sense tells me the problem lies in this section;
NSString *name = [NSString stringWithUTF8String:n];
NSNumber *price = [NSString stringWithUTF8String:p];
NSNumber *quantity = [NSString stringWithUTF8String:q];
I'm not sure how I should approach the NSNumber? I'm aware the NSString stringWithUTF8String is not correct, but I don't know the equivalent for NSNumber.
I would really appreciate any insight and help on this matter.
Thank you!
You are on the right track with what you've mentioned for float and int. Float does not need to be referenced like NSString because it's size does not vary between 32-bit and 64-bit systems. If your integer is larger then I would recommened using NSInteger for that value:
char *n = sqlite3_column_text(compiledStatement, 1);
float p = sqlite3_column_text(compiledStatement, 2);
int q = sqlite3_column_text(compiledStatement, 3);
NSString *name = [NSString stringWithUTF8String:n];
float price = p;
NSInteger quantity = q;
Note: You don't the * for the float or int values, since they are not pointers.
You might even be able just to do (If you are already declaring the properties in your header):
name = [NSString stringWithUTF8String:sqlite3_column_text(compiledStatement, 1)];
price = sqlite3_column_text(compiledStatement, 2);
quantity = sqlite3_column_text(compiledStatement, 3);
To check the values you can use NSLog:
NSLog(#"%# %.02f %li", name, price, quantity);
For completeness sake, if you wanted to make the float and int into NSNumber:
NSString *name = [NSString stringWithUTF8String:n];
NSNumber *price = [NSNumber numberWithFloat:p];
NSNumber *quantity = [NSNumber numberWithInt:q];
With the properties in your header declared:
name = [NSString stringWithUTF8String:n];
value = [NSNumber numberWithFloat:p];
quantity = [NSNumber numberWithInt:q];
NSLog(#"%# %#.02f %#", name, price, quantity);
There are multiple ways to get your result, and that's what makes Objective-C quite flexible.
I am trying to use the AVAssetWriter to encode video. I am using ARC. What I am trying to do is stream video over a socket.
Now here is the problem. The setup I have works the first time around. I am unable to use the AVAssetWriter again, without restarting my application first. If I don't restart my application, when I call [m_writer startWriting] I receive the following error:
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x14d06fe0 {Error Domain=NSOSStatusErrorDomain Code=-12983 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-12983)}
I made sure that file was deleted when the cleaup method was called.
I used iExplorer to navigate to the temp folder where the file was
being created. I also made sure that the status of the AVAssetWriter
after calling finshWriting is AVAssetWriterStatusFinished.
Edit: The error persists even If I used a different file name.
I create an instance of the VideoEncoder class ( code below) and then I feed it raw images. Then I wait for something to be written to the output file by the AVAssetWriter using a dispatch_source_set_event_handler(), i.e.:
m_inputFile = [NSFileHandle fileHandleForReadingAtPath: m_writer.path];
m_readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, [m_inputFile fileDescriptor], 0, m_readQueue);
dispatch_source_set_event_handler(m_readSource, ^{
// Read bytes from file and send over socket
}
dispatch_source_set_cancel_handler(m_readSource, ^{
[self cleanup];
}
dispatch_resume(m_readSource);
I have created a wrapper for the AVAssetWriter called VideoEncoder. Here is how I initialize the AVAssetWriter:
#implementation VideoEncoder : NSObject
{
AVAssetWriter* m_writer;
AVAssetWriterInput* m_writerInput;
AVAssetWriterInputPixelBufferAdaptor* m_pixelBufferAdaptor;
}
-(id) initWithPath:(NSString*)path width:(int)width height:(int)height parameters:(NSDictionary*) parameters
{
if (self = [super init])
{
self.path = path;
[[NSFileManager defaultManager] removeItemAtPath:self.path error:nil];
NSURL* url = [NSURL fileURLWithPath: self.path];
m_writer = [[AVAssetWriter alloc] initWithURL:url fileType:AVFileTypeQuickTimeMovie error: nil];
NSDictionary* settings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt: width], AVVideoWidthKey,
[NSNumber numberWithInt:height], AVVideoHeightKey,
parameters, AVVideoCompressionPropertiesKey,
nil];
m_writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:settings];
m_writerInput.expectsMediaDataInRealTime = YES;
[m_writer addInput:m_writerInput];
NSDictionary* pixelBufferOptions = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithInt: kCVPixelFormatType_32BGRA], kCVPixelBufferPixelFormatTypeKey,
[NSNumber numberWithInt: width*4], kCVPixelBufferBytesPerRowAllignmentKey,
[NSNumber numberWithInt; width], kCVPixelBufferWidthKey,
[NSNumber numberWithInt; height], kCVPixelBufferHeightKey,
nil];
m_pixelBufferAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc]
initWithAssetWriterInput: m_writerInput
sourcePixelBufferAttributes: pixelBufferOptions];
[m_writer startWriting];
[m_writer startSessionAtSourceTime: kCMTimeZero];
}
}
This is how I feed it raw images:
-(BOOL) encodeFrame:(CVPixelBufferRead)pixelBuffer time(CMTime)time;
{
if (m_writer.status == AVAssetWriterStatusFailed)
{
return NO;
}
if (m_writerInput.readyForMoreMediaData == YES)
{
if ([m_pixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:time])
{
return YES:
}
}
return NO;
}
This is how the pixel buffers are generated:
-(bool) encodeImage:(const char*) frameBuffer width:(int)width height:(int)height
{
CVPixelBufferRef pixelBuffer = NULL;
CVReturn ret;
ret = CVPixelBufferCraeteWithBytes(
kCFAllocatorDefault,
with,
height,
kCVPixelFormatType_32BGRA,
(void*) frameBuffer,
width * 4,
NULL, NULL, NULL, NULL, &pixelBuffer);
if (ret == kCVReturnSuccess && pixelBuffer)
{
CFTimeInterval currTime = CACurrentMediaTime();
if (m_frameIndex > 0 )
{
int ticks = (int)((currTime - m_prevTime) * 1000) / 30;
CMTime addTime;
ticks = ticks <= 0 ? 1 : ticks;
addTime = CMTimeMake(ticks, 30);
m_timestamp = CMTimeAdd(m_timestamp, addTime);
}
m_prevTime = currTime;
[m_impl encodeFrame: pixelBuffer time: m_timestamp];
CVBufferRelease(pixelBuffer);
m_frameIndex ++;
}
}
This is how I terminate the AVAssetWriter:
-(void) finishWritingWithCompletionHandler(void (^)(void))handler
{
[m_writerInput markAsFinished];
[m_writer finishWithCompletionHandler: ^{
handler();
}
}
And here is how I use the wrapper. I use this wrapper form a C++ class. Instantiation:
-(void) makeFilename
{
NSString* filename = [NSString* stringWithFormat: #"temp%d.tmp", 1];
NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent: filename];
return path;
}
bool CFrameEncoder::StartEncoding()
{
m_impl = CFRetain((__bridge*void)[[VideoEncoder alloc] initWithPath:[self makeFilepath] width:800 height:480 parameters: params]);
}
Dealloc:
bool CFrameEncoder::StopDecoding()
{
[(__bridge VideoEncoder*) m_impl terminate];
CFRelease(m_impl);
}
The terminate function (of the VideoEncoder class):
-(void) terminate
{
if (m_readSource)
{
dispatch_source_cancel(m_readSource);
}
}
// The dispatch source cancel handler
-(void) cleanup
{
m_readQueue = nil;
m_readSource = nil;
[m_inputFile closeFile];
NSString* path = m_writer.path;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[m_writer finishWithCompletionHandler:^{
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
m_writer = nil;
[[NSFileManager defaultManager] removeItemAtPath: path error: nil];
}
The AVAssetWriter class can have only a limited number of instances. If your application goes over this limit, then the AVAssetWriter begins to fail with AVAssetWriterStatusFailed when you try to startWriting.
This means that there is something in my code that is preventing the AVAssetWriter from being deallocated. Does anybody know where?
I'm using instruments and I have a lot of memory being leaked by this method. It is used everywhere in my app, and when I built it, I used some c++ (i think).
Please let me know where the leak is happening if possible?
Instruments just says Malloc 16 bytes and has about 60 MB worth of these guys...
/*
Parses a dicionary into an object
*/
+(id)makeObject:(id)object fromDictionary:(NSDictionary *)dict{
#autoreleasepool {
NSArray *keys = #[#"#\"NSMutableArray\""];
//Init result
id result = object;
//Iterate every key
for (id key in [dict allKeys]) {
//Convert key to const char
const char * c = [key cStringUsingEncoding:NSASCIIStringEncoding];
//Use c to see if the class has this property
if (class_getProperty([object class], c)) {
//get the property
objc_property_t property = class_getProperty([result class], c);
//Get the property name and type
const char *name = property_getName(property);
const char *type = property_copyAttributeValue(property, "T");
//Cast const char to string
NSString *pNameString = [NSString stringWithFormat:#"%s",name];
NSString *typeString = [NSString stringWithFormat:#"%s",type];
//Add relationships
if ([keys containsObject:typeString]) {
//Get array of objects
NSArray *relationship = [dict objectForKey:pNameString];
NSMutableArray *allSubObjects = [[NSMutableArray alloc]init];
//Parse each individual object
for (NSDictionary *relationshipObj in relationship) {
//Create class from relationship
Class class = NSClassFromString(pNameString);
//Create object
id sub = [self makeObject:[[class alloc]init] fromDictionary:relationshipObj];
[allSubObjects addObject:sub];
}
[result setValue:allSubObjects forKey:pNameString];
}else{
//If so set the property for the key
[result setValue:[dict objectForKey:key] forKey:key];
}
}else{
//NSLog(#"%# did not respond to : %#", result, key);
}
}
//Return result
return result;
}
}
EDIT:
Instruments shows these two items most likely the culprits. What's the best way to fix this?
//Cast const char to string
NSString *pNameString = [NSString stringWithFormat:#"%s",name];
NSString *typeString = [NSString stringWithFormat:#"%s",type];
1) [NSString cStringUsingEncoding]
This allocate some memory internally which will not freed until the NSString object is deallocated. I don't know exactly but could it be possible repeatedly sending cStringUsingEncoding incur unused memory building up?
2) property_copyAttributeValue
Documentation says,
Return Value A C array of pointers of type objc_property_t describing
the properties declared by proto. Any properties declared by other
protocols adopted by this protocol are not included. The array
contains *outCount pointers followed by a NULL terminator. You must
free the array with free().
You need to free const char *type.
3) NSMutableArray *allSubObjects = [[NSMutableArray alloc]init]
It should be NSMutableArray *allSubObjects = [NSMutableArray array].
4) Object creation
Class class = NSClassFromString(pNameString);
//Create object
id sub = [self makeObject:[[class alloc]init] fromDictionary:relationshipObj];
I'd put this code block in its own autorelease pool.
[class alloc]init] is also suspicious.
In my application I am displaying contacts in table view with indexed list. I am displaying indexed list as follow:
static NSString *letters = #"abcdefghijklmnopqrstuvwxyz#";
-(void)getAllUserInfoUsingBlock:(lclResultsArray) block
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSMutableArray *allUserInfoArray = [[NSMutableArray alloc]init];
NSLog(#"[letters length]:- %d",[letters length]);
for (int i = 0; i < [letters length]; i++ ) {
NSMutableDictionary *row = [[NSMutableDictionary alloc] init];
char currentLetter[2] = { toupper([letters characterAtIndex:i]), '\0'};
NSString *str=[NSString stringWithCString:currentLetter encoding:NSASCIIStringEncoding];
NSMutableArray *words = nil;
NSLog(#"Value of i:- %d:: Letter:- %#",i,str);
if (i<[letters length]) {
words = [self getUserInfoByStartingCharOfLastName:str isForEmptyValue:NO];
}
else {
// Get users where name is empty
words = [self getUserInfoByStartingCharOfLastName:#"" isForEmptyValue:YES];
}
NSLog(#"Count for %# :- %d",str,words.count);
[row setValue:str forKey:#"sectionTitle"];
[row setValue:words forKey:#"sectionRows"];
[allUserInfoArray addObject:row];
}
dispatch_async(dispatch_get_main_queue(), ^{
for (NSDictionary *dict in allUserInfoArray) {
NSLog(#"Array count:- %d",[[dict objectForKey:#"sectionRows"]count]);
}
block(allUserInfoArray,nil);
});
});
}
- (NSString *)tableView:(UITableView *)aTableView titleForHeaderInSection:(NSInteger)section
{
if (aTableView != self.searchDisplayController.searchResultsTableView){
NSMutableDictionary *sections=[self.contactsArray objectAtIndex:section];
NSString * sectionTitle= [sections objectForKey:#"sectionTitle"];
return sectionTitle;
}
return nil;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
if (tableView != self.searchDisplayController.searchResultsTableView){
NSMutableDictionary *sections=[self.contactsArray objectAtIndex:index];
NSString * sectionTitle= [sections objectForKey:#"sectionTitle"];
return [self.indices indexOfObject:sectionTitle];
}
return 0;
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
if (tableView != self.searchDisplayController.searchResultsTableView){
return [self.contactsArray valueForKey:#"sectionTitle"];
}
return nil;
}
But it displays as shown in following images
As you can see in first image its displaying A.C.E .... V.X.Z# Its displaying alternate dots(.) after every character.But as shown in second image its dispalying correct headet title for table from ABC....XYZ#
Whats wrong in my implementation ?
Alternative dots between characters in indexed list depends upon display height of that indexedlist.if we can increase the tableSize .it will be automatically display whole characters.
Is it possible to use UIAutomation with cocos2d or any opengl application for that matter?
Specifically I want to use the zucchini framework to test my cocos2d game but that just uses UIAutomation anyway.
You can create custom steps in Zucchini and specify the coordinates to tap, e.g.
'Choose the red bird' : ->
target.tap({x:278, y:36})
'Press Fire' : ->
target.tap({x:170, y:260})
So, I got started with calabash-iOS and expanding on its backdoor. This is just for starters but with this you can get the accessibility label of the current CCScene, so you can check what screen is currently on and thus use for scripting actions. I'm not used to working with objc runtime, but as you can see it's possible to get properties, methods etc. A bit more digging and it should be possible to wrap more functionality, and hopefully something to wrap the cocos2d CCNode structure as well. This is a work in progress.
To use this you need to install https://github.com/calabash/calabash-ios and then implement the below function in the app delegate. Don't forget to set .accessibilityLabel to something like #"menu", #"game" or similar in your code. Optimally, only for the *-cal target, you don't want this code in production builds.
-(NSString*)calabashBackdoor:(NSString*)aIgnorable {
DLog(#"calabashBackdoor: %#", aIgnorable);
// UIApplication* app = [UIApplication sharedApplication];
if (aIgnorable != nil) {
NSArray* p = [aIgnorable componentsSeparatedByString:#" "];
NSString* command = [p objectAtIndex:0];
if ([command isEqualToString:#"getCurrentSceneLabel"]) {
CCDirector* director = [CCDirector sharedDirector];
DLog(#"director.runningScene.accessibilityLabel: %#", director.runningScene.accessibilityLabel);
return director.runningScene.accessibilityLabel;
}
else if ([command isEqualToString:#"class_copyMethodList"]) {
CCDirector* director = [CCDirector sharedDirector];
id inspectThisObject = director.runningScene;
DLog(#"inspectThisObject: %#, %#", [inspectThisObject class], inspectThisObject);
unsigned int count;
// To get the class methods of a class, use class_copyMethodList(object_getClass(cls), &count).
Method* methods = class_copyMethodList(object_getClass(inspectThisObject), &count);
//NSMutableString* returnstring = [NSMutableString string];
NSMutableArray* arrayOfMethodnames = [NSMutableArray array];
if (methods != NULL) {
for (int i = 0; i < count; i++) {
Method method = methods[i];
NSString* stringMethod = NSStringFromSelector(method_getName(method)); //NSStringFromSelector(method->method_name);
[arrayOfMethodnames addObject:stringMethod];
}
// An array of pointers of type Method describing the instance methods implemented by the class—any instance methods implemented by superclasses are not included. The array contains *outCount pointers followed by a NULL terminator. You must free the array with free().
free(methods);
}
DLog(#"arrayOfMethodnames: %#", arrayOfMethodnames);
return [arrayOfMethodnames componentsJoinedByString:#","];
}
else if ([command isEqualToString:#"class_copyPropertyList"]) {
CCDirector* director = [CCDirector sharedDirector];
id inspectThisObject = director.runningScene;
DLog(#"inspectThisObject: %#, %#", [inspectThisObject class], inspectThisObject);
unsigned int count;
// An array of pointers of type objc_property_t describing the properties declared by the class. Any properties declared by superclasses are not included. The array contains *outCount pointers followed by a NULL terminator. You must free the array with free().
//
// If cls declares no properties, or cls is Nil, returns NULL and *outCount is 0.
//
objc_property_t* properties = class_copyPropertyList(object_getClass(inspectThisObject), &count);
NSMutableArray* arrayOfProperties = [NSMutableArray array];
if (properties != NULL) {
for (int i = 0; i < count; i++) {
objc_property_t property = properties[i];
const char* CCS = property_getName(property);
NSString* str = [NSString stringWithUTF8String:CCS];
[arrayOfProperties addObject:str];
}
free(properties);
}
DLog(#"arrayOfProperties: %#", arrayOfProperties);
return [arrayOfProperties componentsJoinedByString:#","];
}
else {
DLog(#"Unhandled command: %#", command);
}
}
return #"calabashBackdoor nil!";
}
In Prefix.pch put this
#ifdef DEBUG
# define DLog( s, ... ) NSLog( #"<%p %#:(%d)> %#", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
# define DLog(...) /* */
#endif
#define ALog(...) NSLog(__VA_ARGS__)
When you get calabash-ios and running, add this in step_definitions/somesteps.rb:
Then(/^I backdoor (.+)$/) do |x|
backdoor("calabashBackdoor:", x)
end