Deprecated Xcode issues - objective-c

im getting errors and warnings with the following code:
Warning undeclared selector uniqueIdentifier at the first if statement;
Error Property uniqueIdentifier not found on object of type UIDevice
Error Cast of C pointer type CFStringRef
// Get the users Device Model, Display Name, Unique ID, Token & Version Number
UIDevice *dev = [UIDevice currentDevice];
NSString *deviceUuid;
if ([dev respondsToSelector:#selector(uniqueIdentifier)]) // Warning #1
deviceUuid = dev.uniqueIdentifier; // Error #1
else {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
id uuid = [defaults objectForKey:#"deviceUuid"];
if (uuid)
deviceUuid = (NSString *)uuid;
else {
CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
deviceUuid = (NSString *)cfUuid; // Error #2
CFRelease(cfUuid);
[defaults setObject:deviceUuid forKey:#"deviceUuid"];
}
}

UIDevice uniqueIdentifier property is deprecated in iOS 5 and above
udid = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSLog(#"UDID : %#", udid);

You must create a method with name uniqueIdentifier
UIDevice does not have a property called uniqueIdentifier. See this answer.
Look at this answer.

Related

CallKit call block set values from array not working

I am working on one app in which I want a feature to block call. If i am passing static values to addBlockingEntryWithNextSequentialPhoneNumber it's blocking numbers but when i'm passing array in addBlockingEntryWithNextSequentialPhoneNumber it's not blocking numbers. I have logged my array in Appdelegate and it looks fine.
Appdegate Code:
NSArray *sortedArr = [lockedArr sortedArrayUsingSelector:#selector(compare:)];
[DEFAULTS setObject:sortedArr forKey:#"SortedBlockedUsers"];
NSArray<NSNumber *> *blockedPhoneNumbers = [DEFAULTS objectForKey:#"SortedBlockedUsers"];
for (NSNumber *phoneNumber in blockedPhoneNumbers) {
NSLog(#"phoneNumber == %lld", (CXCallDirectoryPhoneNumber)[phoneNumber unsignedLongLongValue]);
}
output is: phoneNumber == 918849494978 phoneNumber == 919142142124
HandlerClass code:
NSArray<NSNumber *> *blockedPhoneNumbers = [[NSUserDefaults standardUserDefaults] objectForKey:#"SortedBlockedUsers"];
//NSArray<NSNumber *> *blockedPhoneNumbers = #[ #918823514521, #919586112211 ];
for (NSNumber *phoneNumber in blockedPhoneNumbers)
{
[context addBlockingEntryWithNextSequentialPhoneNumber:(CXCallDirectoryPhoneNumber)[phoneNumber unsignedLongLongValue]];
}
Finally after debugging my extension class I found that problem is assigning value to array from NSUserDefaults. We must have to save and retrieve value using NSUserDefaults SuiteName to interact with Extension class.

NSUserDefaults set the default value of integer variable to empty

I used NSUserDefaults to store an integer value. When I run the project there's a default value of 0 in it. How do I remove the 0 value? I just want it to be empty until the user put something in it.
Here is my code:
- (IBAction)save:(id)sender{
int port = [[portField text] integerValue];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:port forKey:#"port"];
[defaults synchronize];
}
- (void)viewDidLoad {
int port = [defaults integerForKey:#"port"];
NSString *portString = [NSString stringWithFormat:#"%lu",(unsigned long)port];
portField.text = portString;
[super viewDidLoad];
}
Well, this line:
int port = [defaults integerForKey:#"port"];
will always assign some value to port.
Also, this:
NSString *portString = [NSString stringWithFormat:#"%lu",(unsigned long)port];
will always produce a non-empty string. There's no value you could pass for a %lu specifier that will produce an empty string.
So, what you want to do is ask for the object that's stored in the preferences, without converting it to a integer value:
id portObject = [defaults objectForKey:#"port"];
if (portObject)
{
NSInteger port;
if ([portObject respondsToSelector:#selector(integerValue)])
port = [portObject integerValue];
else
{
// portObject is some unexpected class of object, such as an array or dictionary. Take some appropriate action. Or:
port = 0;
}
portField.text = [NSString stringWithFormat:#"%ld", (long)port];
}
else
{
// There was no value either stored or registered for the key "port"
portField.text = #"";
}
Note that for this to work, you must not have registered a default value for the "port" key using -[NSUserDefaults registerDefaults:].
As far as I know, NSUserDefaults always return default values for primitive types when they are not exists.
If the default value is a valid value you use, I suggest to put a blank object or just NSString object to determine if the associated value is valid. e.g.
NSObject *objValid = [userDefaults objectForKey:#"integerIsValid"];
if(objValid != nil) {
// User stored integer value exists.
NSInteger i = [userDefaults integerForKey:#"SomeInteger"];
} else {
// Have not saved integer value.
}
When user save the integer value, also save the associated object:
[userDefaults setObject:[[NSObject alloc]init] forKey:#"integerIsValid"];
[userDefaults setInteger:i forKey:#"SomeInteger"];
UPDATE
If your value range can transform to another value range by some rules, then you can do it another way.
All values are in range [0, 100) for example, you can store in range [1, 101) and retrieve the real value by subtracting 1.

IOS & Objective C - how can i resolve this error "implicit declaration of function "class_getname " is invalid in c99"?

Actually there are two errors, the first one is :
"implicit declaration of function "class_getname " is invalid in c99"
The second one is :
incompatible integer to pointer conversion initializing 'const char*' with an expression of type 'int'
my method is :
-(void) donneesrecoltees:(NSData *)donnees {
NSError *erreur;
NSNumber *lastMessage,*currentMessage;
//int i;
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSString *msg;
UIAlertView *alert;
NSDictionary *json=[NSJSONSerialization JSONObjectWithData:donnees options:0 error:&erreur];
// Check if it's the right class to avoid error stack
// this is the line that is causing the error
const char* className = class_getName([json class]);
NSString *myClass=[NSString stringWithFormat:#"%s",className];
....
}
Any help on how to fix this? thank you
You need to #import <objc/runtime.h>

NSUUID to NSString from (CBPeripheral *)aPeripheral

I want to save the string version of the NSUUID from a CBPeripheral.
I try this:
NSString *uuidString = aPeripheral.UUID;
But a warning appears:
Incompatible pointer types initializing NSString with an expression of type CFUUIDRef
- (void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)aPeripheral {
NSLog(#"method didConnectPeripheral %# " , aPeripheral.UUID);
NSString *uuidString = aPeripheral.UUID;
}
The -UUID method of CBPeripheral returns a CFUUIDRef, not an NSString, and is also deprecated as of iOS 7.1. If you need to use it, either store it in a CFUUIDRef, or use CFUUIDCreateString and bridge it to an NSString.
A UUID is no string (even it is represented as a string very often.)
You can convert it into a CFStringRef with CFUUIDCreateString();

unrecognized selector with category NSMutableData

I'm adding a category to NSData as follows:
// PacketCategories.h
#interface NSData(PacketSplit)
- (NSArray *)splitTransferredPackets:(NSData **)leftover;
#end
// PacketCategories.m
#implementation NSData(PacketSplit)
- (NSArray *)splitTransferredPackets:(NSData **)leftover {
NSMutableArray *ret = [NSMutableArray array];
const unsigned char *beginning = [self bytes];
const unsigned char *offset = [self bytes];
NSInteger bytesEnd = (NSInteger)offset + [self length];
while ((NSInteger)offset < bytesEnd) {
uint64_t dataSize[1];
NSInteger dataSizeStart = offset - beginning;
NSInteger dataStart = dataSizeStart + sizeof(uint64_t);
NSRange headerRange = NSMakeRange(dataSizeStart, sizeof(uint64_t));
[self getBytes:dataSize range:headerRange];
if (dataStart + dataSize[0] + (NSInteger)offset > bytesEnd) {
NSInteger lengthOfRemainingData = [self length] - dataSizeStart;
NSRange dataRange = NSMakeRange(dataSizeStart, lengthOfRemainingData);
*leftover = [self subdataWithRange:dataRange];
return ret;
}
NSRange dataRange = NSMakeRange(dataStart, dataSize[0]);
NSData *parsedData = [self subdataWithRange:dataRange];
[ret addObject:parsedData];
offset = offset + dataSize[0] + sizeof(uint64_t);
}
return ret;
}
#end
And then trying to call that category:
#import "PacketCategories.h"
NSMutableData *data = [NSMutableData data];
// Read some data
[data appendBytes:buffer length:bytesRead];
NSArray *dataPackets = [data splitTransferredPackets:&readLeftover];
Which gets the following error:
-[NSConcreteMutableData splitTransferredPackets:]: unrecognized selector sent to instance 0x6e6f7b0
[ERROR] The application has crashed with an unhandled exception. Stack trace:
Any ideas? Does NSConcreteMutableData not inherit from NSData?
Other suggested answers (Objective-C Category Causing unrecognized selector) have suggested that the file isn't linked in, which is not possible because other categories defined in this file are used just fine.
Thanks
Ookay. I had the same problem, but with a different outcome. Briefly, the problem was in my project file. The category files showed up in the project navigator - I can load/edit, etc. But the linker did not know to link with them. The way I found this was pulling on another thread - creating a dummy concrete class in my category files to force the linker to include them. No luck. Then I tried to instantiate an instance of the dummy class in my app. Eureka - I now get a linker error! So, I simply removed and re-added the category files to the project and now all is well. Not sure how the project file got out of whack ( svn merge? ), but there it is.
Delete the Category files and add them again checking the target.
Solved for me.