How to use BOOL in macro in IOS xCode? - xcode

Hi i'm wondering how to use BOOL in macro in xCode?
like this:
#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES)
#ifdef IS_IPHONE5
# define VIEW_HEIGHT_HALF 284
#else
# define VIEW_HEIGHT_HALF 240
#endif
doesn't work..
so only i can code like this?
#define VIEW_HEIGHT_HALF (([[UIScreen mainScreen] bounds].size.height-568)?240:284)
Thanks.

Related

How to use nested if condition in velocity template template?

I'm trying to create a nested if condition using velocity template. I am not sure if it is right. Please give the suggestions if it works or not..!!
#if(myExpression1)
#if(myExpression2)
Result 1
#else
Result 2
#end
#else
Result 3
#end
Yes this works. You can nest an if within an if. Just make sure that all #if statements are closed with an #end
There are some examples of nested statements within default hybris. For example in copyable-template.vm
#if ($hasEqualsProperties)
<code>
#if ($superEquals)
<code>
#end
<code>
#foreach($v in $equalsProperties)
#if ($v.type == 'boolean')
<code>
#else
<code>
#end
#end
#end
For simplicity, I've removed some of the code and only left the # statements in
We can do all kinds of conditional operations just an example here.
#if ( $ctx.isGuest() )
#set ($orderInfoUrl = "${ctx.baseUrl}/guest/order/${ctx.orderGuid}")
#else
#set ($orderInfoUrl = "${ctx.baseUrl}/my-account/order/${ctx.orderCode}")
#end

How to create an array of CCColor?

