What is the meaning of MCOConnectionLogType to -1? - mailcore2

What is the meaning of MCOConnectionLogType to -1?
In the process of sending,the following code:
smtpSess.connectionLogger = ^(void * connectionID, MCOConnectionLogType type, NSData * data){
// NSLog(#"connectionID==>%#",connectionID);
NSLog(#"type==>%i",type);
NSLog(#"data==>%#",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
};

Related

How to format string encoded with NSASCIIStringEncoding

In my Objective-C project, I'm fetching a key from cloudKit and wanted to format it before like this and wondering what's wrong with the formatting,
[cloudKitDB performQuery:query inZoneWithID:nil completionHandler:^(NSArray<CKRecord *> * _Nullable results, NSError * _Nullable error) {
NSString *key = [[NSString alloc] initWithData:[results.firstObject objectForKey:#"keyvalue"] encoding:NSASCIIStringEncoding];
NSLog(#"First Key Output: %#",key);
NSLog(#"Second Key Output: %#",key);
NSString *formattedKey = [NSString stringWithFormat:#"%#%#",[key stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]], #"1234"];
NSLog(#"Formatted Key: %#",formattedKey);
And here my logged
2020-08-15 21:08:14.704650+0700 myapp[2208:79554] First Key Output: ADEvXp2F2BFJ2E4Lm2dSnYvHENhkFrK8
2020-08-15 21:08:14.704828+0700 myapp[2208:79554] Second Key Output: ADEvXp2F2BFJ2E4Lm2dSnYvHENhkFrK8
2020-08-15 21:08:14.705456+0700 myapp[2208:79554] Formatted Key: ADEvXp2F2BFJ2E4Lm2dSnYvHENhkFrK8
Although, I have tried to trim whitespace but still no luck!
Thanks
This is a strange problem, but I can reproduce it with the code below.
Based on this I still suspect that there are some funnies behind the string and have given ways to fix it in the code.
// Note C strlen will stop at the first 0
char * s = "3Lm9dGmeTf3Lm9dGmeTf3Lm9dGmeTfdd\0\0\0";
NSData * data = [NSData dataWithBytes:s length:strlen( s ) + 2];
NSString * key = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSString * keyFormatted = [NSString stringWithFormat:#"%#%#", key, #"1234"];
NSLog ( #"Key : %#", key );
NSLog ( #"Formatted key: %#", keyFormatted );
// Use strlen to get rid of funnies
NSData * dataFixed = [data subdataWithRange:NSMakeRange( 0, strlen( s ) )];
NSString * keyFixed = [[NSString alloc] initWithData:dataFixed encoding:NSASCIIStringEncoding];
NSString * keyForm2 = [NSString stringWithFormat:#"%#%#", keyFixed, #"1234"];
NSLog ( #"Fixed key : %#", keyFixed );
NSLog ( #"Formatted key: %#", keyForm2 );
// Use C isprint to trim ... crude but works
while ( key.length && ! isprint ( [key characterAtIndex:key.length - 1] ) )
{
key = [key substringToIndex:key.length - 1];
}
keyFormatted = [NSString stringWithFormat:#"%#%#", key, #"1234"];
NSLog ( #"Key : %#", key );
NSLog ( #"Formatted key: %#", keyFormatted );

Unable to convert UTF-8 text from NSDictionary in Objective-C

Im using foursquare API to get some locations around me, but when the name of that place wasn't in english, the name will be like follows:
name = "\U0645\U0633\U062c\U062f \U0627\U0644\U0633\U064a\U062f\U0629 \U0639\U0627\U0626\U0634\U0629 | Aisha Mosque";
i tried to convert the response to a UTF-8 but nothing changed.
Here is my code:
-(void)setUpLocations{
NSURL *url = [NSURL URLWithString: #"https://api.foursquare...."];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSLog(#"Response: %#",[[[json objectForKey:#"response"]objectForKey:#"groups"]valueForKey:#"items"]);
}
And the log result is:
contact = {
};
id = 51712507498ec4e8c5ae9f48;
likes = {
count = 0;
groups = (
);
};
location = {
address = Abdoun;
cc = JO;
city = Amman;
country = Jordan;
distance = 3819;
lat = "31.95406043797281";
lng = "35.88095228186612";
};
name = "\U0645\U0633\U062c\U062f \U0627\U0644\U0633\U064a\U062f\U0629 \U0639\U0627\U0626\U0634\U0629 | Aisha Mosque";
restricted = 1;
stats = {
checkinsCount = 43;
tipCount = 2;
usersCount = 23;
};
verified = 0;
},
Any Suggestions ??
EDIT:
here is how i extract the data from the dictionary:
NSDictionary *dic = [[[[json objectForKey:#"response"]objectForKey:#"groups"]valueForKey:#"items"] copy];
namesArray = [[NSArray alloc]initWithArray:[self removeWhiteSpaces:[dic valueForKey:#"name"]]];
-(NSArray *)removeWhiteSpaces:(NSDictionary *)dic{
NSString *str = [NSString stringWithFormat:#"%#",dic];
NSString *str2 = [str stringByReplacingOccurrencesOfString:#"\n" withString:#""];
NSString *secondString = [str2 stringByReplacingOccurrencesOfString:#" " withString:#""];
NSString *thirdString = [secondString stringByReplacingOccurrencesOfString:#"(" withString:#""];
NSString *forthString = [thirdString stringByReplacingOccurrencesOfString:#")" withString:#""];
NSString *fifthString = [forthString stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSArray *items = [fifthString componentsSeparatedByString:#","];
return items;
}
And in the UITableView:
cell.textLabel.text = [NSString stringWithFormat:#"Name: %# ",[namesArray objectAtIndex:indexPath.row] ];
Update
After trying #Martin R answer i got the same results:
NSDictionary *dic = [[[[json objectForKey:#"response"]objectForKey:#"groups"]valueForKey:#"items"] copy];
NSString *value =[dic valueForKey:#"name"];
NSLog(#"%#", value);
UILabel *lbl = [[UILabel alloc]initWithFrame:self.view.frame];
lbl.numberOfLines = 0;
lbl.text = [NSString stringWithFormat:#"%#",value];;
[self.view addSubview:lbl];
and here is an image of the result
There is no problem.
NSLog() calls the description method of NSDictionary and NSArray, and that prints all non-ASCII characters as \Unnnn escape sequence.
If you extract the string values from the dictionary and print that you will see
that everything is correct.
Simple example:
NSDictionary *dict = #{ #"currency": #"€" };
NSLog(#"%#", dict);
// Output: { currency = "\U20ac"; }
NSString *value = dict[#"currency"];
NSLog(#"%#", value);
// Output: €
UPDATE: The problem seems to be in your removeWhiteSpaces: method, because
NSString *str = [NSString stringWithFormat:#"%#",dic];
already uses the description method to convert the dictionary to a string,
and the following stringByReplacingOccurrencesOfString calls are a (sorry!) very bad
method to fix that.
You should access the dictionary keys with objectForKey instead, or enumerate
the dictionary with for (NSString *key in dic) { ... } and build the desired
array.
UPDATE 2: From the JSON data (posted in chat discussion) it seem that you just need
NSArray *itemsArray = json[#"response"][#"groups"][0][#"items];
NSArray *namesArray = [itemsArray valueForKey:#"name"];
Note that "groups" is an array with one element.
Try to use this one..
[NSString stringWithUTF8String:]

Copying contents of uint8_t[] into an NSString

I have a uint_8[] array of characters and I'd like to convert it to an NSString but I'm getting NULL back. What's the proper way to convert between these two types?
// Defined else where as:
uint8_t someValue[8];
someValue is not NULL and contains some valid characters
I've tried:
NSLog(#"converted using CString: %#", [NSString stringWithCString:(char const *)someValue encoding:NSUTF8StringEncoding]);
as well as:
NSMutableData *data = [[NSMutableData alloc] init];
[data appendBytes:someValue length:sizeof(someValue)];
converted = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"converted using NSData: %#", converted);
Using:
[NSString stringWithCString:(char const *)someValue encoding:NSUTF8StringEncoding];
only works if there is a null terminator in the someValue array.
Your other solution doesn't work because sizeof(someValue) does not return the number of characters in the array, it returns the size of the uint8_t pointer.
You can use:
NSUInteger len = ... // the actual number of characters in someValue
NSString *str = [[NSString alloc] initWithBytes:someValue length:len encoding:NSUTF8StringEncoding];
Of course this requires that you know how many characters are really in the array.

Encode and Decode a string on Objective C

I use below code to encode and decode a string on objective C. The encoding is good, I debug and see that it throw a hash string when input is #"1". But when I try to decode this hash string, it return nil.
Please help me.
+(NSString *)encrypt: (NSString*) input
{
//Base64 Encoding
char base64Result[32];
size_t theResultLength = 32;
Base64EncodeData(input, 20, base64Result, &theResultLength);
NSData *theData = [NSData dataWithBytes:base64Result length:theResultLength];
NSString *base64EncodedResult = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
NSString* decryptedString = [self decrypt:base64EncodedResult];
return [base64EncodedResult autorelease];
}
+ (NSString *) decrypt:(NSString*) input{
Byte inputData[[input lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];//prepare a Byte[]
[[input dataUsingEncoding:NSUTF8StringEncoding] getBytes:inputData];//get the pointer of the data
size_t inputDataSize = (size_t)[input length];
size_t outputDataSize = EstimateBas64DecodedDataSize(inputDataSize);//calculate the decoded data size
Byte outputData[outputDataSize];//prepare a Byte[] for the decoded data
Base64DecodeData(inputData, inputDataSize, outputData, &outputDataSize);//decode the data
NSData *theData = [[NSData alloc] initWithBytes:outputData length:outputDataSize];//create a NSData object from the decoded data
NSString *result = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
return [result autorelease];
}
In you encoding method, you have to convert the input string to a byte buffer and feed that to Base64EncodeData:
NSData *inputData = [input dataUsingEncoding:NSUTF8StringEncoding];
Base64EncodeData([inputData bytes], [inputData length], base64Result, &theResultLength, NO);
(The NSString *input argument in the encoding method points to an Objective-C structure, not to a C string. So your encoding method seems to work. It encodes something, but not the input string. The decoding method then fails at
NSString *result = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
because the decoded data does not contain valid UTF-8.)

iOS - object sent autorelease too many times

I have a method that is reading some information from a sqlite db and initialising a class called Achievement. When I analyse this code I am given the feedback 'object sent autorelease too many times'. I don't really understand where I am going wrong - why is the retval object released on line 225 and not at the return statement on line 229?
Can someone please explain where I have made a mistake in the code below and how I can fix it?
Function Code (so answerer can easily copy/paste):
- (Achievement *)getAchievement:(int)Id
{
Achievement *retval = [[Achievement alloc] autorelease];
NSString *query = [NSString stringWithFormat:#"SELECT * FROM Achievements where ID = %d", Id];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil)
== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
int Id = sqlite3_column_int(statement, 0);
char *name = (char *) sqlite3_column_text(statement, 1);
char *title = (char *) sqlite3_column_text(statement, 2);
char *description = (char *) sqlite3_column_text(statement, 3);
Boolean Achieved;
char *com = (char *) sqlite3_column_text(statement, 4);
NSString *c1 = [[[NSString alloc] initWithUTF8String:com] autorelease];
Achieved = [c1 isEqualToString:#"1"];
NSDate *CompletedDate = (NSDate *) sqlite3_column_text(statement, 5);
char *icon = (char *) sqlite3_column_text(statement, 6);
int New = sqlite3_column_int(statement, 7);
NSString *Title = [[[NSString alloc] initWithUTF8String:title] autorelease];
NSString *Description = [[[NSString alloc] initWithUTF8String:description] autorelease];
NSString *Name = [[[NSString alloc] initWithUTF8String:name] autorelease];
NSString *Icon = [[[NSString alloc] initWithUTF8String:icon] autorelease];
retval = [retval initDetails:Id :Name :Title: Description : Achieved : CompletedDate: Icon: New];
}
sqlite3_finalize(statement);
}
return retval;
}
Analysis feedback image:
As always any feedback is greatly appreciated.
Achievement *retval = [[Achievement alloc] autorelease];
this is very bad idea to do that. You ALWAYS have to initialize object before using it.
Instead you're initializing it in a loop:
retval = [retval initDetails:Id :Name :Title: Description : Achieved : CompletedDate: Icon: New];
I don't really get why you need to initialize the same object multiple times. Maybe, you need to create multiple objects and init them with different values?
Rearrange this:
Achievement *retval = nil;
while (...) {
[retval release];
retval = [[Achievement alloc] initDetails: ...];
}
return [retval autorelease];
I guess you're confusing the compiler with the wrong sequence of alloc, init, autorelease. What you should be doing instead is the following (pseudocode):
Achievement *retval = nil;
while (...) {
retval = [[[Achievement alloc] initDetails: ...] autorelease];
}
return retval;