Wait for MKReverseGeocoder to provide address - iphone

Is there a way to wait for geocoder to invoke didFailWithError or didFindPlaceMark?
My problem is that i have to call a method that receives coordinate and returns placemark holding the address. But when i call [myGeocoder start] code continues and i get an empty placemark.
My code is:
- (MKPlasemark*) getAddress:(CLLocationCoordinate2D) coordinate
{
[self startGeocoder:coordinate];
return self.foundPlasemark;
}
- (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFindPlacemark:(MKPlaseMark*)plasemark
{
self.foundPlasemark=plasemark;
}
- (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFailWithError:(NSError*)error
{
self.foundPlasemark=nil;
}
I tryed to perform sleep() whyle one of the following methods invoked, but it didn't work.

I think you are going about it the wrong way, there is no reason to block, what you have to do is have that method return void, and in the class that is handling the geocoding, define a protocol that has a method say -(void)didReceivePlacemark:(id)placemark, placemark can be nil or some placemark, and it is called when the geocoder returns. You also make a delegate property for your class so anyone can subscribe to the protocol... Then in the calling class subscribe to the protocol and implement the method...heres a bit more on protocols
Hope that helps
Here is an example:
So the interface of your class that does the geocoding will look something like this
#protocol GeocoderControllerDelegate
-(void)didFindGeoTag:(id)sender; // this is the call back method
#end
#interface GeocoderController : NSObject {
id delegate;
}
#property(assign) id <GeocoderControllerDelegate> delegate;
Then in the implementation you would see something like this
- (void) getAddress:(CLLocationCoordinate2D) coordinate
{
[self startGeocoder:coordinate];
}
- (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFindPlacemark:(MKPlaseMark*)plasemark
{
[delegate didFindGeoTag:plasemark];
}
- (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFailWithError:(NSError*)error
{
[delegate didFindGeoTag:nil]
}
In the calling class, all you have to set is the delegate property of the GeocoderClass, and implement the protocol, the implementation might look somethign like
-(void)findMethod
{
GeocoderController *c=...
[c setDelegate:self];
[c findAddress];
//at this point u stop doing anything and just wait for the call back to occur
//this is much preferable than blocking
}
-(void)didFindGeoTag:(id)sender
{
if(sender)
{
//do something with placemark
}
else
{
//geocoding failed
}
}

Related

Swift JSValue callWithArguments() within nested completion handler results in BAD_ACCESS

I have a simple function that takes a completion handler as a JSValue. It's a JSValue because I'm using this function as part of JSExport protocol.
This function then calls another internal method with another completion handler. When this second handler is called, I want to callWithArguments on the JSValue.
This all works as expected when I callWithArguments from outside the second completion handler, but I get a BAD_ACCESS when calling from the second handler.
func myFunction(completion: JSValue) {
// If I put completion.callWithAttributes([]) here, everything works fine.
self.mySecondFunction(completion: {(result: Dictionary<String, AnyObject>) -> Void in
// If I put completion.callWithAttributes([]) here, I get a BAD_ACCESS
})
}
Any help greatly appreciated. Thanks!
I strongly suggest you to do the following
[self.callback.context[#"setTimeout"]
callWithArguments:#[callback, #0, items]];
when you are going to send response to the JavaScriptCore counterpart. This will prevent the TVML UI MainThread to hang. As you can see it's a call of the setTimeout javascript function with delay 0, your callback and items as parameters like:
setTimeout(callback,0,items)
I'm not sure how you are creating the alert anyways here is one from Apple:
createAlert : function(title, description) {
var alertString = `<?xml version="1.0" encoding="UTF-8" ?>
<document>
<alertTemplate>
<title>${title}</title>
<description>${description}</description>
<button class="btn_close">
<text>OK</text>
</button>
</alertTemplate>
</document>`
var parser = new DOMParser();
var alertDoc = parser.parseFromString(alertString, "application/xml");
return alertDoc
}
There is no direct relationship with the alert and the behavior you are seeing here, it's more a side effect of calling this
completion.callWithArguments([])
in a unexpected way. It's better that you save your completion somewhere, and get a reference to it on the object instance. Then, when the long task ends, you call it. Also if you are performing a long task, it's reasonable that you move everything in a NSOperation like this:
/** JavaScriptCore Callback Operation */
#interface JSCallbackOperation: NSOperation
#property(nonatomic, strong) JSValue*callback;
#property(nonatomic, strong) id items;
#end
#implementation JSCallbackOperation
- (id)initWithItems:(id)items callback:(JSValue*)callback {
if(self = [super init]) {
self.items=items;
self.callback=callback;
}
return self;
}
- (void)main {
#autoreleasepool {
if(self.callback) {
NSLog(#"Dispatching %#", self.callback);
[self.callback.context[#"setTimeout"]
callWithArguments:#[self.callback, #0, self.items]];
}
}
}
At this point you define a helper a call the callbacks with parameters then:
#pragma mark - API Helper
- (void)handleResponseWithItems:(id)items callback:(JSValue*)callback {
NSArray *active_and_pending_operations = operationQueue.operations;
NSInteger count_of_operations = operationQueue.operationCount;
NSLog(#"Running operations: %ld of %ld", active_and_pending_operations.count, count_of_operations);
JSCallbackOperation *op = [[JSCallbackOperation alloc] initWithItems:items callback:callback];
[op setQueuePriority:NSOperationQueuePriorityNormal];
[op setCompletionBlock:^{
NSLog(#"Operation completed.");
}];
[operationQueue addOperation:op];
}

Two Independent Delegate Methods in a Class

I have two independent delegate methods in a class.
- (void)delegateMethod1:(id)data {
self.data = data;
}
- (void)delegateMethod2 {
[someClass sendData:self.data];
}
Now, this works fine sometimes but the other times, delegateMethod2 gets called before delegateMethod1.
I need to know how to manage this elegantly so that the line: [someClass sendData:self.data]; gets called only when both delegateMethod1 and delegateMethod2 have been called.
I know I can do it by using a variable to set to something on each delegate call but there has to be an elegant way to do this.
Any help?
Remembering which delegate has been called seems the easiest and cleanest solution to me.
But you can make it symmetric by moving the check to a separate method, so that
is does not matter which delegate is called first:
- (void)checkIfDataCanBeSent {
if (self.method1called && self.method2called) {
[someClass sendData:self.data];
}
}
- (void)delegateMethod1:(id)data {
self.method1called = YES;
// ...
[self checkIfDataCanBeSent];
}
- (void)delegateMethod2 {
self.method2called = YES;
// ...
[self checkIfDataCanBeSent];
}
(I have assumed that all delegate methods are called on the main thread, otherwise
one would have to add some synchronization.)
I believe, using a indicative variable to be the most elegant way to get over this. But this variable has to be kept in the delegate caller object.
Pseudo-type explanation
#interface DelegateCaller
{
BOOL hasCalled1stMethod;
}
#property(nonatomic,weak) id delegate;
#end
#implementation DelegateCaller
-(void)in_some_process_1
{
[self.delegate delegateMethod1]; //call
hasCalled1stMethod = YES; //set indicator
}
-(void)in_some_process_2
{
if(hasCalled1stMethod)
{
[self.delegate delegateMethod2]; //call
hasCalled1stMethod = NO; //reset indicator for reuse, if required.
}
}
#end
This way you'll not have to maintain any variable in the delegate itself, because the regulation of calling is maintained in the caller-object itself.
Another case:
If the delegateMethod1 is called from some object1 and the delegateMethod2 is called from some other object2, then again the indicative variable method is the most elegant way (in this limited scenario)
Pseudo-type explanation:
#interface ClassDelegateObject //aka the callee
{
BOOL hasCalledMethod1;
}
#end
#implementation ClassDelegateObject
-(void)delegateMethod1:(NSData*)data
{
self.data = data;
hasCalledMethod1 = YES; //set the indicator.
}
-(void)delegateMethod2
{
//here relying on the self.data!=nil will not be fruitful
//in case the self.data is not nil and hold some previous garbage data then
//this logic will fail.
if(hasCalledMethod1)
{
[someClass sendData:self.data];
hasCalledMethod1 = NO; //reset the variable for reuse if required.
}
}
#end
I would suggest that you rethink how the code works. Maybe you can check if there is no data and if so send it once it is ready:
- (void)delegateMethod1:(id)data {
self.data = data;
if (self.dataShouldBeSentWhenReady) {
[self sendData];
}
}
- (void)delegateMethod2 {
if (self.data) {
[self sendData];
} else {
[self setDataShouldBeSentWhenReady:YES];
}
}
- (void)sendData {
[self setDataShouldBeSentWhenReady:NO];
[someClass sendData:self.data];
}

Calling a function from another class in theos(logos) Jailbreak

I'm trying to run a function from another Class in another Class.
I want to call -(void)updateClock from the Class SBAwayView
Ive tried [[%c(SBAwayDateView) sharedInstance] updateClock];
Ive also tried [%c(SBAwayDateView) updateClock];
but I can't get it to work. (the SpringBoard crashes and I'm in safemode)
Below is the SBAwayDateView Class
%hook SBAwayDateView
-(void)updateClock
{
//do some stuff
//run %orig;
%orig;
}
%end
How can I run -(void)updateClock in SBAwayView Class below?
%hook SBAwayView
-(void)updateInterface
{
//do some stuff
//How can I run -(void)updateClock here?
//run %orig;
%orig;
}
%end
Thanks in advance.
SBAwayDateView doesn't have sharedInstance nor updateClock class methods.
In cases when you are working with class that is not a singleton you need to either find valid instance of this class in some other class - it might contain it in instance variable or return from some method. Or you can hook init method and save somewhere instances yourself. Depends on what you want to do.
In your case SBAwayView has instance variable SBAwayDateView *_dateHeaderView - problem solved
%hook SBAwayView
-(void)updateInterface
{
//do some stuff
SBAwayDateView* dateView = MSHookIvar<SBAwayDateView*>(self, "_dateHeaderView");
[dateView updateClock];
//run %orig;
%orig;
}
%end

How to stub out the return value on a class based method using ocmock

I'm writing a test to verify location services are started when a button click occurs. This requires a very simple if statement to make sure the phone has location services available.
A working test right now looks like this
- (void)testStartUpdatingLocationInvokedWhenLocationServicesAreEnabled
{
[[[self.locationManager stub] andReturnValue:[NSNumber numberWithBool:true]] locationServicesEnabled];
[[self.locationManager expect] startUpdatingLocation];
[self.sut buttonClickToFindLocation:nil];
[self.locationManager verify];
}
The now tested implementation looks like this
- (IBAction)buttonClickToFindLocation:(id)sender
{
if ([self.locationManager locationServicesEnabled])
{
[self.locationManager startUpdatingLocation];
}
}
All good except the method was deprecated in iOS 4.0. So now I need to use the Class Method [CLLocationManager locationServicesEnabled] instead.
The problem is I can't seem to find if ocmock supports this functionality and if it doesn't how should I get around this issue for now.
hmmm, you could use methodExchange. Just make sure you exchange the method back to original after your done with it. It seems hacky, but I haven't found a better solution. I have done something similar for stubbing [NSDate date]
#implementation
static BOOL locationManagerExpectedResult;
- (void)testStartUpdatingLocationInvokedWhenLocationServicesAreEnabled
{
locationManagerExpectedResult = YES;
method_exchangeImplementations(
class_getClassMethod([CLLocationManager class], #selector(locationServicesEnabled)) ,
class_getClassMethod([self class], #selector(locationServicesEnabledMock))
);
[self.sut buttonClickToFindLocation:nil];
}
+ (BOOL)locationServicesEnabledMock
{
return locationManagerExpectedResult;
}
#end
EDIT: I thought you were verifying, but it seems like you are stubbing. Updated code
The simplest approach is to override locationServicesEnabled in a category in your unit test class:
static BOOL locationServicesEnabled = NO;
#implementation CLLocationManager (UnitTests)
+(BOOL)locationServicesEnabled {
return locationServicesEnabled;
}
#end
...
-(void)tearDown {
// reset to default after each test
locationServicesEnabled = NO;
[super tearDown];
}
It will override the superclass method only at test time, and you can set the static global to an appropriate value in each test.
Alternatively, you could wrap the check in your own instance method, and use a partial mock.
In the class under test:
-(BOOL)locationServicesEnabled {
return [CLLocationManager locationServicesEnabled];
}
In your test:
-(void)testSomeLocationThing {
MyController *controller = [[MyController alloc] init];
id mockController = [OCMockObject partialMockForObject:controller];
BOOL trackingLocation = YES;
[[[mockController stub] andReturnValue:OCMOCK_VALUE(trackingLocation)] locationServicesEnabled];
// test your controller ...
}
I don't think it does. The only approach I can think of would be to use a partial mock and then use runtime calls to swizzle in the implementation you need.
Doable, but complex.
A more pattern orientated solution might be to extract the checking for location services out to sit behind a protocol. Then you can simply use a mock for the protocol's implementation during testing to return YES or NO as your require. As the actual implementation would do nothing but return [CLLocationManager locationServicesEnabled] you could get away with not testing it.
This is supported by OCMock:
[[[[mockLocationManagerClass stub] classMethod] andReturnValue:OCMOCK_VALUE(YES)] locationServicesEnabled];

Searching for the Right Pattern (iPhone/Objective C)

EDIT: It was suggested to me that I implement the strategy pattern (http://en.wikipedia.org/wiki/Strategy_pattern), which I think I would do as several objects that implement a delegate protocol in Objective-C. This accomplishes the encapsulation I want while still allowing me to have a generic view controller in memory.
I have a class called DetailViewController that displays information about various types of data - waypoints, trails, maps, photos.
Right now, this class is 1400 lines long and it has some messy switch statements. For example:
- (void) changeMiniView:(id)sender {
if (self.track) {
[self changeTrackMiniView:[sender selectedSegmentIndex]];
} else if (self.waypoint) {
[self changeWaypointMiniView:[sender selectedSegmentIndex]];
} else if (self.photo) {
[self changePhotoMiniView:[sender selectedSegmentIndex]];
} else if (self.map) {
[self changeMapMiniView:[sender selectedSegmentIndex]];
}
}
This would be a lot neater if I made subclasses of DetailViewController, but my conundrum is I would like to keep the viewController in memory and just change certain elements, so I can have crisp transitions, particularly on 3G phones.
I feel like if I want my code to be neat, I have to take a performance hit.
Have the current view in a field in your object (rather than one field for every type of miniview you have), and implement changeMiniView for each of them.
Then your method would look like:
- (void) changeMiniView: (id)sender {
[self.currentMiniView changeMiniView: [sender selectedSegmentIndex]];
}
How about using selector?
- (void)viewDidLoad {
if (self.track) {
sel = #selector(changeTrackMiniView:);
} else if (self.waypoint) {
sel = #selector(changeWaypointMiniView:);
} else if (self.photo) {
sel = #selector(changePhotoMiniView:);
} else if (self.map) {
sel = #selector(changeMapMiniView:);
}
}
- (void)changeTrackMiniView:(id)sender {
....
}
- (void)changeMiniView:(id)sender {
[self performSelector:sel withObject:sender];
}