I use cocos2dV3 i create some color:
#define color_red ccc3(253, 93, 70)
#define color_green ccc3(138,233,145)
#define color_yellow ccc3(230,219,37)
#define color_violet ccc3 (153,93,181)
#define color_turquoise ccc3(138,188,255)
#define color_default ccc3(225,225,225)
How i can save it as array : NSArray , NSmutableAraay ... ?
NSmutableArray * _arrColors =[[NSMutableArray alloc]init];
[_arrColors addObject:color_turquoise];
When i create array it alway show errors : " Sending 'ccColor3B' (aka 'struct _ccColor3B') to parameter of incompatible type 'id'"
What i do worng ?
Using cocos2d does not relieve you of the responsibility of knowing Objective-C. A ccColor3B is not an object - it is a struct - so it cannot be put into an NSArray. You could, if you really want to do this, wrap it in an object, something like this perhaps:
ccColor3B c = color_turquoise;
[_arrColors addObject:[NSValue valueWithBytes:&c objCType:#encode(ccColor3B)]];

How to filter console output in Xcode

In my iOS project, I use one 3rd-party library, which is is incredible spamming into the console output. Can I apply any filtering to debug output.
If the library is using NSLog you can redefine it and discard the log message when it comes from the library. Example code:
#define NSLog(args...) [[Logger singleton] debugWithLevel:kDebug line:__LINE__ funcName:__PRETTY_FUNCTION__ message:args];
// poor man's nslog
#interface Logger : NSObject
typedef enum {
kTrace=0, kDebug=1, kInfo=2, kWarn=3, kError=4, KSilent=5
} LoggerLevel;
// ...
#implementation Logger
+(Logger *)singleton {
static dispatch_once_t pred;
static Logger *shared = nil;
dispatch_once(&pred, ^{
shared = [[Logger alloc] init];
shared.logThreshold = kTrace;
});
return shared;
}
-(void) debugWithLevel:(LoggerLevel)level
line:(int)line
funcName:(const char *)funcName
message:(NSString *)msg, ... {
va_list ap;
va_start (ap, msg);
msg = [[[NSString alloc] initWithFormat:msg arguments:ap] autorelease];
va_end (ap);
msg = [NSString stringWithFormat:#"%s %50s:%3d - %#", levelName[level], funcName, line, msg];
// ... filter by class name ...
fprintf(stdout,"%s\n", [msg UTF8String]);
}
#end
Note that funcName contains the classname and method sending the message. If the library is a good citizen and has classes that start with a prefix, discard the output if the className starts with that. Otherwise you have to load a list of classes from that library and check them before the fprintf line.
This of course, doesn't duplicate the log to syslogd like NSLog does, but who cares. :P
Works in Xcode 5.0 through 7.3, Apple no longer supports Xcode plug-ins as of Xcode 8.0.
MCLog should be what you're looking for.
This is an XCode plugin.
It depends if you're using directly the 3rd party library source code in your project or a binary library.
If you're using the source code I'd suggest to check what they are using to log the messages. It may have a way to reduce the verbosity. If they are using plain NSLog the only option would be to redefine NSLog in order to do some filtering, as Jano proposed you.
If they are using low level functions like printf and the like, your best option is to replace them with your own custom logging macro, like:
#ifdef DEBUG_3P
#define LOG_3P(str) NSLog(#"%s", str)
#else
#define LOG_3P(str) /* nothing */
#endif
Then, replace printf("a c string message") with LOG_3P("a c string message"). You'll need to customize the solution, adjust macro parameters or even add several macros for your case. And make a few search and replace until it works.
When you want to see the 3rd party library logs, just define DEBUG_3P in your build settings as C flags: -D DEBUG_3P, otherwise it will be mute.
If you're using a binary library you can just build it with its release configuration, disabling or reducing the logs verbosity to its minimum.
For Swift, I wrote a wrapper around print() that does just this. See here: https://github.com/SebastianMecklenburg/TagLog
It works by adding tags to debug messages and then filter the output by those tags. It works all in code and doesn't need an Xcode plugin.

Cocoa naming scheme for assign initializer

For some reason I thought this was valid under the memory management naming rules:
Bar *bar = [Bar new];
[Foo fooWithNewBar:bar];
// no need to release bar, foo took ownership
However now I'm running my static analysis, it thinks there's a potential leak everytime I did this.
I see there is __attribute((ns_consumed)) which I could use on the fooWithNewBar declaration. But Xcode 4.0.1's Clang does not yet support this attribute.
So, there's no such naming pattern?
I also think there’s no naming pattern corresponding to ns_consumed in your case. Naming patterns are largely driven by NeXTSTEP/Apple and I can’t think of a method in Apple’s frameworks with the same semantics you want.
Note, however, that you can tell Xcode to use a more recent version of Clang Static Analyser that supports the ns_consumed attribute, which was released with checker-254.
I’m using checker-256 (released today, but any version >= 254 should work) and I’ve just tried the following:
// MyClass.h
#ifndef __has_feature // Optional.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif
#ifndef NS_CONSUMED
#if __has_feature(attribute_ns_consumed)
#define NS_CONSUMED __attribute__((ns_consumed))
#else
#define NS_CONSUMED
#endif
#endif
#interface MyClass : NSObject {
#private
NSString *_string;
}
+ (MyClass *)myClassWithNewStringConsumed:(NSString *) NS_CONSUMED string NS_RETURNS_RETAINED;
+ (MyClass *)myClassWithNewString:(NSString *)string NS_RETURNS_RETAINED;
#end
and
// MyClass.m
#import "MyClass.h"
#implementation MyClass
+ (MyClass *)myClassWithNewStringConsumed:(NSString *)string {
MyClass *o = [MyClass new];
if (o) o->_string = string;
return o;
}
+ (MyClass *)myClassWithNewString:(NSString *)string {
MyClass *o = [MyClass new];
if (o) o->_string = string;
return o;
}
#end
This code gives a static analyser warning for a potential leak of the string stored in s:
// SomewhereElse.m
NSString *s = [[NSString alloc] initWithFormat:#"%d",
[[NSProcessInfo processInfo] processIdentifier]];
MyClass *o = [MyClass myClassWithNewString:s];
[o release];
whereas this code, which uses the method parameter with an ns_consumed attribute, doesn’t give a static analyser warning:
// SomewhereElse.m
NSString *s = [[NSString alloc] initWithFormat:#"%d",
[[NSProcessInfo processInfo] processIdentifier]];
MyClass *o = [MyClass myClassWithNewStringConsumed:s];
[o release];
There is no such pattern. Wherever I think I read about it, I didn't.
Bar *bar = [Bar new];
You own bar.
[Foo fooWithNewBar:bar];
If this wants to own bar, it should be retaining it. That doesn't relinquish your ownership, so you still have to release bar.
I've never seen the pattern you're using.
Foo took an interest in Bar, but *bar still has interest until [bar release] that interest.
Ownership in Objective-C reference-counted memory management is C++ share_ptr, rather than auto_ptr style. In other words, you don't transfer ownership to the Foo instance. Rather the Foo instance declares a share of ownerhsip in your Bar instance (leaving you, the caller of [Bar new] with a share of ownership as well). You always need to relinquish your ownership share of an instance before it may be deallocated. Thus, your example should be
Bar *bar = [[Bar alloc] init]; //Most Obj-C devs prefer alloc/init. When in Rome...
[Foo fooWithNewBar:[bar autorelease]]; //relinquish ownership of bar
Note that you have to use -autorelease rather than -release to relinquish your ownership share because Foo needs a chance to claim an ownership stake before bar is deallocated.

In Xcode, is there a way to disable the timestamps that appear in the debugger console when calling NSLog?

Xcode's debugger console makes it easy to see any debugging messages my app sends out using NSLog(), but it always sticks a timestamp prefix on them:
2009-08-30 04:54:48.128 MyApp[94652:a0f] some log message
2009-08-30 04:54:50.647 MyApp[94652:a0f] another log message
...
I have no use for this prefix, and it takes up a lot of room. I have a feeling it is hard-coded into Apple's logging system, but just in case there is a solution out there:
Can I have the debugger console show me log messages without the timestamp prefix?
Something like this would be perfect:
some log message
another log message
...
NSLog() is what is doing that, not the debugger console.
The easiest way to avoid it is to not use NSLog at all. You could use fprintf(), but that is a pain in that it doesn't support %# format types.
I generally write a function for this:
void MyLog(NSString *format, ...) {
va_list args;
va_start(args, format);
NSString *formattedString = [[NSString alloc] initWithFormat: format
arguments: args];
va_end(args);
[[NSFileHandle fileHandleWithStandardOutput]
writeData: [formattedString dataUsingEncoding: NSNEXTSTEPStringEncoding]];
}
Obviously, modify it to add a newline or use a shorter prefix, etc...
(Fixed the stray ctrl-b)
Define a macro
#if __has_feature(objc_arc)
#define MDLog(format, ...) CFShow((__bridge CFStringRef)[NSString stringWithFormat:format, ## __VA_ARGS__]);
#else
#define MDLog(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]);
#endif
And use this macro in you code like
NSLog(#"some log message");
MDLog(#"some log message");
Here is the output of console
NSLog->2014-01-28 10:43:17.873 TestApp[452:60b] some log message
MDLog -> some log message
P.S.
If anyone wants Custom Logs which gives you more info like method name / line number etc. can download the open source MLog.h on GitHub.
put in this one line code in your .pch file and you are done
#define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
notice the ## part
A way to keep using NSLog in conjunction with bbum's answer is to use a preprocessor macro to redefine NSLog to your own function
#define USECUSTOMLOGS 1
#if USECUSTOMLOGS
#define NSLog MyLog
#endif
This will replace NSLog with MyLog on compile time. Basically you can keep using NSLog everywhere and it will still use your custom format for the console window. You can also change it back to use NSLog at anytime by changing the 1 to a 0.
ARC Version:
void NFLog(NSString *format, ...)
{
va_list args;
va_start(args, format);
NSString *formattedString = [NSString stringWithFormat:format, args];
formattedString = [formattedString stringByAppendingString:#"\n"];
va_end(args);
[[NSFileHandle fileHandleWithStandardOutput] writeData: [formattedString dataUsingEncoding: NSUTF8StringEncoding]];
}
update:
What I am doing is add this code to xxx-Prefix.pch then you can use it anywhere:
#define newLine do { [(NSFileHandle*)[NSFileHandle fileHandleWithStandardOutput] writeData:[#"\n" dataUsingEncoding: NSUTF8StringEncoding]]; } while(0);
#define NFLog(args,...) do { [(NSFileHandle*)[NSFileHandle fileHandleWithStandardOutput] writeData:[[NSString stringWithFormat:args, ##__VA_ARGS__] dataUsingEncoding: NSUTF8StringEncoding]]; } while(0); newLine
and if you want NSLog back:
#define NFLog(args,...) NSLog(args,##__VA_ARGS__)
In the top left corner of the console window there is a pulldown menu that says All Output / Debugger Output / Target Output.
Select Target Output. It worked on my older versions of Xcode, but to be honest with you it doesn't with my current 4.3 version.
I hope this helps you.
JR
This is way more easier than the suggested solutions. Using carelesslyChoosy's solution and adding a little bit more to make it log entries on release builds only you get the macro below. Just add this macro to your header or .pch file. This macro will show log entries when the DEBUG flag is enabled, on release builds you won't see log entries.
#ifdef DEBUG
#define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#define Log(x, ...) NSLog(#"%s %d: " x, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define Log(x, ...)
#endif
Clean Log Macro
Here is a macro I've made for this purpose. It works exactly like NSLog but with just your text, no extra info
Macro (paste to your .h)
#define CLog(__string, ...) fprintf(stderr, "\n%s", [([NSString stringWithFormat:__string, ##__VA_ARGS__]) UTF8String])
Example use:
CLog(#"I am %i days and %i years old", 3, 7);
Logs:
I am 3 days and 7 years old

Resources