Core What?                       Chris Adamson • @invalidname                                 CocoaConf                   ...
Monday, March 19, 12
Core FoundationMonday, March 19, 12
Core Foundation                    “Core Foundation is a library with a set of                  programming interfaces con...
CF Concepts                • Opaque Types                • Naming Conventions                • Memory-management conventio...
Opaque Types                • References (pointers) to structs you cannot                  directly access                ...
Naming Conventions                • Opaque type references end in "Ref":                  CFArrayRef, CFStringRef, etc.   ...
Memory Management                • You own or co-own an object by getting a reference                  to it by any functi...
Toll-Free Bridging                • Many CF opaque types are identical to NS equivalents in                  Foundation, a...
TF-Bridged Types                                         NSArray = CFArray                                NSMutableArray =...
So, anyways…Monday, March 19, 12
/** Get the list of presets for the AUiPodEQ unit as a         CFArrayRef / NSArray of AUPreset structs (note: these      ...
UInt32 size = sizeof(iPodEQPresets);    OSStatus presetsErr = AudioUnitGetProperty(                              iPodEQUni...
Wait, what?Monday, March 19, 12
objectAtIndex:         Returns the object located at index.         - (id)objectAtIndex:(NSUInteger)index        CFArrayGe...
Monday, March 19, 12
Monday, March 19, 12
Fun with stringsMonday, March 19, 12
//     perform substitutions - strip anything that cant be in an      //     XML attribute (note for future: if highlights...
Monday, March 19, 12
CFStringTransform              Perform in-place transliteration on a mutable string.              Boolean CFStringTransfor...
DemoMonday, March 19, 12
CFStringTransform              Perform in-place transliteration on a mutable string.              Boolean CFStringTransfor...
Transform Identifiers for CFStringTransform     Constants that identify transforms used with CFStringTransform.     const  ...
ICU Transforms                • Any-Remove              • Any-Hex                • Any-Lower, Any-Upper,   • Any-Hex/XML  ...
ICU TransformsMonday, March 19, 12
Weird CF Collections                • CFBag — Unordered collection that allows                  duplicates (compare to CFS...
Unique IDsMonday, March 19, 12
UUID                • “Universally Unique Identifier”                • 128-bit / 16 bytes                • Usually written ...
CFUUID                  Creating CFUUID Objects                  CFUUIDCreate                  CFUUIDCreateFromString     ...
DemoMonday, March 19, 12
UUID strength                • 340,282,366,920,938,463,463,374,607,431,768                  ,211,456 possible UUIDs (16 to...
UUID and You                • -[UIDevice uniqueIdentifier] is deprecated in                  iOS 5                • Guidanc...
Monday, March 19, 12
Network StuffMonday, March 19, 12
CFNetwork                • Non-blocking socket-level APIs (CFSocket,                  CFStream)                • Host name...
Reachability                • Check SCNetworkReachabilityFlags()                  to determine if you can reach a given ho...
Captive Network                • App registers SSIDs of known-friendly wifi                  networks with CNSetSupportedSS...
Hypothetical CN UseMonday, March 19, 12
Hypothetical CN UseMonday, March 19, 12
Hypothetical CN UseMonday, March 19, 12
Monday, March 19, 12
Core Telephony                • Obj-C framework to be notified of changes in call states                       • CTCallStat...
Dead EndsMonday, March 19, 12
CFPlugIn                • API for discovering and implementing                  executable code modules at runtime        ...
Monday, March 19, 12
PDF                       Abandon all hope ye who parse here…Monday, March 19, 12
Portable Document                         Format (PDF)                • Open format, ISO standard                • 9 versi...
CGPDF                • Core Graphics API for:                       • Rendering PDF content in Quartz                     ...
CGPDFDocument…                • Open PDF doc with URL, then get metadata                  with CGPDFDocumentGetVersion,   ...
CGPDFPage                • From CGPDFDocumentGetPage()                • CGPDFPageGetBoxRect() — gets                  rect...
Drawing a page    if (NULL != _currentPDFPage) {    ! CGContextRef context = UIGraphicsGetCurrentContext();    !       // ...
Oops.Monday, March 19, 12
PDF coordinate system                • PDF coordinate system puts (0,0) at upper                  left; increasing Y value...
-(void) resetTransform {   ! CGAffineTransform centerToOrigin =   ! ! CGAffineTransformMakeTranslation(   ! ! ! ! ! ! ! ! ...
Draw with transform    if (NULL != _currentPDFPage) {    ! CGContextRef context = UIGraphicsGetCurrentContext();    !     ...
PDF Drawing DemoMonday, March 19, 12
Drawing into PDF                • Create a PDF drawing context with                  CGPDFContextCreateWithURL()          ...
Create PDF Context       CFMutableDictionaryRef pdfDict =       ! CFDictionaryCreateMutable(NULL, 0,       ! ! &kCFTypeDic...
Draw into PDF context CGContextBeginPage (pdfContext, pageRect); CGContextDrawPDFPage(pdfContext, ! ! ! ! ! ! self.pdfView...
Exporting PDF DemoMonday, March 19, 12
Accessing PDF                           Contents                • It cant be that hard, can it?Monday, March 19, 12
Monday, March 19, 12
Monday, March 19, 12
Parsing PDFs is Hard                • Document and pages have metadata                  dictionary                • One di...
Content streams                • Content streams contain everything you see                  on the page: fonts, graphics,...
Trivial example: ABC                                  BT                                       /F13 12 Tf                 ...
Text Operators                • Text state: Tf (font), Tfs (font size), Tc                  (character spacing), Tw (word ...
Handling the Operators                • Set up a CGPDFScanner with a given content                  stream                ...
void scanContentStream (CGPDFContentStreamRef stream) {   ! NSLog (@"scanContentStream()");   ! CGPDFOperatorTableRef oper...
A simple(!) Tj operator                             callback  void contentStreamTjOperatorCallback (CGPDFScannerRef scanne...
It gets worse!                • Youd think it would be enough to grab content                  streams, scan for Tj operat...
Word to the wise: bail!                • Many third-party PDF frameworks available                  (licenses and capabili...
Or you can plan on                          dealing with                • Multiple font types (Type 1, Type 3, TrueType), ...
You know, Ive learned                        something today…Monday, March 19, 12
Takeaways                • C-based frameworks in iOS have a lot of neat                  stuff that doesnt exist in Founda...
Questions?                       invalidname@gmail.com                       @invalidname                       http://www...
Upcoming SlideShare
Loading in …5
×

Core What?

3,988 views

Published on

There sure are a lot of "Core" frameworks in iOS, but what do they do for you? Core Foundation is often assumed to just be a C version of the familiar Objective-C objects in Foundation, but wait... what's this CFPlugIn? That sure doesn't have an NS-equivalent. And collections like CFBagRef and CFTreeRef, what are they? What's this CFUUID that Apple says I have to use instead of -[UIDevice uniqueIDentifier]?

That's just the beginning: beyond Core Foundation, there's even more C-only functionality to be had. Core Graphics' CGPDF functions let you draw to and from PDFs, and even parse their notoriously nasty innards. And there are more interesting C-only treats in Core Text, Core Telephony, and others.

In this session, we'll make peace with iOS' C frameworks by getting used to the conventions of allocators, opaque types, run loops, and the toll-free bridge, and tour some of the unique functionality that's only available at this level of the iOS stack.

Published in: Technology, Education
0 Comments
13 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,988
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
0
Comments
0
Likes
13
Embeds 0
No embeds

No notes for slide

Core What?

  1. 1. Core What? Chris Adamson • @invalidname CocoaConf Mar 17, 2012 • Chicago, ILMonday, March 19, 12
  2. 2. Monday, March 19, 12
  3. 3. Core FoundationMonday, March 19, 12
  4. 4. Core Foundation “Core Foundation is a library with a set of programming interfaces conceptually derived from the Objective-C-based Foundation framework but implemented in the C language.”Monday, March 19, 12
  5. 5. CF Concepts • Opaque Types • Naming Conventions • Memory-management conventions • Relationship to Foundation ("toll free bridging")Monday, March 19, 12
  6. 6. Opaque Types • References (pointers) to structs you cannot directly access • Not a “class”, per se. Gives you implementation hiding but not (much) polymorphism • Individual instances are still “objects”Monday, March 19, 12
  7. 7. Naming Conventions • Opaque type references end in "Ref": CFArrayRef, CFStringRef, etc. • Functions that take a type start with that types name: CFStringGetLength(), CFArrayGetObjectAtIndex() • Functions take target object as first parameter (sometimes second, as in Create functions)Monday, March 19, 12
  8. 8. Memory Management • You own or co-own an object by getting a reference to it by any function with Create or Copy in its name, or by explicitly calling CFRetain() • You dont own objects you obtain by calling functions without these words (e.g., "Get") • You CFRelease() objects you own and are done with • Some objects have different cleanup: AudioQueueDispose(), CGPDFDocumentRelease()Monday, March 19, 12
  9. 9. Toll-Free Bridging • Many CF opaque types are identical to NS equivalents in Foundation, and can be cast at zero cost CFStringRef myCFString = (CFStringRef) myNSString; NSString *myNSString = (NSString*) myCFString; • With ARC, use • __bridge_transfer to give ARC ownership • __bridge_retained to relieve ARC of ownership • __bridge to keep ARC out of it.Monday, March 19, 12
  10. 10. TF-Bridged Types NSArray = CFArray NSMutableArray = CFMutableArray NSCalendar = CFCalendar NSCharacterSet = CFCharacterSet NSMutableCharacterSet = CFMutableCharacterSet NSData = CFData NSMutableData = CFMutableData NSDate = CFDate NSDictionary = CFDictionary NSMutableDictionary = CFMutableDictionary NSNumber = CFNumber NSTimer = CFRunLoopTimer NSSet = CFSet NSMutableSet = CFMutableSet NSString = CFString NSMutableString = CFMutableString NSURL = CFURL NSTimeZone = CFTimeZone NSInputStream = CFReadStream NSOutputStream = CFWriteStream NSAttributedString = CFAttributedString NSMutableAttributedString = CFMutableAttributedString From cocoadev.comMonday, March 19, 12
  11. 11. So, anyways…Monday, March 19, 12
  12. 12. /** Get the list of presets for the AUiPodEQ unit as a CFArrayRef / NSArray of AUPreset structs (note: these are structs, not NSObjects/ids... use CFArrayGetValueAtIndex()). */ -(CFArrayRef) iPodEQPresets;Monday, March 19, 12
  13. 13. UInt32 size = sizeof(iPodEQPresets); OSStatus presetsErr = AudioUnitGetProperty( iPodEQUnit, kAudioUnitProperty_FactoryPresets, kAudioUnitScope_Global, 0, &iPodEQPresets, &size);Monday, March 19, 12
  14. 14. Wait, what?Monday, March 19, 12
  15. 15. objectAtIndex: Returns the object located at index. - (id)objectAtIndex:(NSUInteger)index CFArrayGetValueAtIndex Retrieves a value at a given index. const void * CFArrayGetValueAtIndex ( CFArrayRef theArray, CFIndex idx );Monday, March 19, 12
  16. 16. Monday, March 19, 12
  17. 17. Monday, March 19, 12
  18. 18. Fun with stringsMonday, March 19, 12
  19. 19. // perform substitutions - strip anything that cant be in an // XML attribute (note for future: if highlights are disappearing, // this is probably why... theyll generate a parsing error and // get thrown away, possibly nuking the whole notes file) [cleanedUpString replaceOccurrencesOfString:@"—" withString:@"--" ! ! ! ! ! ! ! ! ! options:0 range:NSMakeRange(0, [cleanedUpString length])]; [cleanedUpString replaceOccurrencesOfString:@"“" withString:@""" ! ! ! ! ! ! ! ! ! options:0 range:NSMakeRange(0, [cleanedUpString length])];Monday, March 19, 12
  20. 20. Monday, March 19, 12
  21. 21. CFStringTransform Perform in-place transliteration on a mutable string. Boolean CFStringTransform ( CFMutableStringRef string, CFRange *range, CFStringRef transform, Boolean reverse );Monday, March 19, 12
  22. 22. DemoMonday, March 19, 12
  23. 23. CFStringTransform Perform in-place transliteration on a mutable string. Boolean CFStringTransform ( CFMutableStringRef string, CFRange *range, CFStringRef transform, Boolean reverse );Monday, March 19, 12
  24. 24. Transform Identifiers for CFStringTransform Constants that identify transforms used with CFStringTransform. const CFStringRef kCFStringTransformStripCombiningMarks; const CFStringRef kCFStringTransformToLatin; const CFStringRef kCFStringTransformFullwidthHalfwidth; const CFStringRef kCFStringTransformLatinKatakana; const CFStringRef kCFStringTransformLatinHiragana; const CFStringRef kCFStringTransformHiraganaKatakana; const CFStringRef kCFStringTransformMandarinLatin; const CFStringRef kCFStringTransformLatinHangul; const CFStringRef kCFStringTransformLatinArabic; const CFStringRef kCFStringTransformLatinHebrew; const CFStringRef kCFStringTransformLatinThai; const CFStringRef kCFStringTransformLatinCyrillic; const CFStringRef kCFStringTransformLatinGreek; const CFStringRef kCFStringTransformToXMLHex; const CFStringRef kCFStringTransformToUnicodeName; const CFStringRef kCFStringTransformStripDiacritics;Monday, March 19, 12
  25. 25. ICU Transforms • Any-Remove • Any-Hex • Any-Lower, Any-Upper, • Any-Hex/XML Any-Title • Any-Accents • Any-NFD, Any-NFC, Any-NFKD, Any-NFKC • Any-Publishing • Any-Name • Fullwidth-Halfwidth Or a custom transform following the ICU syntax, see http://userguide.icu-project.org/transforms/generalMonday, March 19, 12
  26. 26. ICU TransformsMonday, March 19, 12
  27. 27. Weird CF Collections • CFBag — Unordered collection that allows duplicates (compare to CFSet) • CFBitVector — Ordered collection of bit values • CFBinaryHeap — Mutable collection sorted by a binary search function you provide • CFTree — Mutable tree-structure collectionMonday, March 19, 12
  28. 28. Unique IDsMonday, March 19, 12
  29. 29. UUID • “Universally Unique Identifier” • 128-bit / 16 bytes • Usually written as hex pattern 8-4-4-12 • Standardized as RFC 4122, et. al. • Early versions used MAC address and date; newer versions are based on huge random numbersMonday, March 19, 12
  30. 30. CFUUID Creating CFUUID Objects CFUUIDCreate CFUUIDCreateFromString CFUUIDCreateFromUUIDBytes CFUUIDCreateWithBytes Getting Information About CFUUID Objects CFUUIDCreateString CFUUIDGetConstantUUIDWithBytes CFUUIDGetUUIDBytesMonday, March 19, 12
  31. 31. DemoMonday, March 19, 12
  32. 32. UUID strength • 340,282,366,920,938,463,463,374,607,431,768 ,211,456 possible UUIDs (16 to the 32nd power) • 50% chance of a duplicate UUID if: • Everyone on Earth had 600 million UUIDs, or • You generated 1 billion UUIDs every second for the next 100 yearsMonday, March 19, 12
  33. 33. UUID and You • -[UIDevice uniqueIdentifier] is deprecated in iOS 5 • Guidance from Apple is for apps to use a CFUUID to uniquely identify an installed instance.Monday, March 19, 12
  34. 34. Monday, March 19, 12
  35. 35. Network StuffMonday, March 19, 12
  36. 36. CFNetwork • Non-blocking socket-level APIs (CFSocket, CFStream) • Host name resolution • HTTP/HTTPS/FTP, with authentication • BonjourMonday, March 19, 12
  37. 37. Reachability • Check SCNetworkReachabilityFlags() to determine if you can reach a given host, check to see if its wifi or cellular (kSCNetworkReachabilityFlagsIsWWAN) • Register for callbacks with SCNetworkReachabilitySetCallback()Monday, March 19, 12
  38. 38. Captive Network • App registers SSIDs of known-friendly wifi networks with CNSetSupportedSSIDs() • Login/TOS web sheet will be suppressed for these wifi hotspots • App indicates authentication success/failure with CNMarkPortalOnline()/ CNMarkPortalOffline()Monday, March 19, 12
  39. 39. Hypothetical CN UseMonday, March 19, 12
  40. 40. Hypothetical CN UseMonday, March 19, 12
  41. 41. Hypothetical CN UseMonday, March 19, 12
  42. 42. Monday, March 19, 12
  43. 43. Core Telephony • Obj-C framework to be notified of changes in call states • CTCallStateDialing, CTCallStateIncoming, CTCallStateConnected, CTCallStateDisconnected • CTCarrier lets you inspect carrier ID, country code, whether it allows VoIP on its network • No access to call numbers, call audio, etc.Monday, March 19, 12
  44. 44. Dead EndsMonday, March 19, 12
  45. 45. CFPlugIn • API for discovering and implementing executable code modules at runtime • Plugin code is packaged as bundles • iPhone OS 3 had a custom Audio Unit API based on CFPlugIn • But it was removed in iOS 4. Uh oh…Monday, March 19, 12
  46. 46. Monday, March 19, 12
  47. 47. PDF Abandon all hope ye who parse here…Monday, March 19, 12
  48. 48. Portable Document Format (PDF) • Open format, ISO standard • 9 versions since 1.0 in 1993 • Basically an extensible container format, a subset of PostScript, and a font-bundling/ replacement systemMonday, March 19, 12
  49. 49. CGPDF • Core Graphics API for: • Rendering PDF content in Quartz • Providing a PDF context for Quartz drawing commands • Parsing PDF contentsMonday, March 19, 12
  50. 50. CGPDFDocument… • Open PDF doc with URL, then get metadata with CGPDFDocumentGetVersion, CGPDFDocumentGetInfo, CGPDFDocumentGetID, CGPDFDocumentAllowsPrinting, etc NSURL *pdfURL = [NSURL fileURLWithPath:pdfPath]; self.pdfDocument = CGPDFDocumentCreateWithURL( (__bridge CFURLRef) pdfURL);Monday, March 19, 12
  51. 51. CGPDFPage • From CGPDFDocumentGetPage() • CGPDFPageGetBoxRect() — gets rectangles describing important spaces like physical media area (kCGPDFMediaBox) or meaningful content (kCGPDFArtBox) • Metadata in CGPDFPageGetDictionary()Monday, March 19, 12
  52. 52. Drawing a page if (NULL != _currentPDFPage) { ! CGContextRef context = UIGraphicsGetCurrentContext(); ! // background ! CGContextSetFillColorWithColor(context, ! ! ! ! ! ! ! ! ! [UIColor grayColor].CGColor); ! CGContextFillRect(context, self.bounds); ! // draw pdf page ! CGContextSetFillColorWithColor(context, ! ! ! ! ! ! ! ! ! [UIColor whiteColor].CGColor); ! CGContextFillRect(context, self.bounds); ! CGContextDrawPDFPage(context, _currentPDFPage); }Monday, March 19, 12
  53. 53. Oops.Monday, March 19, 12
  54. 54. PDF coordinate system • PDF coordinate system puts (0,0) at upper left; increasing Y values go down (similar to UIKit) • Need to scale Y by -1.0 and translate prior to drawingMonday, March 19, 12
  55. 55. -(void) resetTransform { ! CGAffineTransform centerToOrigin = ! ! CGAffineTransformMakeTranslation( ! ! ! ! ! ! ! ! ! ! self.bounds.size.width / 2.0, ! ! ! ! ! ! ! ! ! ! self.bounds.size.height / -2.0); ! CGAffineTransform flip = CGAffineTransformMakeScale( ! ! ! ! ! ! ! ! ! ! 1.0, -1.0); ! CGAffineTransform originToCenter = ! ! CGAffineTransformInvert(centerToOrigin); ! self.pdfTransform = CGAffineTransformConcat( ! ! ! ! ! ! ! ! ! ! centerToOrigin, flip); ! self.pdfTransform = CGAffineTransformConcat( ! ! ! ! ! ! ! ! ! self.pdfTransform, originToCenter); ! [self setNeedsDisplay]; }Monday, March 19, 12
  56. 56. Draw with transform if (NULL != _currentPDFPage) { ! CGContextRef context = UIGraphicsGetCurrentContext(); ! // background ! CGContextSetFillColorWithColor(context, ! ! ! ! ! ! ! ! ! [UIColor grayColor].CGColor); ! CGContextFillRect(context, self.bounds); ! // draw pdf page ! CGContextSaveGState (context); ! CGContextConcatCTM(context, self.pdfTransform); ! CGContextSetFillColorWithColor(context, ! ! ! ! ! ! ! ! ! [UIColor whiteColor].CGColor); ! CGContextFillRect(context, self.bounds); ! CGContextDrawPDFPage(context, _currentPDFPage); ! CGContextRestoreGState(context); }Monday, March 19, 12
  57. 57. PDF Drawing DemoMonday, March 19, 12
  58. 58. Drawing into PDF • Create a PDF drawing context with CGPDFContextCreateWithURL() • Start each page with CGContextStartPage() • Draw with Quartz as usual • End pages with CGContextEndPage() • CFContextRelease() to finish writing to fileMonday, March 19, 12
  59. 59. Create PDF Context CFMutableDictionaryRef pdfDict = ! CFDictionaryCreateMutable(NULL, 0, ! ! &kCFTypeDictionaryKeyCallBacks, ! ! &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(pdfDict, kCGPDFContextTitle, ! ! ! ! ! ! ! ! CFSTR("Exported PDF")); CFDictionarySetValue(pdfDict, kCGPDFContextCreator, ! ! ! ! ! ! ! ! CFSTR("CocoaConf demo app")); CGRect *pageRect = malloc (sizeof (CGRect)); // TODO: use a box *pageRect = CGRectMake (0.0, 0.0, 612.0, 792.0); CGContextRef pdfContext = CGPDFContextCreateWithURL( ! ! ! ! ! ! ! ! url, pageRect, pdfDict);Monday, March 19, 12
  60. 60. Draw into PDF context CGContextBeginPage (pdfContext, pageRect); CGContextDrawPDFPage(pdfContext, ! ! ! ! ! ! self.pdfView.currentPDFPage); NSString *watermarkString = [NSString ! stringWithFormat:@"Created at CocoaConf at %@", ! ! [NSDate date]]; const char* watermarkCString = [watermarkString UTF8String]; NSInteger watermarkLength = [watermarkString length]; CGContextSelectFont(pdfContext, PDF_EXPORT_FONT_NAME, ! ! PDF_EXPORT_FONT_SIZE, kCGEncodingMacRoman); CGContextRotateCTM(pdfContext, 0.25 * M_PI); CGContextSetFillColorWithColor(pdfContext, ! ! ! ! ! ! [UIColor redColor].CGColor); CGContextShowTextAtPoint(pdfContext, 300.0, 150.0, ! ! ! ! ! ! watermarkCString, watermarkLength); CGContextEndPage(pdfContext);Monday, March 19, 12
  61. 61. Exporting PDF DemoMonday, March 19, 12
  62. 62. Accessing PDF Contents • It cant be that hard, can it?Monday, March 19, 12
  63. 63. Monday, March 19, 12
  64. 64. Monday, March 19, 12
  65. 65. Parsing PDFs is Hard • Document and pages have metadata dictionary • One dictionary item is "Contents", value is a content stream • Content stream may be contents, or an array of content streamsMonday, March 19, 12
  66. 66. Content streams • Content streams contain everything you see on the page: fonts, graphics, text • Stream is literally that: a start to end stream of data and drawing instructions • Generally no representation of the structure of the content (paragraphs, lines, words)Monday, March 19, 12
  67. 67. Trivial example: ABC BT /F13 12 Tf 288 720 Td (ABC) Tj ET 1. Select Helvetica font (/F13) 2. Move to coordinates (288, 720) 3. Stroke characters "ABC"Monday, March 19, 12
  68. 68. Text Operators • Text state: Tf (font), Tfs (font size), Tc (character spacing), Tw (word spacing)… • Text position: Tm (matrix for new position), TD/ Td (next line with offset matrix), … • Text showing: Tj (show string), TJ (show array of glyphs)Monday, March 19, 12
  69. 69. Handling the Operators • Set up a CGPDFScanner with a given content stream • Register callback functions for the operators you want to deal with • Call CGPDFScannerScan()Monday, March 19, 12
  70. 70. void scanContentStream (CGPDFContentStreamRef stream) { ! NSLog (@"scanContentStream()"); ! CGPDFOperatorTableRef operatorTable = ! ! ! ! ! ! CGPDFOperatorTableCreate(); ! CGPDFOperatorTableSetCallback(operatorTable, "TJ", ! ! ! ! ! ! contentStreamTJOperatorCallback); ! CGPDFOperatorTableSetCallback(operatorTable, "Tj", ! ! ! ! ! ! contentStreamTjOperatorCallback); ! CGPDFOperatorTableSetCallback(operatorTable, "Td", ! ! ! ! ! ! contentStreamTdOperatorCallback); ! CGPDFOperatorTableSetCallback(operatorTable, "TD", ! ! ! ! ! ! contentStreamTDOperatorCallback); ! CGPDFOperatorTableSetCallback(operatorTable, "Tm", ! ! ! ! ! ! contentStreamTmOperatorCallback); ! CGPDFOperatorTableSetCallback(operatorTable, "T*", ! ! ! ! ! ! contentStreamTStarOperatorCallback); ! CGPDFScannerRef streamScanner = CGPDFScannerCreate(stream, ! ! ! ! ! ! operatorTable, NULL); ! NSLog (@"created scanner"); ! bool scanned = CGPDFScannerScan(streamScanner); ! NSLog (@"scan result: %@", scanned ? @"true" : @"false"); ! CGPDFScannerRelease(streamScanner); }Monday, March 19, 12
  71. 71. A simple(!) Tj operator callback void contentStreamTjOperatorCallback (CGPDFScannerRef scanner, ! ! ! ! ! ! ! ! ! ! ! ! ! void *info) { ! CGPDFStringRef pdfStringToShow; ! bool popped = CGPDFScannerPopString( ! ! ! ! ! ! ! scanner, &pdfStringToShow); ! while (popped) { ! ! CFStringRef stringToShow = ! ! ! ! CGPDFStringCopyTextString(pdfStringToShow); ! ! NSLog (@"contentStreamTjOperatorCallback()[%ld]: %@", ! ! ! ! CFStringGetLength(stringToShow), stringToShow); ! ! [pageText appendString:stringToShow]; ! ! CFRelease (stringToShow); ! ! popped = CGPDFScannerPopString(scanner, ! ! ! ! ! ! ! &pdfStringToShow); ! } }Monday, March 19, 12
  72. 72. It gets worse! • Youd think it would be enough to grab content streams, scan for Tj operators, build up a string. But… • The streams and their contents are not guaranteed to be in reading order (and often arent) • Need to process all the text moving, styling, font operators just to find where stuff is on the pageMonday, March 19, 12
  73. 73. Word to the wise: bail! • Many third-party PDF frameworks available (licenses and capabilities vary) • PSPDFKit • FastPDFKit • Foxit • PDFTron • etc…Monday, March 19, 12
  74. 74. Or you can plan on dealing with • Multiple font types (Type 1, Type 3, TrueType), composite fonts, CJKV issues, Unicode mappings, glyphs, glyph metrics… • Color-space conversions, halftone screens, transparency/translucency… • Images, graphics commands (fills, strokes, etc.)…Monday, March 19, 12
  75. 75. You know, Ive learned something today…Monday, March 19, 12
  76. 76. Takeaways • C-based frameworks in iOS have a lot of neat stuff that doesnt exist in Foundation or Cocoa Touch • Granted, it also has duplication and dead- end Carbon legacies • Look around docs and headers, ask questions, find stuffMonday, March 19, 12
  77. 77. Questions? invalidname@gmail.com @invalidname http://www.subfurther.com/blogMonday, March 19, 12

×