Use variable with in block - objective-c-blocks

I am using some public APIs for displaying images where i am using following code to show image full screen and once full screen is closed i want to call RateImage: method with imgID
__block NSString *imgID = _img.ImageID;
[cell.imageView setupImageViewerWithImageURL:[NSURL URLWithString:strImageURL] onOpen:^{
NSLog(#"Open");
} onClose:^{
[MyAppDelegate RateImage:imgID];
}];
I dont know for some reason my application crashes.
error: address doesn't contain a section that points to a section in a object file
I have been through this
can any one tell how to pass value with in block?

Related

Creating a PDF from WKWebView in macOS 11.+

As WKWebView contents can finally be printed out in macOS 11+, I'm trying to replace old WebView dependencies.
However, with the HTML correctly loaded in WKWebView, creating PDF files using NSPrintJobDisposition: NSPrintSaveJob produces blank, empty documents. They have the correct page count and sizing, but remain empty. Using the same code without NSPrintSaveJob works just fine.
This is how I'm printing the contents:
NSPrintInfo *printInfo = NSPrintInfo.sharedPrintInfo;
[printInfo.dictionary addEntriesFromDictionary:#{
NSPrintJobDisposition: NSPrintSaveJob,
NSPrintJobSavingURL: url
}];
NSPrintOperation *printOperation =[(WKWebView*)_webView printOperationWithPrintInfo:printInfo];
printOperation.view.frame = NSMakeRect(0,0, printInfo.paperSize.width, printInfo.paperSize.height);
printOperation.showsPrintPanel = NO;
printOperation.showsProgressPanel = YES;
[printOperation runOperation];
Setting showsPrintPanel as true and uncommenting the dictionary will display a normal print dialog, and the result looks completely normal there.
I'm confused about what I am doing wrong, or is printing from WKWebView still this buggy?
Sample project:
https://www.dropbox.com/s/t220cn8orooorwb/WebkitPDFTest.zip?dl=1
Create PDF and Print buttons share the same code (found in PreviewView), but the other produces an empty file, which is then loaded into the PDFView.
Further findings
By what I've gathered online, this could be a long-running bug.
It seems that WKWebView prefers using its createPDF method when creating PDF files in the background, but that method renders what is displayed on screen, not the actual document content with page breaks and print stylization. It also appears to ignore some NSPrintInfo settings.
WKWebView printing is very badly documented. The reason for the blank pages is the run-loop code in WebKit, and all printing must happen asynchronously.
This is why [printOperation runOperation] / printOperation.runOperation() does not work. Instead, you need to call the strangely named runOperationModalForWindow. Although the method name refers to a modal window, you don't need to display the modal, but this method somehow makes the print operation asynchronous.
// Create print operation
NSPrintOperation *printOperation = [webView printOperationWithPrintInfo:printInfo];
// Set web view bounds - without this, the operation will crash
printOperation.view.frame = NSMakeRect(0,0, printInfo.paperSize.width, printInfo.paperSize.height);
// Print it out
[printOperation runOperationModalForWindow:self.window delegate:self didRunSelector:#selector(printOperationDidRun:success:contextInfo:) contextInfo:nil];
You also need to have a handler method to catch the results:
- (void)printOperationDidRun:(id)operation success:(bool)success contextInfo:(nullable void *)contextInfo {
// Do something with your print
}

Synchronize operations inside a for loop

I'm using the QBImagePickerControllerlibrary to select more than one image in the provided Image Picker view.
I want to let the user upload more than a single image to the "main" server, with a UIImageView displaying what is uploaded at the moment and a UIProgressView.
Since
- (void)imagePickerController:(QBImagePickerController *)imagePickerController didSelectAssets:(NSArray *)assets
give me an array of ALAssets containig all the images the user selected, I iterate through it this way:
NSMutableArray *IDs = [[NSMutableArray alloc] init];
if([assets count] == 1) {
// single image, no prob.
} else {
for(ALAsset *a in assets) {
//set the image to the one which is uploaded right now
//upload it through a library and tell about status with NSProgress
//write the result into IDs
}
}
My problem is that if the user select two images, the operations appears to be running at the same time, so the UIProgressView is uploaded in what seems a "first come, first served" scenario, while the UIImageViewshows only the last image selected and IDs seems empty.
Is this behaviour due to the method I use to iterate through the array?
What can I do to make each operation mutually exclusive?

Cocos2D project with tileMap. Invalid positions returned

I have a project in which I am trying to implement a pathfinding class but I have stumbled upon an issue I can't seem to fix.
A video of the error as it occurs can be found here:
https://www.dropbox.com/s/25ajb0mc5p4a3a9/Tilemap%20Error.mov
The error message thrown is: Assertion failure in -[CCTMXLayer tileGIDAt:withFlags:], /Users/Dave/Desktop/AI_DISS_new copy/AI_DISS/libs/cocos2d/CCTMXLayer.m:304
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'TMXLayer: invalid position'.
The point returns as pixel values while the map and layer sizes return in tile values so I tried dividing variables holding pixel values by the width or height of the tiles but nothing seems to have worked.
GID for tileAt:point returns too high when using pixel values (understandably) and when converted to tile values, searches for a very long time, eventually moving off the map and continuously searching until Xcode crashes.
I have tried to explain in as much detail as possible I apologize if this isn't the kind of question best suited to this forum. I would really appreciate any assistance.
If you need further details please ask.
The original instructions for using the class were on cocos2d forums which have just had an overhaul and the thread appears to have been moved or deleted so I can't quote them but I am sure the tilemap (a TMX Tilemap) and layer attributes have been passed in correctly.
From my HelloWorldLayer class the values are:
//Pathfinding related code
////////////////////////////
_tileMap = [CCTMXTiledMap tiledMapWithTMXFile:#"NewMap.tmx"];
_pathFinder = [[AStar alloc] initWithTileMap:_tileMap groundLayer:#"Collision"]; //collidable Tiles
[_pathFinder setCollideKey:#"Collidable"]; // defaults to COLLIDE
[_pathFinder setCollideValue:#"True"]; // defaults to 1
_pathFinder2 = [[AStar alloc] initWithTileMap:_tileMap groundLayer:#"Collision"]; //collidable Tiles
[_pathFinder2 setCollideKey:#"Collidable"]; // defaults to COLLIDE
[_pathFinder2 setCollideValue:#"True"]; // defaults to 1
/////////////////////////////
and the move method is called as:
/////////////// player path finding related code //////////////////
[_pathFinder moveSprite:_player from:s to:f atSpeed:0.003];
///////////// end player path finding related code //////////////
Thanks in advance.
GID Code as commented on below:
if (tileGid)
{
// check the tile for the collide property.
NSDictionary *dict = [tileMap propertiesForGID:tileGid];
if (dict)
{
//check the tile for the collideKey and return Yes if a match
NSString *collide = [dict valueForKey:collideKey];
if (collide && [collide compare:collideValue] == NSOrderedSame)
return YES;
}
}

Cocoa app behaves diffirently with breakpoint on & off

Important update: I found out that most part of my question was based on a false premise (see my answer below). Notifications actually got to the receiver, they just got there too fast. (Although, it still doesn't explain why the behavior with breakpoint and without it was different.)
I'm developing the app that calculates the hashes of files given to it. The calculation takes place in SHHashComputer. It's an abstract class (well, intended to be abstract, as there are no abstract classes in Objective C) that takes the file path and creates an NSInvocationOperation. It, in turn, calls the method (void)computeAndSendHash, which uses the file path saved in the object to compute hash and sends it as notification. The actual computing takes place in (NSString*)computeHash method that child classes need to override.
Here's SHHashComputer.m:
- (NSString*)computeHash {
return [NSString stringWithFormat:#"unimplemented hash for file %#", self.path];
}
- (void)computeAndSendHash {
NSString *result = [self computeHash];
NSString *notificationName = [NSString stringWithFormat:#"%#%#",
gotResultNotification,
self.hashType];
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName
object:result];
self.operation = nil;
}
And here's SHMD5Computer.m (the child class of SHHashComputer):
- (NSString*)computeHash {
return #"MD5 test"; // it actually doesn't matter what it returns
}
I won't bother you with the receivers of notification. Let's just say that as long as I comment out the computeHash method in SHMD5Computer.m everything works just fine: the notification with text "unimplemented ..." is received & displayed in GUI. But if I don't — then it gets really interesting.
If I don't set up any breakpoints, the notification just never comes. However, if I set up a breakpoint at the declaration of computeHash in SHMD5Computer.h and then step over until the line 'self.operation = nil', and continue execution at that point, the notification gets to destination. If I don't stop there, the debugger suddenly switches to the state as if it isn't debugging anything, and the app freezes.
I don't think that 'WTF' is a good form for a question here, so let me put it this way: am I missing something? Are there errors in my code? What can cause this type of behavior in xcode? How can I fix this?
(If you'll want to get all my code to reproduce it, I'll gladly give it to you.)
More experiments:
If I continute execution exactly after stopping at breakpoint, the application encounters EXC_BAD_ACCESS error in the code that receives the notification, at the last line:
id newResult = [newResultNotification object];
if (newResult == nil)
[NSException raise:#"No object"
format:#"Expected object with notification!"];
else if (![newResult isKindOfClass:[NSString class]])
[NSException raise:#"Not NSString"
format:#"Expected NSString object!"];
else
self.result = (NSString*) newResult;
[self.textField setStringValue:self.result];
When I tried to reproduce the previous experiment, something even stranger happenned. In my debug setup, I have two hash computer objects: one SHMD5HashComputer (which we're talking about), and one SHHashComputer (which, of course, produces the "unimpemented" hash). In all previous experiments, as long as app didn't crash, the notification form SHHashComputer always successfully arrived. But in this case, both notifications didn't arrive, and the app didn't crash. (All the steps are exactly the same as in previous one).
As Josh Caswell pointer out in the comments, I wasn't using the notifications correctly. I should've sent the object itself as notification object, as described in documentation. I fixed that, and I'm getting exactly the same results. (Which means that I fixed it correctly, because sometimes the notifications work correctly, and also that it wasn't the problem).
More updates:
The notification that I'm sending should arrive at SHHashResultViewController. That's how I create it and register for notification:
- (id)initWithHashType:(NSString *)hashType {
self = [self initWithNibName:#"SHHashResultView" bundle:[NSBundle mainBundle]];
if (self) {
[self setHashType:hashType];
}
return self;
}
- (void)setHashType:(NSString *)hashType {
[self.label setStringValue:[NSString stringWithFormat:#"%#:", hashType]];
_hashType = hashType;
NSString *notificationName = [NSString stringWithFormat:#"%#%#",
gotResultNotification,
_hashType];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(gotResult:)
name:notificationName
object:nil];
}
Actually, the question was based on a false premise. I thought that notification never came through because I never saw the information displayed in the GUI; however, my error was in the code of controllers (not published there) which made possible the situation in which the GUI first got results of hash calculation and only after that got information about a new input — which resulted in deleting all the text and activating progress animation.

Get EXC_BAD_ACCESS when tableview get data from URL?

My tableview is get XML data from URL,First I declare a NSMutableArray *dataArray;
and this is how I get the data in my TableviewSample.m
- (void)getDataFromURL{
NSString *theURLAsString = [NSString stringWithFormat:GetAllData];//<-EXE_BAD_ACCESS HERE
//#define stringWithFormat:GetAllData #"http://192.168.10.28/req_alldata.php"
NSURL *theURL = [NSURL URLWithString:theURLAsString];
self.dataArray = [NSMutableArray arrayWithContentsOfURL:theURL];
}
Then I just get the elements form this array to my tableview ...
But here I have to say one more thing , actually it won't crash before I add another view...
I add a bar button to go to a webView , this webView is use to load a IP Cam stream video
When I back to the tableview , It will appear EXC_BAD_ACCESS
This is odd things I cannot to solve it...because both side code are all looks normal
If I remove this webview ,no matter how I run the program ,it won't crash...
And sometimes I leave the webView I will receive memory warning :level 2
But just only one time.
or do I use a wrong way to open an ip cam stream ???
Thanks for all reply : )
OK,here is the code different I use in my webview class
This is first version I use
- (void)viewDidAppear:(BOOL)animated{
NSString *directGoToWebCam = [NSString stringWithFormat:GetAllData];
self.IPCamWebView=[[[UIWebView alloc] initWithFrame:CGRectMake(0,0,640,960)] autorelease];
[self.IPCamWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:directGoToWebCam]]];
[self.view addSubview:self.IPCamWebView];
}
Where does GetAllData come from? It looks like that isn't pointing to anything. More code, the exact error, and a more careful description will go a long way here.
It probably has something to do with the use of #define which does not say anything about the type of the object you are using.
If you want to define a constant string in your code the best would be to use something like this:
static NSString *GetAllData = #"192.168.10.28/req_alldata.php";
Where you need to use the string you can simply write:
NSString *GoToWebCam = [NSString stringWithString:GetAllData];