I get this warning in Xcode
warning: Attempting to create USE_BLOCK_IN_FRAME variable with block
that isn't in the frame.
Xcode redirect me to my NSStream
_naturStream = [[NSInputStream alloc] initWithData:natur];
It is random when it does this error, and my application crashes when it is triggered. Anyone tried similar problem ?
thanks
EDIT
in the appDelegate.h
#property (nonatomic, strong) NSInputStream *naturStream;
In the appDelegate.m:
NSData *natur = [NSData dataWithContentsOfURL:[NSURL URLWithString:_locString]];
_naturStream = [[NSInputStream alloc] initWithData:natur];
[_naturStream open];
if (_naturStream) {
NSError *parseError = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithStream:_naturStream options:NSJSONReadingAllowFragments error:&parseError];
if ([jsonObject respondsToSelector:#selector(objectForKey:)]) {
for (NSDictionary *natur in [jsonObject objectForKey:#"results"]) {
_poi = [[POI alloc]init];
[_poi setTitle:[natur objectForKey:#"title"]];
[_poi setLat:[[natur objectForKey:#"lat"]floatValue]];
[_poi setLon:[[natur objectForKey:#"lng"]floatValue]];
[_poi setDistance:[natur objectForKey:#"distance"]];
[_poi setWebUrl:[natur objectForKey:#"webpage"]];
[_naturArray addObject:_poi];
}
}
}
else {
NSLog(#"Failed to open stream.");
}
[_naturStream close];
}
I realized that i forgot [_naturStream close] i don't know if it has solved the problem or not ?
EDIT
Another thing,.... I use a Thread for fetching the JSON data:
dispatch_queue_t jsonParsingQueue = dispatch_queue_create("jsonParsingQueue", NULL);
// execute a task on that queue asynchronously
dispatch_async(jsonParsingQueue, ^{
[self parseJSON];
dispatch_async(dispatch_get_main_queue(), ^{
[_kortvisning updateAnno];
[visListe updateList];
});
});
// release the dispatch queue
dispatch_release(jsonParsingQueue);
Sounds like you're using ARC - if _naturStream is an instance variable for an objective C class, you might need to pull it out and add a __block reference so that ARC knows the scope correctly - but I'm guessing because I don't see how the block is used with the NSInputStream (if you post that part we might know). A good bit is here: http://nachbaur.com/blog/using-gcd-and-blocks-effectively
-- edit --
Ok, now that you posted the rest, I bet it has to do with the _kortvisning and visListe variables. I think you want to pull those out right after you create your queue something like
__block KortVisning *localKortVisning = _kortvisning;
__block NSMutableArray *localVisListe = visListe;
Then access those directly from your final completion handler you're sending back to the main queue.
Related
I'm getting occasional crashes in my GCDWebServer handlers, which access mutable dictionaries. The GCDWebServer ReadMe says the handlers "are executed on arbitrary threads within GCD so special attention must be paid to thread-safety and re-entrancy," and I think that's my problem. Is there a best practice or recommended pattern for accessing mutable properties of the parent object from the handlers?
I don't know if I can synchronize between threads since I'm not creating the handler threads. Also, I imagine I could use an asynchronous handler, then call a method on the main thread from there, then do my work in that method, then send the response, but that seems more complicated and less efficient than necessary.
Here's a simplified version of my code:
#property (nonatomic, strong) NSMutableDictionary *data;
#property (nonatomic, strong) GCDWebServer *webServer;
- (void)setup {
self.data = [NSMutableDictionary dictionary];
[self.data setObject:#"1" forKey:#"status"];
self.webServer = [[GCDWebServer alloc] init];
[self.webServer addHandlerForMethod:#"GET" path:#"/getStatus.txt" requestClass:[GCDWebServerRequest class] processBlock:^(GCDWebServerRequest *request) {
return [self handleStatusRequest:request];
}];
}
- (GCDWebServerDataResponse *)handleStatusRequest:(GCDWebServerRequest *)request {
NSString *status = [self.data objectForKey:#"status"]; // crash here
return [GCDWebServerDataResponse responseWithText:status];
}
Are you mutating your data dictionary after creating it? If so that would explain the crashes.
You must prevent concurrent access to your data dictionary by using locks. The easiest way is through GCD e.g.
#property dispatch_queue_t lock;
__block NSString* status;
dispatch_sync(self.lock, ^{
status = [self.data objectForKey:#"status"];
});
NSString* status = #"Hello";
dispatch_async(self.lock, ^{
[self.data setObject:status forKey:#"status"];
}); // Use dispatch_sync() or dispatch_async() here depending on your needs
looking for little help on accessing readonly property with Kiwi.
In short, I want to test if _myReadOnlyDict gets initialized or not.
Problem is that myReadOnlyDict is still always empty(has no contents), despite that in beforeEach block it is mocked and a value added to it.
// All these return 0
ad.myReadOnlyDict.count;
[[ad myReadOnlyDict] allKeys].count;
[ad myReadOnlyDict].count;
What I am missing here?
Any help is appreciated!
Please see the code below:
In AppDelegate.h I have a porperty.
#property (nonatomic, readonly) NSDictionary * myReadOnlyDict;
In AppDelegate.m I have a method, which is called from AppDelegate's didFinishLaunchingWithOptions method.
- (void)initConfig
{
_myReadOnlyDict = [NSJSONSerialization JSONObjectWithData:[self jsonData] options:nil error:nil];
}
I have a Kiwi test set up
describe(#"App Delegate", ^{
__block AppDelegate *ad;
beforeEach(^{
ad = [[AppDelegate alloc] init];
NSMutableDictionary * mockedDict = [NSJSONSerialization nullMock];
mockedDict[#"my_data"] = #"my_value";
[ad stub:#selector(myReadOnlyDict) andReturn:mockedDict];
});
afterEach(^{
ad = nil;
});
context(#"when smth happens", ^{
it(#"should do smth else", ^{
[[ad should] receive:#selector(initConfig)];
// These three lines fail
[[theValue([ad myReadOnlyDict].count) shouldNot] equal:theValue(0)];
[[theValue(ad.myReadOnlyDict.count) shouldNot] equal:theValue(0)];
[[theValue([[ad myReadOnlyDict] allKeys].count) shouldNot] equal:theValue(0)];
[ad initConfig];
});
});
});
Your problem is caused by the fact that [NSJSONSerialization nullMock]returns a null mock, which is an object that does nothing for any called method, and returns nil/0 to any method that must return something.
This should work:
NSMutableDictionary * mockedDict = [#{#"my_data": #"my_value"} mutableCopy];
[ad stub:#selector(myReadOnlyDict) andReturn:mockedDict];
Hi My problem is that i am getting a response from a web service and when i parse it and add to table and reload the table view it is not refreshing . Although if i call the [table reload] in keyboard is shown it gets updated there. Could someone tell me if im missing anything
This is what i am trying to do
- (void) longPoll {
//create an autorelease pool for the thread
#autoreleasepool {
NSLog(#"polling");
VSAppDelegate *var = (VSAppDelegate*)[[UIApplication sharedApplication] delegate];
//compose the request
NSError* error = nil;
NSHTTPURLResponse* response = nil;
//send the request (will block until a response comes back)
NSData* responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"polling response is %d",response.statusCode);
//pass the response on to the handler (can also check for errors here, if you want)
[self performSelectorOnMainThread:#selector(dataReceived:) withObject:responseData waitUntilDone:YES];
}
[self performSelectorInBackground:#selector(longPoll) withObject: nil];
}
- (void) startPoll {
[self performSelectorInBackground:#selector(longPoll) withObject: nil];
}
- (void) dataReceived: (NSData*) theData
{
//process the response here
NSError *error = nil;
NSLog(#"polling data is %#",[[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding]);
NSLog(#"polling data is %#",[[theData base64EncodedString]base64DecodedString]);
NSDictionary *notifDic= [NSJSONSerialization JSONObjectWithData:theData options:kNilOptions error:&error];
//VSViewControllerSplit *split = [[VSViewControllerSplit alloc]init];
[self RecieveFunction:notifDic];
}
try it
dispatch_async(dispatch_get_main_queue(), ^{
[tablrView reloaddata];
});
The dataReceived method doesn't appear to be calling reloadData. I'll assume that RecieveFunction method does, though, but you should confirm that. It's hard to say without seeing RecieveFunction.
The more fundamental issue would appear to be that dataReceived method is creating a new instance of VSViewControllerSplit, calling its RecieveFunction method, and then letting this new VSViewControllerSplit instance fall out of scope (and if using ARC, get deallocated unless you pushed to it, presented it, etc.). You presumably don't want to create a new VSViewControllerSplit every time longPoll calls dataReceived, but rather just reference the existing instance.
I have a UITableView that gets its data from an array. Populating that array, however, requires downloading and parsing large chucks of data from the Web. That being the case, I'd like perform those operations in a background thread. Here's what I've got so far:
#interface MyClass()
#property (nonatomic, strong) NSArray *model;
#end
#implementation MyClass
- (void) getData {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:SOME_URL]];
if (data) {
NSMutableArray *arr = [NSMutableArray array];
//Populate arr with data just fetched, which can take a while
dispatch_async(dispatch_get_main_queue(), ^{
//THIS IS THE STEP I AM UNSURE ABOUT. SHOULD I DO:
self.model = arr;
//OR
self.model = [NSArray arrayWithArray:arr];
//OR
self.model = [arr copy];
//OR
//something else?
});
}
});
}
#end
Thank you!
// you can use any string instead "mythread"
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0);
dispatch_async(backgroundQueue, ^{
// Send Request to server for Data
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:SOME_URL]];
dispatch_async(dispatch_get_main_queue(), ^{
// Receive Result here for your request and perform UI Updation Task Here
if ([data length] > 0) {
// if you receive any data in Response, Parse it either (XML or JSON) and reload tableview new data
}
});
});
You should do:
self.model = arr;
The reference to self calls the setter, which will release any previous references in that variable and then add a reference count to arr so it doesn't go out of scope. If you were accessing the ivar directly you would do:
[model release];
model = [arr retain];
Take a look at this link Understanding dispatch_async and this https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
You should add DISPATCH_QUEUE_PRIORITY_BACKGROUND instead of DISPATCH_QUEUE_PRIORITY_DEFAULT to run this on the background.
By using DISPATCH_QUEUE_PRIORITY_DEFAULT you just made your task be classified as a normal task. If you have changed it to higher or lower priority, the queue would have run it before or after some other tasks, respectively.
I am creating a update method for in house enterprise apps. What I am trying to create is a class that I can quickly put in a app and it will check with the server if it needs to be updated. This is what I have so far, it checks correctly but its returning NO before it finishes the method.
In my checkUpdate.h
#interface checkForUpdate : NSObject
+ (BOOL)updateCheck;
#end
In my checkUpdate.m
#import "checkForUpdate.h"
#implementation checkForUpdate
BOOL needsUpdate
NSDictionary *versionDict;
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
+ (BOOL)updateCheck {
NSString *urlStringVersion = [[NSString alloc] initWithFormat:#"http://URL/app_info?app=app"];
NSURL *urlVersion = [NSURL URLWithString:urlStringVersion];
dispatch_async(kBgQueue, ^{
NSData* data =[NSData dataWithContentsOfURL:urlVersion];
if (data){
NSError* error;
NSArray* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (json != nil && [json count] != 0) {
versionDict = [json objectAtIndex:0];
CGFloat serverVersion = [[versionDict valueForKey:#"version"]floatValue];
CGFloat appVersion = [[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey] floatValue];
NSLog(#"Server Version %f",serverVersion);
NSLog(#"App Version %f",appVersion);
if ([versionDict count] != 0){
if (serverVersion > appVersion){
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:1];
needsUpdate = YES;
}else{
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
needsUpdate = NO;
}
}
}
}
});
return needsUpdate;
}
#end
I call it like this
NSLog(#"Needs Update %#",[checkForUpdate checkForUpdateWithResponse] ? #"Yes":#"No");
This is my log
Needs Update No
Server Version 2.000000
App Version 1.000000
I'm not sure why it's returning NO before it even checks. I need it to be a asynchronous because the server that the app will check with is behind our firewall. So if the person is outside the firewall the app needs to continue when is can't reach the server. I'm I headed in the right direction, or is there a better way?
You are asynchronously checking for an update but expecting an immediate response by virtue of your method's design. You can re-engineer your method to something like the example below to notify a handler whenever the operation is complete:
Note: Unchecked and untested for errors; however, the lesson to be gleaned from the example is to use a callback of sorts:
UpdateChecker Class
typedef void (^onComplete)(BOOL requiresUpdate);
#interface UpdateChecker : NSObject
-(void)checkForUpdates:(onComplete)completionHandler;
#end
#implementation UpdateChecker
-(void)checkForUpdates:(onComplete)completionHandler
{
NSString *urlStringVersion = [[NSString alloc] initWithFormat:#"http://URL/app_info?app=app"];
NSURL *urlVersion = [NSURL URLWithString:urlStringVersion];
dispatch_block_t executionBlock =
^{
/*
Your update checking script here
(Use the same logic you are currently using to retrieve the data using the url)
*/
NSData* data = [NSData dataWithContentsOfURL:urlVersion];
BOOL requiresUpdate = NO;
if (data)
{
...
...
...
requiresUpdate = ...; //<-whatever your outcome
}
//Then when completed, notify the handler (this is our callback)
//Note: I typically call the handler on the main thread, but is not required.
//Suit to taste.
dispatch_async(dispatch_get_main_queue(),
^{
if (completionHandler!=NULL)
completionHandler(requiresUpdate);
});
};
dispatch_async(kBgQueue, executionBlock);
}
#end
This is what it would look when you use UpdateChecker to check for updates throughout your app
UpdateChecker *checker = [UpdateChecker alloc] init];
[checker checkForUpdates:^(BOOL requiresUpdate)
{
if (requiresUpdate)
{
//Do something if your app requires update
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:1];
}
else
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
}];
Since dispatch_async is non-blocking, your method returns before your update information has returned (does the dispatch and continues). As needsUpdate defaults to NO, that's what you'll see. You can see this in your log timing - the "Needs Update No" shows up before the server and app versions.
You need some sort of callback (a delegate method or second dispatch_async for example) to ensure you get the correct result, or you need to block. I recommend looking into NSURLConnection, and sendAsynchronousRequest:queue:completionHandler: - it will execute the completion handler on completion, where you can have whatever code you need for handling the update.