-3

I am making a Mac app, entirely in Swift. Now, I need to add an Objective-C function to the app, but I can't figure out how. I have very little knowledge about Objective-C, but I need to add this pdf-making function to my app:

void MyCreatePDFFile (CGRect pageRect, const char *filename)// 1
{
CGContextRef pdfContext;
CFStringRef path;
CFURLRef url;
CFDataRef boxData = NULL;
CFMutableDictionaryRef myDictionary = NULL;
CFMutableDictionaryRef pageDictionary = NULL;

path = CFStringCreateWithCString (NULL, filename, // 2
                            kCFStringEncodingUTF8);
url = CFURLCreateWithFileSystemPath (NULL, path, // 3
                 kCFURLPOSIXPathStyle, 0);
CFRelease (path);
myDictionary = CFDictionaryCreateMutable(NULL, 0,
                    &kCFTypeDictionaryKeyCallBacks,
                    &kCFTypeDictionaryValueCallBacks); // 4
CFDictionarySetValue(myDictionary, kCGPDFContextTitle, CFSTR("My PDF File"));
CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("My Name"));
pdfContext = CGPDFContextCreateWithURL (url, &pageRect, myDictionary); // 5
CFRelease(myDictionary);
CFRelease(url);
pageDictionary = CFDictionaryCreateMutable(NULL, 0,
                    &kCFTypeDictionaryKeyCallBacks,
                    &kCFTypeDictionaryValueCallBacks); // 6
boxData = CFDataCreate(NULL,(const UInt8 *)&pageRect, sizeof (CGRect));
CFDictionarySetValue(pageDictionary, kCGPDFContextMediaBox, boxData);
CGPDFContextBeginPage (pdfContext, pageDictionary); // 7
myDrawContent (pdfContext);// 8
CGPDFContextEndPage (pdfContext);// 9
CGContextRelease (pdfContext);// 10
CFRelease(pageDictionary); // 11
CFRelease(boxData);
}

(That code is from Apple's documentation.)

How can I bridge that code to Swift, and how do I call it from my Swift view controller?

Edit: I'm using Swift 3 and Xcode 8 beta 5.

owlswipe
  • 19,159
  • 9
  • 37
  • 82
  • 2
    See this http://stackoverflow.com/questions/24002369/how-to-call-objective-c-code-from-swift – Onur Tuna Sep 04 '16 at 16:11
  • @OnurTuna I tried that, it didn't seem to work, because that's for using Objective-C objects with Swift (which I think are different from methods), when I tried putting my big function inside ` @implementation CustomObject` I was unable to call it from my Swift file and also had some errors that forced me to change the code. In short, it didn't really work. – owlswipe Sep 04 '16 at 16:17
  • @matt It comes from the Apple documentation for *Mac* PDF creation! Also, I have `CGRect`s elsewhere in my Mac app's code—with no error. Here's an example Mac Stack Overflow question that has CGRect if you need more evidence: http://stackoverflow.com/questions/18710933/objective-c-how-to-rotate-cgrect. But thanks for your answer, let me try it out. – owlswipe Sep 04 '16 at 16:48
  • Actually that is C, not Objective-C. You can put the code in a .c file, the function prototype in a .h file, and include the .h file from the bridging header, in the same way as you would with including Objective-C code. – But what do you expect `myDrawContent (pdfContext);` to do? Where should that function come from? – Martin R Sep 04 '16 at 16:52
  • @MartinR I would have assumed `myDrawContent` was part of Quartz (which I'm also importing in the H file). But I guess I don't know! It's not really clear in the documentation. Here's what I'm trying to do: http://stackoverflow.com/questions/39135233/create-a-paginated-pdf-swift-3-os-x – owlswipe Sep 04 '16 at 16:58
  • @JohnRamos: That is the *real* problem. That function is a stub in the sample code, where the actual drawing into the PDF context happens. So where should the PDF content be created? If you want the drawing to be done in Swift then it would be far easier to translate the C code to Swift. – Martin R Sep 04 '16 at 17:00
  • @MartinR Ok, I just really don't know what to do *after* translating that PDF creation code to Swift; how do I make the draw function (maybe `dataWithPDF`)? – owlswipe Sep 04 '16 at 17:02

1 Answers1

2

Here's the solution for an iOS app:

File Thing.h:

#import <UIKit/UIKit.h>

@interface Thing : NSObject

void MyCreatePDFFile (CGRect pageRect, const char *filename);

@end

File Thing.m:

#import "Thing.h"

@implementation Thing

void MyCreatePDFFile (CGRect pageRect, const char *filename) {
    // ... your code here ...
}

@end

In the bridging header:

#import "Thing.h"

Now your Swift code can see and call this function.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • There is CoreGraphics with CGRect, CGContextRef and all that stuff on macOS. – Martin R Sep 04 '16 at 16:49
  • @MartinR Thanks :D. And matt, I'm getting a weird error. – owlswipe Sep 04 '16 at 16:53
  • All of this: "Undefined symbols for architecture x86_64: "_myDrawContent", referenced from: _MyCreatePDFFile in CreatePDF.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)" – owlswipe Sep 04 '16 at 16:53
  • Matt, your code here totally works, so I'm accepting it as the correct answer, even though my whole problem isn't really solved because my code is not doing well. – owlswipe Sep 04 '16 at 17:01
  • There is no need to define an Objective-C class just in order to call C functions. – Martin R Sep 04 '16 at 17:03
  • @MartinR I know that. I just wanted to show that this has nothing to do with this being a C function as opposed to a method, so I just stuck it into the standard solution which the OP had claimed didn't work. – matt Sep 04 '16 at 17:15
  • @matt: But it makes people think that you can only include Objective-C interfaces. – In any case, your initial claim about CGRect on macOS is wrong. – Martin R Sep 04 '16 at 17:17
  • @MartinR Fine, I'll take that out. – matt Sep 04 '16 at 17:18
  • @MartinR Anyway the real problem is that the OP is barking up the wrong tree; the question he's asked is not the question he needs to know the answer to. I'm just trying to get him to bark up a different tree and abandon this one. – matt Sep 04 '16 at 17:20
  • @matt Understood, I realize that. Thanks for the answer, though. – owlswipe Sep 04 '16 at 17:50