Spika-iOS : "incompatible block pointer types" - ios

I have downloaded the 'Spika' script for iOS and Android but have run into the following issue. When trying to compile I get the following error :
Incompatible block pointer types sending 'int (^)(ModelMessage *__strong, ModelMessage *__strong)' to parameter of type 'NSComparator' (aka 'NSComparisonResult (^)(__strong id, __strong id)')
I have tried to resolve the issue by changing it to NSComparisonResult but cannot seem to get my head around what the issue is.
Here is the code :
NSMutableArray *removeTarget = [[NSMutableArray alloc] init];
for(int i = 0; i < [result count] ; i++){
ModelMessage *message = [result objectAtIndex:i];
if(message.valid == NO)
[removeTarget addObject:message];
}
for(int ii = 0; ii < [removeTarget count] ; ii++){
[result removeObject:[removeTarget objectAtIndex:ii]];
}
NSArray *sortedAry = [result sortedArrayUsingComparator:^(ModelMessage *a, ModelMessage *b) {
return a.modified> b.modified;
}];
int fetchNum = PagingMessageFetchNum;
if(fetchNum > sortedAry.count)
fetchNum = sortedAry.count;
return sortedAry;
//return [sortedAry subarrayWithRange:NSMakeRange(0, fetchNum)];
}
The issue lies in :
NSArray *sortedAry = [result sortedArrayUsingComparator:^(ModelMessage *a, ModelMessage *b) {
return a.modified> b.modified;
Any help would be greatly appreciated. Thanks guys.

You should return not a BOOL result as in your code above.
The result must be of type NSComparisonResult which is enum
enum {
NSOrderedAscending = -1,
NSOrderedSame,
NSOrderedDescending
};
In your case the sorting block should look like that
NSArray *sortedAry = [result sortedArrayUsingComparator:^(ModelMessage *a, ModelMessage *b) {
if(a.modified<b.modified)
return NSOrderedAscending;
else if(a.modified>b.modified)
return NSOrderedDescending;
else
return NSOrderedSame;
}];

Related

NSString containsString crashes

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
}
}

how to get iPhone App Crash Log file from iPhone programmatically

