CGImageSourceRef memoryleak - cocoa

NSDictionary* result = nil;
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)[self TIFFRepresentation], NULL);
if ( NULL == source )
{
}
else
{
CFDictionaryRef metadataRef = CGImageSourceCopyPropertiesAtIndex (source, 0, NULL);
if (metadataRef)
{
NSDictionary* immutableMetadata = (__bridge NSDictionary *)metadataRef;
if (immutableMetadata)
{
result = [NSDictionary dictionaryWithDictionary : (__bridge NSDictionary *)metadataRef];
}
CFRelease(metadataRef);
metadataRef = nil;
}
CFRelease(source);
source = nil;
}
return result;
I am using XCode with ARC.
This code causes my app to leak memory when i run it on many images in a loop.
Does anybody know what i did wrong?

wrapping #autoreleasepool around code solved the problem. Images were about 1.2MB

Related

macOS SearchKit CoreService found nothing

im working on an that search in the content of allot of files, i planed to use SearchKit but i can't figure out to make Apple's sample code to work, and i can't find any other ressources (NSHipster code didn't work either), here's my code:
#define kSearchMax 1000
#interface ViewController()
#property(nonatomic) SKIndexRef mySKIndex;
#end
#implementation ViewController
#synthesize mySKIndex;
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[self openIndex];
[self addDoc];
SKIndexFlush(self.mySKIndex);
// i thought that the indexation may need some time ..
sleep(2);
dispatch_async(dispatch_get_main_queue(), ^{
[self searchterm:#"var"];
});
});
}
- (void) openIndex {
NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent:#"index"] stringByAppendingPathExtension:#"txt"]; // 1
NSURL *url = [NSURL fileURLWithPath:path];
NSString *name = #"extension_index";
if ([name length] == 0) name = nil;
SKIndexType type = kSKIndexInverted;
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
mySKIndex = SKIndexOpenWithURL ((__bridge CFURLRef) url,
(__bridge CFStringRef) name,
true
);
}else{
self.mySKIndex = SKIndexCreateWithURL((__bridge CFURLRef) url,
(__bridge CFStringRef) name,
(SKIndexType) type,
(CFDictionaryRef) NULL);
}
}
- (void) addDoc {
SKLoadDefaultExtractorPlugIns ();
NSString *path = [NSBundle.mainBundle pathForResource:#"Products" ofType:#"rtf"]; // 1
NSURL *url = [NSURL fileURLWithPath: path]; // 2
SKDocumentRef doc = SKDocumentCreateWithURL ((__bridge CFURLRef) url);
NSString *mimeTypeHint = #"text/rtf";
BOOL added = SKIndexAddDocument ((SKIndexRef) mySKIndex,
(SKDocumentRef) doc,
(__bridge CFStringRef)mimeTypeHint,
(Boolean) true
);
NSLog(added ? #"added" : #"not added");
}
- (void) searchterm:(NSString*)query{
SKSearchOptions options = kSKSearchOptionDefault;
BOOL more = YES;
UInt32 totalCount = 0;
SKSearchRef search = SKSearchCreate (mySKIndex,
(__bridge CFStringRef) query,
options);
while (more) {
SKDocumentID foundDocIDs [kSearchMax];
float foundScores [kSearchMax];
float *scores;
Boolean unranked =
options & kSKSearchOptionNoRelevanceScores;
if (unranked) {
scores = NULL;
} else {
scores = foundScores;
}
CFIndex foundCount = 0;
more = SKSearchFindMatches (
search,
kSearchMax,
foundDocIDs,
scores,
100,
&foundCount
);
NSLog(#"%#", [NSString stringWithFormat:#"current count = %i", totalCount]);
totalCount += foundCount;
}
}
#end
it always print "current count = 0" and the loop is executed only one time.

can't figure why insert sqlite sql statement is not being executed , Xcode

everything looks good for me, but the prepare_v2 doesn't get SQLITE_OK
the sql instruction is pretty basic, if I copy and paste it on the sqlite manager, it inserts fine
is there anything I am missing?
//from view controller
- (void)viewDidLoad
{
[super viewDidLoad];
DBConnection* dbCon = [DBConnection alloc];
[dbCon init];
[dbCon InsertDataRollNo:#"888"];
}
-(id)init
{
//[super init];
DBName = #"FoodDB2.sqlite";
NSArray* documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDir = [documentsPath objectAtIndex:0];
DBPath = [documentsDir stringByAppendingPathComponent:DBName];
return self;
}
-(void)InsertDataRollNo:(NSString*)theName
{
[self CheckAndCreateDB];
sqlite3* database;
if(sqlite3_open([DBPath UTF8String], &database)== SQLITE_OK)
{
NSString* statement;
sqlite3_stmt* compliedStatement;
//statement = [[NSString alloc]initWithFormat:#"insert into Category(TheName)values('%d')",#"epa"];
statement = #"insert into Category(TheName)values('aaa')";
const char* sqlStatement = [statement UTF8String];
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compliedStatement, NULL) == SQLITE_OK)
{
if(SQLITE_DONE!=sqlite3_step(compliedStatement))
{
NSAssert1(0,#"Error by inserting '%s' ", sqlite3_errmsg(database));
}
else
{
NSAssert1(0,#"cool '%s' ", #"ope");
}
}
sqlite3_finalize(compliedStatement);
}
sqlite3_close(database);
}
-(void)CheckAndCreateDB
{
BOOL success;
NSFileManager* fileManager = [NSFileManager defaultManager];
success = [fileManager fileExistsAtPath:DBPath];
if(success) return;
NSString* databasePathFromApp = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:DBName];
[fileManager copyItemAtPath:databasePathFromApp toPath:DBPath error:nil];
//[fileManager release];
}
I figure it out, actually I was not copying the sqlite file to iPhone project, running good now

How to identify a NSData's image format?

If I get a NSData which I know it's a image's data.But I don't know what format it is.
So how can I identify which image format is it?Jpeg or PNG?
PS:iOS
I used Mats answer to build a simple category on NSData which tells me if its content is JPEG or PNG based on its first 4 bytes:
#interface NSData (yourCategory)
- (BOOL)isJPG;
- (BOOL)isPNG;
#end
#implementation NSData (yourCategory)
- (BOOL)isJPG
{
if (self.length > 4)
{
unsigned char buffer[4];
[self getBytes:&buffer length:4];
return buffer[0]==0xff &&
buffer[1]==0xd8 &&
buffer[2]==0xff &&
buffer[3]==0xe0;
}
return NO;
}
- (BOOL)isPNG
{
if (self.length > 4)
{
unsigned char buffer[4];
[self getBytes:&buffer length:4];
return buffer[0]==0x89 &&
buffer[1]==0x50 &&
buffer[2]==0x4e &&
buffer[3]==0x47;
}
return NO;
}
#end
And then, simply do a :
CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData((CFDataRef) imgData);
CGImageRef imgRef = nil;
if ([imgData isJPG])
imgRef = CGImageCreateWithJPEGDataProvider(imgDataProvider, NULL, true, kCGRenderingIntentDefault);
else if ([imgData isPNG])
imgRef = CGImageCreateWithPNGDataProvider(imgDataProvider, NULL, true, kCGRenderingIntentDefault);
UIImage* image = [UIImage imageWithCGImage:imgRef];
CGImageRelease(imgRef);
CGDataProviderRelease(imgDataProvider);
You could look at the first bytes and make a guess. There are many lists of magic numbers available on the internet, e.g. http://www.astro.keele.ac.uk/oldusers/rno/Computing/File_magic.html.
Here's a Swift version of the #apouche's answer:
extension NSData {
func firstBytes(length: Int) -> [UInt8] {
var bytes: [UInt8] = [UInt8](count: length, repeatedValue: 0)
self.getBytes(&bytes, length: length)
return bytes
}
var isJPEG: Bool {
let signature:[UInt8] = [0xff, 0xd8, 0xff, 0xe0]
return firstBytes(4) == signature
}
var isPNG: Bool {
let signature:[UInt8] = [0x89, 0x50, 0x4e, 0x47]
return firstBytes(4) == signature
}
}
Can you create an image from that and then just ask that NSImage what format it is?
You can use -initWithData to create the NSImage, for more, see http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSImage_Class/Reference/Reference.html
You can create CGImageSourceRef and then ask it for image type
CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef) imageData, NULL);
if(imageSource)
{
// this is the type of image (e.g., public.jpeg - kUTTypeJPEG )
// <MobileCoreServices/UTCoreTypes.h>
CFStringRef UTI = CGImageSourceGetType(imageSource);
CFRelease(imageSource);
}
imageSource = nil;
If you use UIImage imageWithData, you don't need to know if the data is png or jpg.
// read from file
NSData * thumbnailData = [decoder decodeObjectForKey:kThumbnailKey];
[UIImage imageWithData:thumbnailData];

Is it possible to airprint a fullpage UIScrollview?

I fall into this problem for a long time. as I asked, I can print the scrollview but only a part of it, not the full size view "contentView".
the code is like this:
if ([UIPrintInteractionController isPrintingAvailable])
{
UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController];
UIGraphicsBeginImageContext(sv.contentSize);
[sv.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *myData = [NSData dataWithData:UIImagePNGRepresentation(viewImage)];
if(pic && [UIPrintInteractionController canPrintData: myData] ) {
pic.delegate =(id<UIPrintInteractionControllerDelegate>) self;
UIPrintInfo *printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGeneral;
printInfo.jobName = [NSString stringWithFormat:#"QFTicket-%#",self.payment.id];
printInfo.duplex = UIPrintInfoDuplexLongEdge;
pic.printInfo = printInfo;
pic.showsPageRange = YES;
pic.printingItem = myData;
pic.printFormatter=[sv viewPrintFormatter];
void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
if (!completed && error) {
NSLog(#"FAILED! due to error in domain %# with error code %u", error.domain, error.code);
}
};
[pic presentAnimated:YES completionHandler:completionHandler];
}
}
Am I missing something?
thx

Removing url fragment from NSURL

I'm writing a Cocoa application, which uses NSURLs -- I need to remove the fragment portion of the URL (the #BLAH part).
example: http://example.com/#blah should end up as http://example.com/
I found some code in WebCore that seems to do it by using CFURL functionality, but it never finds the fragment portion in the URL. I've encapsulated it in a extension category:
-(NSURL *)urlByRemovingComponent:(CFURLComponentType)component {
CFRange fragRg = CFURLGetByteRangeForComponent((CFURLRef)self, component, NULL);
// Check to see if a fragment exists before decomposing the URL.
if (fragRg.location == kCFNotFound)
return self;
UInt8 *urlBytes, buffer[2048];
CFIndex numBytes = CFURLGetBytes((CFURLRef)self, buffer, 2048);
if (numBytes == -1) {
numBytes = CFURLGetBytes((CFURLRef)self, NULL, 0);
urlBytes = (UInt8 *)(malloc(numBytes));
CFURLGetBytes((CFURLRef)self, urlBytes, numBytes);
} else
urlBytes = buffer;
NSURL *result = (NSURL *)CFMakeCollectable(CFURLCreateWithBytes(NULL, urlBytes, fragRg.location - 1, kCFStringEncodingUTF8, NULL));
if (!result)
result = (NSURL *)CFMakeCollectable(CFURLCreateWithBytes(NULL, urlBytes, fragRg.location - 1, kCFStringEncodingISOLatin1, NULL));
if (urlBytes != buffer) free(urlBytes);
return result ? [result autorelease] : self;
}
-(NSURL *)urlByRemovingFragment {
return [self urlByRemovingComponent:kCFURLComponentFragment];
}
This is used as such:
NSURL *newUrl = [[NSURL URLWithString:#"http://example.com/#blah"] urlByRemovingFragment];
unfortunately, newUrl ends up being "http://example.com/#blah" because the first line in urlByRemovingComponent always returns kCFNotFound
I'm stumped. Is there a better way of going about this?
Working Code, thanks to nall
-(NSURL *)urlByRemovingFragment {
NSString *urlString = [self absoluteString];
// Find that last component in the string from the end to make sure to get the last one
NSRange fragmentRange = [urlString rangeOfString:#"#" options:NSBackwardsSearch];
if (fragmentRange.location != NSNotFound) {
// Chop the fragment.
NSString* newURLString = [urlString substringToIndex:fragmentRange.location];
return [NSURL URLWithString:newURLString];
} else {
return self;
}
}
How about this:
NSString* s = #"http://www.somewhere.org/foo/bar.html/#label";
NSURL* u = [NSURL URLWithString:s];
// Get the last path component from the URL. This doesn't include
// any fragment.
NSString* lastComponent = [u lastPathComponent];
// Find that last component in the string from the end to make sure
// to get the last one
NSRange fragmentRange = [s rangeOfString:lastComponent
options:NSBackwardsSearch];
// Chop the fragment.
NSString* newURLString = [s substringToIndex:fragmentRange.location + fragmentRange.length];
NSLog(#"%#", s);
NSLog(#"%#", newURLString);
This is quite an old question, and it has already been answered, but for another simple option this is how I did it:
NSString* urlAsString = [myURL absoluteString];
NSArray* components = [urlAsString componentsSeparatedByString:#"#"];
NSURL* myURLminusFragment = [NSURL URLWithString: components[0]];
if there is no fragment, urlMinusFragment will be the same as myURL
Swift 3.0
this will remove the fragment
if let fragment = url.fragment{
url = URL(string: url.absoluteString.replacingOccurrences(of: "#\(fragment)", with: "")!
}

Resources