iOS: Reading contents of PDF File - ios

By going to the Quartz 2D programming guide and some of the post on SO I pieced together some code to read the contents of a PDF file. It's failing on the PDF Scanner part, I think. When I go to release the scanner the app crashes with this error:
avi(2282,0x3de7bb88) malloc: *** error for object 0x693f7c0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
I am opening the PDF file through an email attachment. I know it's at least recognizing the file as I can get the page count. Could someone look at my code below and see where my error is happening? Thanks.
- (void) readPDFFile:(NSURL *)PDFURL {
//make a pdf document and point it to the url of our pdf file
CGPDFDocumentRef pdfDocument;
pdfDocument = CGPDFDocumentCreateWithURL((__bridge CFURLRef)(PDFURL));
//release the url
CFRelease((__bridge CFTypeRef)(PDFURL));
if (pdfDocument) {
//get page count
int pageCount = CGPDFDocumentGetNumberOfPages (pdfDocument);
//
if (pageCount > 0) {
//set up operator table
CGPDFOperatorTableRef pdfOpTable;
pdfOpTable = CGPDFOperatorTableCreate();
//call backs for Op Table
CGPDFOperatorTableSetCallback (pdfOpTable, "MP", &op_MP);
CGPDFOperatorTableSetCallback (pdfOpTable, "DP", &op_DP);
CGPDFOperatorTableSetCallback (pdfOpTable, "BMC", &op_BMC);
CGPDFOperatorTableSetCallback (pdfOpTable, "BDC", &op_BDC);
CGPDFOperatorTableSetCallback (pdfOpTable, "EMC", &op_EMC);
for(int i=0; i<pageCount; i++) {
//set up
CGPDFPageRef thisPage;
CGPDFScannerRef pdfScanner;
CGPDFContentStreamRef thisContentStream;
//get the page
thisPage = CGPDFDocumentGetPage (pdfDocument, i + 1 );
//get the page content stream
thisContentStream = CGPDFContentStreamCreateWithPage (thisPage);
//create a pdf scanner using our previously created table and callbacks
pdfScanner = CGPDFScannerCreate (thisContentStream, pdfOpTable, NULL);
//scan the pdf file
CGPDFScannerScan (pdfScanner); //-->call backs happen here
//release everything
CGPDFPageRelease (thisPage);
/*CGPDFScannerRelease (pdfScanner);
CGPDFContentStreamRelease (thisContentStream);*/
}
}
}
//release the pdf document
CGPDFDocumentRelease(pdfDocument);
}
static void op_MP (CGPDFScannerRef s, void *info) {
const char *name;
if (!CGPDFScannerPopName(s, &name))
return;
NSLog(#"MP /%s\n", name);
}
static void op_DP (CGPDFScannerRef s, void *info) {
const char *name;
if (!CGPDFScannerPopName(s, &name))
return;
NSLog(#"DP /%s\n", name);
}
static void op_BMC (CGPDFScannerRef s, void *info) {
const char *name;
if (!CGPDFScannerPopName(s, &name))
return;
NSLog(#"BMC /%s\n", name);
}
static void op_BDC (CGPDFScannerRef s, void *info) {
const char *name;
if (!CGPDFScannerPopName(s, &name))
return;
NSLog(#"BDC /%s\n", name);
}
static void op_EMC (CGPDFScannerRef s, void *info) {
const char *name;
if (!CGPDFScannerPopName(s, &name))
return;
NSLog(#"EMC /%s\n", name);
}
EDIT: PDFURL comes from this process: User opts to open PDF file attached to email with app. In AppDelegate.m:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
/* NSLog(#"Open URL:\t%#\n"
"From source:\t%#\n"
"With annotation:%#",
url, sourceApplication, annotation);*/
NSMutableDictionary* userData = [[NSMutableDictionary alloc] init];
[userData setObject:#"Read PDF" forKey:#"Action"];
[userData setObject:url forKey:#"File Path"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"theMessenger" object:self userInfo: userData];
//NSString *filepath = [url path];
//...
return YES;
}
in viewcontroller.m
- (void) receiveNotification:(NSNotification* ) notification {
...
} else if ([strAction isEqualToString:#"Read PDF"]) {
NSURL* documentURL = [[notification userInfo] objectForKey:#"File Path"];
[self readPDFFile:documentURL];
}
...
EDIT: If I do not release this page app still crashes:
libobjc.A.dylib`objc_release:
0x3be89f20: cmp r0, #0
0x3be89f22: it eq
0x3be89f24: bxeq lr
0x3be89f26: ldr r1, [r0]
0x3be89f28: movs r2, #2
0x3be89f2a: ldr r1, [r1, #16]
0x3be89f2c: bfi r1, r2, #0, #2
0x3be89f30: ldrb r1, [r1]
0x3be89f32: tst.w r1, #2
0x3be89f36: bne 0x3be89f3e ; objc_release + 30
0x3be89f38: movs r1, #0
0x3be89f3a: b.w 0x3be981c0 ; -[NSObject release]
0x3be89f3e: movw r1, #19326
0x3be89f42: movt r1, #507
0x3be89f46: add r1, pc
0x3be89f48: ldr r1, [r1]
0x3be89f4a: b.w 0x3be875a0 ; objc_msgSend
0x3be89f4e: nop

dont release thisPage.. you get it via a GET call not a copy or a create method meaning you don't own it
--
dont release PDURL.. you get it from outside but you don't own it
--
do release the operatorTable .. you CREATE it
AND
dont reuse it for multiple scanners

Related

Implementing a simple SuperpoweredAdvancedAudioPlayer in swift

I am trying to implement a simple SuperpoweredAdvancedAudioPlayer in swift. I successfully modified the SuperpoweredCrossExample project so that playerA plays the song on starting the application.
ViewController.mm now looks like this:
#import "ViewController.h"
#import "SuperpoweredAdvancedAudioPlayer.h"
#import "SuperpoweredFilter.h"
#import "SuperpoweredRoll.h"
#import "SuperpoweredFlanger.h"
#import "SuperpoweredIOSAudioIO.h"
#import "SuperpoweredSimple.h"
#import <stdlib.h>
#define HEADROOM_DECIBEL 3.0f
static const float headroom = powf(10.0f, -HEADROOM_DECIBEL * 0.025);
/*
This is a .mm file, meaning it's Objective-C++.
You can perfectly mix it with Objective-C or Swift, until you keep the member variables and C++ related includes here.
Yes, the header file (.h) isn't the only place for member variables.
*/
#implementation ViewController {
SuperpoweredAdvancedAudioPlayer *playerA;
SuperpoweredIOSAudioIO *output;
float *stereoBuffer, volA;
unsigned int lastSamplerate;
}
void playerEventCallbackA(void *clientData, SuperpoweredAdvancedAudioPlayerEvent event, void *value) {
if (event == SuperpoweredAdvancedAudioPlayerEvent_LoadSuccess) {
ViewController *self = (__bridge ViewController *)clientData;
self->playerA->setBpm(126.0f);
self->playerA->setFirstBeatMs(353);
self->playerA->setPosition(self->playerA->firstBeatMs, false, false);
};
}
// This is where the Superpowered magic happens.
static bool audioProcessing(void *clientdata, float **buffers, unsigned int inputChannels, unsigned int outputChannels, unsigned int numberOfSamples, unsigned int samplerate, uint64_t hostTime) {
__unsafe_unretained ViewController *self = (__bridge ViewController *)clientdata;
if (samplerate != self->lastSamplerate) { // Has samplerate changed?
self->lastSamplerate = samplerate;
self->playerA->setSamplerate(samplerate);
};
bool silence = !self->playerA->process(self->stereoBuffer, false, numberOfSamples, self->volA);
if (!silence) SuperpoweredDeInterleave(self->stereoBuffer, buffers[0], buffers[1], numberOfSamples); // The stereoBuffer is ready now, let's put the finished audio into the requested buffers.
return !silence;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self f];
}
- (void) f {
volA = 1.0f * headroom;
if (posix_memalign((void **)&stereoBuffer, 16, 4096 + 128) != 0) abort(); // Allocating memory, aligned to 16.
playerA = new SuperpoweredAdvancedAudioPlayer((__bridge void *)self, playerEventCallbackA, 44100, 0);
playerA->open([[[NSBundle mainBundle] pathForResource:#"lycka" ofType:#"mp3"] fileSystemRepresentation]);
output = [[SuperpoweredIOSAudioIO alloc] initWithDelegate:(id<SuperpoweredIOSAudioIODelegate>)self preferredBufferSize:12 preferredMinimumSamplerate:44100 audioSessionCategory:AVAudioSessionCategoryPlayback channels:2 audioProcessingCallback:audioProcessing clientdata:(__bridge void *)self];
[output start];
playerA->play(false);
}
- (void)dealloc {
delete playerA;
free(stereoBuffer);
#if !__has_feature(objc_arc)
[output release];
[super dealloc];
#endif
}
- (void)interruptionStarted {}
- (void)recordPermissionRefused {}
- (void)mapChannels:(multiOutputChannelMap *)outputMap inputMap:(multiInputChannelMap *)inputMap externalAudioDeviceName:(NSString *)externalAudioDeviceName outputsAndInputs:(NSString *)outputsAndInputs {}
- (void)interruptionEnded { // If a player plays Apple Lossless audio files, then we need this. Otherwise unnecessary.
playerA->onMediaserverInterrupt();
}
#end
I am trying to use the same code in swift following the same method used in SuperpoweredFrequencies project to import c++ files in swift.
Superpowered.h:
#import <UIKit/UIKit.h>
#interface Superpowered: NSObject
-(void) f;
#end
Superpowered.mm:
#import "Superpowered.h"
#import "Superpowered/Headers/SuperpoweredAdvancedAudioPlayer.h"
#import "Superpowered/Headers/SuperpoweredFilter.h"
#import "Superpowered/Headers/SuperpoweredRoll.h"
#import "Superpowered/Headers/SuperpoweredFlanger.h"
#import "Superpowered/SuperpoweredIOSAudioIO.h"
#import "Superpowered/Headers/SuperpoweredSimple.h"
#import <stdlib.h>
#define HEADROOM_DECIBEL 3.0f
static const float headroom = powf(10.0f, -HEADROOM_DECIBEL * 0.025);
/*
This is a .mm file, meaning it's Objective-C++.
You can perfectly mix it with Objective-C or Swift, until you keep the member variables and C++ related includes here.
Yes, the header file (.h) isn't the only place for member variables.
*/
#implementation Superpowered {
SuperpoweredAdvancedAudioPlayer *playerA;
SuperpoweredIOSAudioIO *output;
float *stereoBuffer, volA;
unsigned int lastSamplerate;
}
void playerEventCallbackA(void *clientData, SuperpoweredAdvancedAudioPlayerEvent event, void *value) {
if (event == SuperpoweredAdvancedAudioPlayerEvent_LoadSuccess) {
Superpowered *self = (__bridge Superpowered *)clientData;
self->playerA->setBpm(126.0f);
self->playerA->setFirstBeatMs(353);
self->playerA->setPosition(self->playerA->firstBeatMs, false, false);
};
}
// This is where the Superpowered magic happens.
static bool audioProcessing(void *clientdata, float **buffers, unsigned int inputChannels, unsigned int outputChannels, unsigned int numberOfSamples, unsigned int samplerate, uint64_t hostTime) {
__unsafe_unretained Superpowered *self = (__bridge Superpowered *)clientdata;
if (samplerate != self->lastSamplerate) { // Has samplerate changed?
self->lastSamplerate = samplerate;
self->playerA->setSamplerate(samplerate);
};
bool silence = !self->playerA->process(self->stereoBuffer, false, numberOfSamples, self->volA);
if (!silence) SuperpoweredDeInterleave(self->stereoBuffer, buffers[0], buffers[1], numberOfSamples); // The stereoBuffer is ready now, let's put the finished audio into the requested buffers.
return !silence;
}
- (void)f {
volA = 1.0f * headroom;
if (posix_memalign((void **)&stereoBuffer, 16, 4096 + 128) != 0) abort(); // Allocating memory, aligned to 16.
playerA = new SuperpoweredAdvancedAudioPlayer((__bridge void *)self, playerEventCallbackA, 44100, 0);
playerA->open([[[NSBundle mainBundle] pathForResource:#"lycka" ofType:#"mp3"] fileSystemRepresentation]);
output = [[SuperpoweredIOSAudioIO alloc] initWithDelegate:(id<SuperpoweredIOSAudioIODelegate>)self preferredBufferSize:12 preferredMinimumSamplerate:44100 audioSessionCategory:AVAudioSessionCategoryPlayback channels:2 audioProcessingCallback:audioProcessing clientdata:(__bridge void *)self];
[output start];
playerA->play(false);
}
- (void)dealloc {
delete playerA;
free(stereoBuffer);
#if !__has_feature(objc_arc)
[output release];
[super dealloc];
#endif
}
- (void)interruptionStarted {}
- (void)recordPermissionRefused {}
- (void)mapChannels:(multiOutputChannelMap *)outputMap inputMap:(multiInputChannelMap *)inputMap externalAudioDeviceName:(NSString *)externalAudioDeviceName outputsAndInputs:(NSString *)outputsAndInputs {}
- (void)interruptionEnded { // If a player plays Apple Lossless audio files, then we need this. Otherwise unnecessary.
playerA->onMediaserverInterrupt();
}
#end
Project-Bridging-Header.h:
#import "Superpowered.h"
Controller.swift:
override func viewDidLoad() {
super.viewDidLoad()
let s = Superpowered();
s.f();
}
When running the app it crashes and gives the following error:
let s = Superpowered(); should be declared outside viewDidLoad(). Declaring it as an instance variable solved the problem.

UIImage setImage crash

I implemented a video player with ffmpeg. Each frame is decoded successfully and can be saved to a valid jpg file and can be show in UIImageView when running in emulator. However, the memory is unbounded growing when I run my app in emulator. Moreover, the app will crash after excuting p_diaplayNextFrame 2 times when running on device. If I comment self.imageView.image = frame;, memory is not leaked and app is not crashed in emulator or on device.
-(void)p_displayNextFrame
{
ZCVFrameSec *frameSec = [video getNextVideoFrameSec];
UIImage *frame = [frameSec toUIImage];
static int fi = 0;
NSAssert( [NSThread isMainThread], #"Fatal error: must be main thread" );
NSString *fileName = [Utilities documentsPath:[NSString stringWithFormat:#"image%06d.jpg",fi++]];
NSLog(#"p_displayNextFrame write image file: %#",fileName);
// frame is saved successfully as jpg, I can view it
[UIImageJPEGRepresentation(frame, 0.7) writeToFile:fileName atomically:YES];
// leak(but not crash) in emulator, crash on device
self.imageView.image = frame;
double delayInSeconds = 0.05;//1/30.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self p_displayNextFrame];
});
}
ZCVFrameSec's toUIImage
- (UIImage*) toUIImage
{
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, [self.data bytes], self.width * self.height * 3,kCFAllocatorNull);
NSAssert( [self.data length] == self.width * self.height * 3,
#"Fatal error: data length:%d, width:%d, height:%d, mul3=%d",
[self.data length],
self.width, self.height, self.width * self.height * 3 );
CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef cgImage = CGImageCreate(self.width,
self.height,
8,
24,
3 * self.width,
colorSpace,
bitmapInfo,
provider,
NULL,
NO,
kCGRenderingIntentDefault);
UIImage *image = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
CGColorSpaceRelease(colorSpace);
CGDataProviderRelease(provider);
CFRelease(data);
return image;
}
crash info:
vImage`__vConvert_RGB888toBGRA8888_block_invoke98:
0x2d72aeb0: push {r4, r5, r6, r7, lr}
0x2d72aeb2: add r7, sp, #0xc
0x2d72aeb4: push.w {r8, r10}
0x2d72aeb8: ldr r2, [r0, #0x14]
0x2d72aeba: ldr r2, [r2, #0x4]
0x2d72aebc: ldr r2, [r2, #0x10]
0x2d72aebe: cmp r2, #0x0
0x2d72aec0: beq.w 0x2d72b076 ; __vConvert_RGB888toBGRA8888_block_invoke98 + 454
0x2d72aec4: vldr d16, [pc, #440]
0x2d72aec8: vmov.i32 q10, #0xff000000
0x2d72aecc: lsl.w r9, r1, #0x3
0x2d72aed0: vldr d18, [pc, #436]
0x2d72aed4: mov.w r12, #0x0
0x2d72aed8: ldr.w r8, [r0, #24]
0x2d72aedc: add.w r5, r0, #0x1c
0x2d72aee0: add.w r6, r12, r9
0x2d72aee4: ldm r5, {r2, r4, r5}
0x2d72aee6: ldr r3, [r0, #0x28]
0x2d72aee8: ldr r1, [r0, #0x2c]
0x2d72aeea: mla r2, r2, r6, r8
0x2d72aeee: mla lr, r5, r6, r4
0x2d72aef2: mla r3, r1, r6, r3
0x2d72aef6: tst.w r3, #0xf
0x2d72aefa: bne 0x2d72af44 ; __vConvert_RGB888toBGRA8888_block_invoke98 + 148
0x2d72aefc: tst.w r2, #0xf
0x2d72af00: bne 0x2d72af80 ; __vConvert_RGB888toBGRA8888_block_invoke98 + 208
0x2d72af02: ldr r4, [r0, #0x30]
0x2d72af04: movs r1, #0x0
0x2d72af06: tst.w lr, #0xf
0x2d72af0a: bne 0x2d72afbc ; __vConvert_RGB888toBGRA8888_block_invoke98 + 268
0x2d72af0c: cmp r4, #0x10
0x2d72af0e: blo 0x2d72aff2 ; __vConvert_RGB888toBGRA8888_block_invoke98 + 322
0x2d72af10: ldr r4, [r0, #0x34]
0x2d72af12: vld3.8 {d0, d2, d4}, [r2]!
Thread 1: EXC_BAD_ACCESS (code=1,address=0x7403000)
Any hint is appreciated!!!
I think the problem was because ZCVFrameSec *frameSec got deallocate after it got out of scope of -(void)p_displayNextFrame method.
If you used CFDataCreateWithBytesNoCopy on the bytes array in frameSec, then the byte array might vanish with frameSec before you finished using it in your cgImage, or you could say, in your UIImage *frame. This caused a EXC_BAD_ACCESS exception.
That why changing to CFDataCreate instead of CFDataCreateWithBytesNoCopy worked.
To answer your next question, how you can avoid copying a frame, I think there are a lot of ways to do that. You may hold your frameSec all the time until you change imageView to the next frame then you can release it.
To do that you can only declare a property to hold the current frame. Like this :
-(void)p_displayNextFrame
{
ZCVFrameSec *frameSec = [video getNextVideoFrameSec];
UIImage *frame = [frameSec toUIImage];
static int fi = 0;
NSAssert( [NSThread isMainThread], #"Fatal error: must be main thread" );
NSString *fileName = [Utilities documentsPath:[NSString stringWithFormat:#"image%06d.jpg",fi++]];
NSLog(#"p_displayNextFrame write image file: %#",fileName);
// frame is saved successfully as jpg, I can view it
[UIImageJPEGRepresentation(frame, 0.7) writeToFile:fileName atomically:YES];
// leak(but not crash) in emulator, crash on device
self.imageView.image = frame;
// At your header you should declare : #property ZCVFrameSec *currentFrameSec;
self.currentFrameSec = frameSec;
double delayInSeconds = 0.05;//1/30.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self p_displayNextFrame];
});
}

iOS MobileSubstrate CFNotificationCenterPostNotification - Not working

I have a SpringBoard hook which listens to Distributed notifications. Various other apps I have hooked post notification which are received in SpringBoard.
If I pass userInfo as null, SpringBoard receives notifications from all apps. If I pass CFDictionaryRef as userInfo, SpringBoard receives notifications from only SpringBoard and SystemApps. However user apps are not able to send notifications. (Or rather not received by Springboard).
CFDictionaryRef is innocent and not the culprit because I am able to pass it when sender and receiver are system apps.
Is there a restriction that User Apps cannot send userInfo object to System Apps?
EDIT:
Attaching the code. I compile it using iOSOpenDev. Rely on NSLog to debug.
Scenario 1: If you touch SpringBoard, you would see 2 logs for notification send and notification received.
Scenario 2: Invoke any system app like clock etc, you would see both logs.
Scenario 3: Any app from app store, like SketchBookX etc, and only one log will be printed for notification send. Its not received.
I have tried all flavors of CFNotificationCenterPostNotification but nothing works.
#import <UIKit/UIKit.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFNotificationCenter.h>
#include "GraphicsServices/GSEvent.h"
#define GS_EVENT_TYPE_OFFSET 2
#define HOME_DOWN 1000
#define HOME_UP 1001
#define VOL_DOWN_KEY_DOWN 1008
#define VOL_DOWN_KEY_UP 1009
extern "C" CFNotificationCenterRef CFNotificationCenterGetDistributedCenter(void);
void LogEvent(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
NSString *str = [[NSString alloc]initWithFormat:#"%#,%#,%d,%d,%d,%d,%d\r\n",
(NSString*)CFDictionaryGetValue(userInfo,#"strWindow"),
(NSString*)CFDictionaryGetValue(userInfo,#"strView"),
[(NSNumber*)CFDictionaryGetValue(userInfo,#"phase") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,#"xInView") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,#"yInView") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,#"xInWindow") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,#"yInWindow") intValue]];
NSLog(#"Area51 Notification Received: %#",str);
}
%hook UIApplication
-(void) sendEvent:(UIEvent*)event
{
if( [NSStringFromClass([event class]) isEqualToString:#"UITouchesEvent"] )
{
NSSet *touches = [event allTouches];
NSEnumerator *enumerator = [touches objectEnumerator];
id value;
while ((value = [enumerator nextObject])) {
UITouch *touch = value;
NSString *strViewClassName;
if(!touch.view)
strViewClassName = #" ";
else
strViewClassName = [NSString stringWithString:NSStringFromClass([[touch view] class])];
CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL,0,&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(dictionary, #"phase", [NSNumber numberWithInt:[touch phase]] );
CFDictionaryAddValue(dictionary, #"strWindow", NSStringFromClass([[touch window] class]) );
CFDictionaryAddValue(dictionary, #"strView", strViewClassName);
CFDictionaryAddValue(dictionary, #"xInView", [NSNumber numberWithInt:[touch locationInView:touch.view].x]) ;
CFDictionaryAddValue(dictionary, #"yInView", [NSNumber numberWithInt:[touch locationInView:touch.view].y]) ;
CFDictionaryAddValue(dictionary, #"xInWindow", [NSNumber numberWithInt:[touch locationInView:nil].x]) ;
CFDictionaryAddValue(dictionary, #"yInWindow", [NSNumber numberWithInt:[touch locationInView:nil].y]) ;
CFNotificationCenterPostNotificationWithOptions(
CFNotificationCenterGetDistributedCenter(),
(CFStringRef)#"RecordTouch",
NULL,
dictionary,
kCFNotificationDeliverImmediately|kCFNotificationPostToAllSessions);
NSLog(#"Area 51: Notification Send for App: %#",[[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleDisplayName"] );
}
}
%orig;
}
%end
%hook SpringBoard
-(void)applicationDidFinishLaunching:(UIApplication*) application
{
CFNotificationCenterAddObserver(
CFNotificationCenterGetDistributedCenter(),
NULL,
LogEvent,
NULL,
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
NSLog(#"Area51: ObserverAdded");
%orig;
}
%end
__attribute__((constructor)) void area51init() {
%init;
}
The problem seems to be that userInfo is ignored (and thus NULL) when using a Darwin Notification Center as center. Source
Also see this thread.

iOS UIWebview crash if copy text from the displayed pdf

i've tried to search a lot inside stackoverflow and in google before ask my question.
Seems to be similar questions but for me without answer.
So i'm trying to ask!!
i've a view controller presented as presentModalViewController with inside a uitoolbar and a uiwebview.
In the web view is displayed a pdf file. The web view as default allow me to select a text and show to me the copy function of the standard UIMenuController.
At this point if i dismiss the view controller the app crash with this logged error showed in the console:
libobjc.A.dylib`objc_msgSend:
0x372daf68: teq.w r0, #0
0x372daf6c: beq 0x372dafaa ; objc_msgSend + 66
0x372daf6e: push.w {r3, r4}
0x372daf72: ldr r4, [r0]
0x372daf74: lsr.w r9, r1, #2
0x372daf78: ldr r3, [r4, #8]
0x372daf7a: add.w r3, r3, #8
0x372daf7e: ldr r12, [r3, #-8]
0x372daf82: and.w r9, r9, r12
0x372daf86: ldr.w r4, [r3, r9, lsl #2]
0x372daf8a: teq.w r4, #0
0x372daf8e: add.w r9, r9, #1
0x372daf92: beq 0x372dafa6 ; objc_msgSend + 62
0x372daf94: ldr.w r12, [r4]
0x372daf98: teq.w r1, r12
0x372daf9c: bne 0x372db17e ; objc_msgSendSuper_stret + 34
0x372daf9e: ldr.w r12, [r4, #8]
0x372dafa2: pop {r3, r4}
0x372dafa4: bx r12
0x372dafa6: pop {r3, r4}
0x372dafa8: b 0x372dafb0 ; objc_msgSend_uncached
0x372dafaa: mov.w r1, #0
0x372dafae: bx lr
I don't understand if this is a my error o a bug of the uiwebview
I've also tried to use CGPDFDocument for render a pdf page but i'm not able to show the UIMenuController and select the text and perform the standard copy action inside the document.
I've also tried to start with this excellent project but also in this i can not perform copy action - https://github.com/vfr/Reader
Basically these are the used code.
I'm working with iOS 5 with ARC
- (void)viewDidLoad
{
[super viewDidLoad];
if (![urlPdfFile hasPrefix:#"http"]) {
NSString *ofType = [urlPdfFile pathExtension];
NSString *pathForResource = [[[urlPdfFile lastPathComponent] componentsSeparatedByString:#"."] objectAtIndex:0];
NSString *inDirectory = [urlPdfFile stringByDeletingLastPathComponent];
NSString *url = [[NSBundle mainBundle] pathForResource:pathForResource
ofType:ofType
inDirectory:inDirectory];
[self loadCatalogueFile:url];
} else {
[self loadFile:urlPdfFile];
}
}
- (void)viewDidUnload
{
[self setMyWebView:nil];
[super viewDidUnload];
}
-(void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.view removeFromSuperview];
self.view=nil;
[self viewDidUnload];
}
-(void)loadCatalogueFile:(NSString*)url {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:url]];
[myWebView loadRequest:request];
}
-(void)loadFile:(NSString*)url
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[myWebView loadRequest:request];
}
-(void) webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
//
}
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
//
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
//
}
Thank you very much for your help!!!
Had the same problem.
Mine was caused because I retained the view controller which holds the UIWebView, and re-used it.
To fix it just create the view controller each time from scratch.

Stuck in loop form CFRunLoop

ViewController.h
#interface ViewController : UIViewController{
CFSocketRef s;
int connectFlag;
}
ViewController.m
void receiveDataCilent(CFSocketRef cs,
CFSocketCallBackType type,
CFDataRef address,
const void *data,
void *info)
{
CFDataRef df = (CFDataRef) data;
int len = CFDataGetLength(df);
if(len <= 0) return;
CFRange range = CFRangeMake(0,len);
UInt8 buffer[len];
NSLog(#"Received %d bytes from socket %d\n",
len, CFSocketGetNative(cs));
CFDataGetBytes(df, range, buffer);
NSLog(#"Client received: %s\n", buffer);
NSLog(#"As UInt8 coding: %#", df);
NSLog(#"len value: %d", len);
}
-(void) clientConnect:(int)sender;{
s = CFSocketCreate(NULL, PF_INET,
SOCK_STREAM, IPPROTO_TCP,
kCFSocketDataCallBack,
receiveDataCilent,
NULL);
struct sockaddr_in sin;
struct hostent *host;
memset(&sin, 0, sizeof(sin));
host = gethostbyname("localhost");
memcpy(&(sin.sin_addr), host->h_addr,host->h_length);
sin.sin_family = AF_INET;
sin.sin_port = htons(6666);
CFDataRef address;
CFRunLoopSourceRef source;
address = CFDataCreate(NULL, (UInt8 *)&sin, sizeof(sin));
CFSocketConnectToAddress(s, address, 0);
CFRelease(address);
source = CFSocketCreateRunLoopSource(NULL, s, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(),
source,
kCFRunLoopDefaultMode);
CFRelease(source);
CFRunLoopRun();
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if(connectFlag == 0 ){
[self clientConnect:1];
}
}
First I'm sorry for messing the concept of xcode programming and threading programming I'm very new to xcode and I need to finish my game project soon
This code is suppose to connect to server and waiting for message from server. I try and test it and it work fine. In view I have IBAction that can press and change view.
But after I implement it to my main project. It can run but I cannot press any button or do anything. After log it out. It seem it stuck around CFRunLoopRun(); I think it stuck in loop but why when I test it. it not stuck ?
In my project this code is run from another view not from ViewController like I just test.
I don't know why it stuck in my project.
Any help would be appreciated.
Don't run the run loop yourself on the main thread. The main event loop will run it.
Edit: I should say, "within the context of a GUI app". In a command-line tool, you do need to run the run loop yourself.

Resources