Is there a way to access iphone crash log file via programmatically. I trying to write a crash report feature that when you launch the app after a crash, it will offer to send the crash report to the server. I can't find how to get the crash log within the app.
You can use the following logic for the same.
aslmsg q, m;
int i;
const char *key, *val;
float how_old = fTime ;
q = asl_new(ASL_TYPE_QUERY);
asl_set_query(q, ASL_KEY_LEVEL, strLoggerLevel ,ASL_QUERY_OP_LESS_EQUAL);
asl_set_query(q, ASL_KEY_FACILITY, [#"YourBundleIdOfAPP" UTF8String] ,ASL_QUERY_OP_EQUAL);
asl_set_query(q, ASL_KEY_TIME, [[NSString stringWithFormat:#"%.f", [[NSDate date] timeIntervalSince1970] - how_old] UTF8String], ASL_QUERY_OP_GREATER_EQUAL);
int goInside=0;
aslresponse r = asl_search(NULL, q);
while (NULL != (m = aslresponse_next(r)))
{
NSString *cValueToWrite;
NSMutableDictionary *tmpDict = [NSMutableDictionary dictionary];
for (i = 0; (NULL != (key = asl_key(m, i))); i++)
{
//get the only required fields
if(i==12 || i==10 || i==11 || i==8 || i==9 ||i==3)
{
NSString *keyString = [NSString stringWithUTF8String:(char *)key];
val = asl_get(m, key);
NSString *string = [NSString stringWithUTF8String:val];
[tmpDict setObject:string forKey:keyString];
}
}
cValueToWrite=[[NSString alloc]initWithFormat:#"\n--------------[Debug]----------------\nDateTime: %#\nApplication: %#\nInfo: %#",[tmpDict valueForKey:#"CFLog Local Time"],[tmpDict valueForKey:#"Sender"],[tmpDict valueForKey:#"Message"]];
}
strLoggerLevel is the NSString which holds the logger type which you want which ranges upto 7.

incompatible block pointer types objectsPassingTest:

I want to get filtred NSSet:
NSSet* contents = [self.content objectsPassingTest:^(id obj, BOOL* stop){
NSNumber* chapterNo = ((LTContent*)obj).chapterNo;
return [chapterNo integerValue] < 0;
}];
But this code fires an error: incompatible block pointer types sending 'int (^)(id, BOOL *)' to parameter of type 'BOOL (^)(id, BOOL *)
If I change code:
NSSet* contents = [self.content objectsPassingTest:^(id obj, BOOL* stop){
NSNumber* chapterNo = ((LTContent*)obj).chapterNo;
BOOL a = [chapterNo integerValue] < 0;
return a;
}];
it works perfect. But I don't want to use odd line. What's wrong in first snippet?
You forgot block's return type:
NSSet* contents = [self.content objectsPassingTest:^BOOL(id obj, BOOL* stop) {
Specify the explicit return type BOOL for the block:
NSSet* contents = [set objectsPassingTest:^BOOL(id obj, BOOL* stop) {
// ...
return [chapterNo integerValue] < 0;
}];
Otherwise the compiler derives the return type from the
return statement, and that is int in your case.

Parsing a NSString to a byte array

I need to parse an NSString to a byte array and am having some trouble doing it. I have a padded byte array in a method and convert that into a mutablestring, then I have a method that needs to place those numbers back into a byte array.
In C# it would be as simple as:
do
{
val = byte.Parse(str.Substring(i, 3));
byteArr[j++] = val;
i += 3;
}
Here is the code snippit Note** Ive been trying a lot of different things in the do loop so its a mess in there right now:
-(NSData*) StrToByteArray: (NSString*)str
{
NSLog(#"StrToByteArray. String: %#", str);
if([str length]==0)
NSLog(#"Invailid String");
int val;
Byte byteArr[[str length]/3];
int i = 0;
int j = 0;
NSRange range;
do {
range = NSMakeRange(i, 3);
val = (int)[str substringFromIndex:i];
NSLog(#"StrToByteArray. VAR: %i", val);
byteArr[j++] = val;
NSLog(#"byteArr: %i",byteArr[i]);
i+=3;
}while(i<str.length);
NSData* wrappedByteArr = [NSData dataWithBytes:&byteArr length: sizeof(byteArr)];
return wrappedByteArr;
}
Here is the loop that makes the padded string:
for(int i = 0; i<=len;i++)
{
val = byteArr[i];
NSLog(#"byteArr to string original: %i", val);
if(val<(Byte)10)
{
[tempStr appendString:(#"00")];
[tempStr appendString:[NSString stringWithFormat:#"%d",val]];
}
else if(val<(Byte)100)
{
[tempStr appendString:(#"0")];
[tempStr appendString:[NSString stringWithFormat:#"%d",val]];
}
else {
[tempStr appendString:[NSString stringWithFormat:#"%d",val]];
}
}
NSLog(#"string: %#", tempStr);
return tempStr;
Take 2
Now that I know what the data looks like and how you want to parse it, I would approach it like this:
- (NSData *) parseStringToData:(NSString *) str
{
if ([str length] % 3 != 0)
{
// raise an exception, because the string's length should be a multiple of 3.
}
NSMutableData *result = [NSMutableData dataWithLength:[str length] / 3];
unsigned char *buffer = [result mutableBytes];
for (NSUInteger i = 0; i < [result length]; i++)
{
NSString *byteString = [str substringWithRange:NSMakeRange(i * 3, 3)];
buffer[i] = [byteString intValue];
}
return result;
}
Edit:
Your padding method could be simplified as well by providing the correct format specifier that automatically pads integers.
for(int i = 0; i<=len;i++)
{
val = byteArr[i];
NSLog(#"byteArr to string original: %i", val);
[tempStr appendFormat:#"%03d", val];
}

when I use git clone to get a git from the remote, the git_index_entrycount return 0?

I use git_repository_index to get the index first ,and then I use git_index_entrycount to see how many index items in it , but the result is 0? why? Below is my code, what's wrong with it? Thx
(void)viewDidLoad
{
[super viewDidLoad];
git_repository *repo;
progress_data pd = {{0}};
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [array objectAtIndex:0];
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT;
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
checkout_opts.progress_cb = checkout_progress;
checkout_opts.progress_payload = &pd;
clone_opts.checkout_opts = checkout_opts;
clone_opts.fetch_progress_cb = &fetch_progress;
clone_opts.fetch_progress_payload = &pd;
clone_opts.cred_acquire_cb = cred_acquire;
NSString *pp = [docPath stringByAppendingPathComponent:#"/abc" ];
const char * a =[pp UTF8String];
int res = git_clone(&repo, "http://path/.git", a, &clone_opts);
NSLog(#"Get it. res:%d\n path:%s", res, a);
//get index
int ret;
git_index* index;
ret = git_repository_index(&index, repo);
NSLog(#"git_repository_index ret:%d", ret);
int count = git_index_entrycount(index);
if(count != 0)
{
NSLog(#"index number:%d", count);
}
else
{
NSLog(#"count == 0");
}
const git_error *err = giterr_last();
if(err == NULL)
{
NSLog(#"NULL");
}
else
{
NSLog(#"err:%s", err->message);
}
}
On order to trigger the checkout as part of the git_clone() process, have you considered using
GIT_CHECKOUT_SAFE_CREATE as the checkout_strategy?
Both this commit and the the git_checkout() documentation hint about this.

Resources