I use it to check iOS version, but it doesn't work:
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_5_0
#define kCFCoreFoundationVersionNumber_iPhoneOS_5_0 675.000000
#endif
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_5_0
#define IF_IOS5_OR_GREATER(...) \
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_5_0) \
{ \
__VA_ARGS__ \
}
#else
#define IF_IOS5_OR_GREATER 0
#endif
when I make
#if IF_IOS5_OR_GREATER
NSLog(#"iOS5");
#endif
nothing happens. Is something wrong here?
Much simpler:
#define IS_IOS6_AND_UP ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0)
#ifdef __IPHONE_5_0
etc
Just look for that constant. All the objective c constants start with two underscores
You've defined a macro, but you're using it in the non-macro way. Try something like this, with your same macro definition.
IF_IOS5_OR_GREATER(NSLog(#"iOS5");)
(This is instead of your #if/#endif block.)
Define this method:
+(BOOL)iOS_5 {
NSString *osVersion = #"5.0";
NSString *currOsVersion = [[UIDevice currentDevice] systemVersion];
return [currOsVersion compare:osVersion options:NSNumericSearch] == NSOrderedAscending;
}
Then define the macro as that method.
For a runtime check use something like this:
- (BOOL)iOSVersionIsAtLeast:(NSString*)version {
NSComparisonResult result = [[[UIDevice currentDevice] systemVersion] compare:version options:NSNumericSearch];
return (result == NSOrderedDescending || result == NSOrderedSame);
}
If you create a category on UIDevice for it, you can use it as such:
#implementation UIDevice (OSVersion)
- (BOOL)iOSVersionIsAtLeast:(NSString*)version {
NSComparisonResult result = [[self systemVersion] compare:version options:NSNumericSearch];
return (result == NSOrderedDescending || result == NSOrderedSame);
}
#end
...
if([[UIDevice currentDevice] iOSVersionIsAtLeast:#"6.0"]) self.navigationBar.shadowImage = [UIImage new];
#define isIOS7 ([[[UIDevice currentDevice]systemVersion]floatValue] > 6.9) ?1 :0
Related
the code:
<UIKit/UIApplication.h> line 293-297
#if UIKIT_STRING_ENUMS
typedef NSString * UIApplicationLaunchOptionsKey NS_EXTENSIBLE_STRING_ENUM;
#else
typedef NSString * UIApplicationLaunchOptionsKey;
#endif
<UIKit/UIKitDefines.h>
#define UIKIT_STRING_ENUMS ((defined(SWIFT_SDK_OVERLAY_UIKIT_EPOCH) && SWIFT_SDK_OVERLAY_UIKIT_EPOCH >= 2))
What is #define UIKIT_STRING_ENUMS ?
UIKIT_STRING_ENUMS is a macro to control how Objective-C code is imported into Swift
I'm trying to filter an array according to one of it's string fields.
Both nameLower and filterLower has NSString value inside, and yet i keep getting:
__NSCFString containsString:]: unrecognized selector sent to instance 0x7f876b79e160
-(void) filterFriendsArray:(NSString*)filter {
[_filteredFriendsArray removeAllObjects];
for (FacebookUser* user in _friendsArray)
{
NSString* nameLower = [user.user.name lowercaseString];
NSString* filterLower = [filter lowercaseString];
if ([nameLower containsString:filterLower])
[_filteredFriendsArray addObject:user];
}
_displayedFriendsArray = _filteredFriendsArray;
}
If you want your code to work on iOS 7 as well as iOS 8 you should use one of the rangeOfString calls instead. Basically if the range returned has a length of zero, the substring is not there.
/* These methods return length==0 if the target string is not found. So, to check for containment: ([str rangeOfString:#"target"].length > 0). Note that the length of the range returned by these methods might be different than the length of the target string, due composed characters and such.
*/
- (NSRange)rangeOfString:(NSString *)aString;
- (NSRange)rangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask;
- (NSRange)rangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask range:(NSRange)searchRange;
- (NSRange)rangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask range:(NSRange)searchRange locale:(NSLocale *)locale NS_AVAILABLE(10_5, 2_0);
Obviously it's trivial to implement containsString yourself in a category using rangeOfString:
#implementation NSString (Contains)
- (BOOL)myContainsString:(NSString*)other {
NSRange range = [self rangeOfString:other];
return range.length != 0;
}
#end
compare rangeOfString with NSNotFound
NSRange range = [self rangeOfString:other];
if(range.location != NSNotFound){
//do something
}
Use following:
if (![[NSString class] respondsToSelector:#selector(containsString)])
{
//ios 7
NSRange range = [mystring rangeOfString:other];
if(range.location != NSNotFound){
//do something
}
}
else //for iOS 8
{
if ([mystring containsString: other])
{
//do something
}
}
For those who encountered this in XLForm, make sure when you install XLForm using pods
platform :ios, '7'
pod 'XLForm'
It is already fixed in 3.1
from
if ([cellClassString contains:#"/"]) {
}
to
if ([cellClassString rangeOfString:#"/"].location != NSNotFound) {
}
I encapsulate my solution in YJKit, and you can call -[NSString containsString:] even for old version which below iOS 8.
bool _yj_streq(const char *str1, const char *str2, size_t length) {
for (int i = 0; i < length; i++) {
if (*str1++ != *str2++) {
return false;
}
}
return true;
}
- (BOOL)yj_containsString:(NSString *)string {
NSAssert(string != nil, #"*** -[%# containsString:] can not use nil argument.", [self class]);
size_t len1 = (size_t)self.length;
size_t len2 = (size_t)string.length;
if (len1 == 0 || len2 == 0 || len1 < len2) {
return NO;
}
const char *str1 = self.UTF8String;
const char *str2 = string.UTF8String;
for (size_t i = 0; i <= len1 - len2; i++) {
const char *substr1 = str1 + i;
if (_yj_streq(substr1, str2, len2)) {
return YES;
} else {
continue;
}
}
return NO;
}
Here is my source code:
https://github.com/huang-kun/YJKit/blob/master/YJKit/Base/Foundation/Categories/Generics/NSString%2BYJCompatible.m
Swift version of the answer given by w0mbat:
extension NSString {
func compatibleContainsString(string: NSString) -> Bool{
let range = self.rangeOfString(string as String)
return range.length != 0
}
}
I'm a starter in obj-c programming and I need to know how to display device info ( name, device type, ios version )
I you know the answer, please tell me and keep in mind i'm a starter with xcode ;)
I've used these information in an App that I developed so I did the following code. I think this may help you. I just didn't understand what you mean with device type.
To get the device model:
// get model from UIDevice
NSString *modelDevice = [UIDevice currentDevice].model;
To get the iOS Version:
//get the iOS version
NSString *systemVersion = [[UIDevice currentDevice] systemVersion];
To get the device name:
/** Method responsible to get the device name
*
* #return device Name
*/
+ (NSString *)deviceName
{
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithUTF8String:machine];
free(machine);
return platform;
}
You may try something like this: I use this for in-app support emailing from users.
#import <sys/utsname.h>
- (void)yourMethod
{
struct utsname systemInfo;
uname(&systemInfo);
NSString *appVersion = [NSBundle mainBundle].infoDictionary[#"CFBundleVersion"];
NSString *osVersion = [[UIDevice currentDevice] systemVersion];
NSString *machine = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
}
NSLog(#"uniqueIdentifier: %#", [[UIDevice currentDevice] uniqueIdentifier]);
NSLog(#"name: %#", [[UIDevice currentDevice] name]);
NSLog(#"systemName: %#", [[UIDevice currentDevice] systemName]);
NSLog(#"systemVersion: %#", [[UIDevice currentDevice] systemVersion]);
NSLog(#"model: %#", [[UIDevice currentDevice] model]);
NSLog(#"localizedModel: %#", [[UIDevice currentDevice] localizedModel])
;
Please refer to UIDevice Class. It has all accessible system information properties. This is a singleton class. You can access this class instance like this : [UIDevice currentDevice]
For example if you want to access device model, you can access like this :
[UIDevice currentDevice]. model
Please refer this link to get information about all properties : https://developer.apple.com/library/ios/documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html
I am trying to find a way for Cocoa Lumberjack to show me file and line number.
After looking through the docs and some Googling, I found no easy way to do this.
Is there any way to do this without adding custom formatter?
Well, like I said, there is no built-in way. So, I've implemented custom formatter:
#interface LineNumberLogFormatter : NSObject<DDLogFormatter>
- (NSString *)formatLogMessage:(DDLogMessage *)logMessage;
#end
#implementation LineNumberLogFormatter
- (NSString *)formatLogMessage:(DDLogMessage *)logMessage
{
NSString *path = [NSString stringWithCString:logMessage->file encoding:NSASCIIStringEncoding];
NSString *fileName = [path lastPathComponent];
return [NSString stringWithFormat:#"%#:%d %#", fileName, logMessage->lineNumber, logMessage->logMsg];
}
#end
While a separate formatter class would work, it would make your logging code a bit more verbose. In my project I opted for adding some additional macros that make use of CocoaLumberjack like so:
// Prefix.pch file
// ...
#ifdef DEBUG
#define DLogError(fmt, ...) DDLogError((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#define DLogWarn(fmt, ...) DDLogWarn((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#define DLogInfo(fmt, ...) DDLogInfo((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#define DLogDebug(fmt, ...) DDLogDebug((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#define DLogVerbose(fmt, ...) DDLogVerbose((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define DLogError(fmt, ...)
#define DLogWarn(fmt, ...)
#define DLogInfo(fmt, ...)
#define DLogDebug(fmt, ...)
#define DLogVerbose(fmt, ...)
#endif
In your client code, you could then call:
DLogWarn(#"This is a warning");
As UrK suggested, there isn't any trivial way, but it's pretty simple if you define your own formatter (see doc)
Hello guys I have found this code that is used to create a different NSLog (without data and timestamps) that displays the class where the log was made and the line number.
I have read that is possible to disable the logging only for certain classes with NO_LOG but there was not explained how to use it exactly, I am quite new to obj-c and I appreciate an explanation on how to disable logging for certain classes and how to activate and deactivate the debugging. thanks
#define MAKESTRING(__VA_ARGS__) #__VA_ARGS__
#define TOSTRING(...) MAKESTRING(__VA_ARGS__)
static inline void PxReportv(BOOL doLog, char const *file, int line, NSString *prefix, NSString *fmt, va_list argList) {
if (doLog) {
NSString *fileNameWithExtension = [[NSString stringWithFormat:#"%s", file] lastPathComponent];
#ifdef NO_LOG
NSString *fileName = [fileNameWithExtension stringByDeletingPathExtension];
char *f = TOSTRING(NO_LOG);
NSArray *comps = [[[NSString alloc] initWithFormat:#"%s", f] componentsSeparatedByString:#","];
for (NSString *except in comps) {
if ([except isEqualToString:fileName]) {
return;
}
}
#endif
vprintf([[[NSString alloc] initWithFormat:[[NSString alloc] initWithFormat:#"%# <%# [%d]> %#\n", prefix, fileNameWithExtension, line, fmt] arguments:argList] cStringUsingEncoding:NSUTF8StringEncoding], NULL);
}
}
static inline void PxReport(BOOL doLog, char const *file, int line, NSString *prefix, NSString *fmt, ...) {
va_list ap;
va_start(ap, fmt);
PxReportv(doLog, file, line, prefix, fmt, ap);
va_end(ap);
}
#define PxError(...) PxReport(YES, __FILE__, __LINE__, #"[ERROR]", __VA_ARGS__)
#ifdef DEBUG
#define PxDebug(...) PxReport(YES, __FILE__, __LINE__, #"[DEBUG]", __VA_ARGS__)
#define NSLog(...) PxReport(YES, __FILE__, __LINE__, #"", __VA_ARGS__)
#else
#define PxDebug(...)
#define NSLog(...)
#endif
Add this:
#define NO_LOG 1
before #importing the file you've shown above.
BTW a better implementation would define PxDebug() and NSLog() to nothing if NO_LOG was defined...
that is quite a verbose solution, i made one that is a lot neater than that
#ifndef DebugLog_h
#define DebugLog_h
#if DEBUG
#define DLog(...) do{\
printf("[%s:%d]", __FUNCTION__, __LINE__);\
NSString *_S_ = [NSString stringWithFormat:__VA_ARGS__];\
printf(" %s\n",[_S_ cStringUsingEncoding:NSUTF8StringEncoding]);\
}while(0);
#else
#define DLog(...)
#endif
#endif
that will print the line number, class and function it came from
eg:
Dlog(#"hello %d", 123);
[-[SomeViewController viewWillAppear:]:91] hello 123
edit: if you add the file to your projectname-Prefix.pch file, then you can use it without having to include it everywhere
and it will automatically be taken out of release builds, because DEBUG is defined as a project definition automatically when its in debug mode