Mk Mapview keeps resetting on users location? - mkmapview

I currently have a map displaying 10 or so co ordinates.The map gets the users location and centers on it as soon as it is opened. When panning the page or zooming different levels it eventually resets and centers in on the first position of the user.I have tried "stopupdating location" and Animated as "NO".I can not get it to stay in positon when the user scrolls the map.
- (void)viewDidLoad {
[super viewDidLoad];
self.petrolMap.delegate = self;
self.location = [[CLLocationManager alloc] init];
[location setDelegate:self];
[location setDistanceFilter:0]; // Do not apply a distance filter to the map
[location setDesiredAccuracy:kCLLocationAccuracyBest]; // Use the best accuracy possible when displaying the map
petrolMap.delegate=self; // Display on "Petrol Map" , the mapview for the application}
-(void) mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{MKCoordinateRegion mapRegion;
mapRegion.center = petrolMap.userLocation.coordinate;
mapRegion.span.latitudeDelta=0.02;
mapRegion.span.longitudeDelta=0.02;
[petrolMap setRegion:mapRegion animated:NO];}

Your 'location' is a location manager, when it works out where you are it'll send its delegate
locationManager:didUpdateToLocation:fromLocation:
which you don't seem to have, so all those settings you're doing to 'location' are wasted (as far as the code you've given us, it may be useful elsewhere) and telling it to stop tracking the user is of no use.
"(void) mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{MKCoordinateRegion mapRegion;" is what petrolMap is sending to its delegate. Somewhere you must have set petrolMap to track the user, it can be done in the .xib.
Anyway, to stop petrolMap sending messages make sure you run
[petrolMap setUserTrackingMode:MKUserTrackingModeNone animated:NO];
Some extra notes:
Within didUpdateUserLocation you don't need to refer to petrolMap directly because the mapView parameter is set to which ever MKMapView sent the message.
Also within didUpdateUserLocation you are using petrolMap's userLocation instead of the parameter userLocation, and even building your region. The entire code for that function could be one line
[mapView setRegion:mapRegion animated:NO];
'Animated' controls how the change in region is done. Yes means it will slide between locations, No means it will snap from one to the other instantly, either way the map will move to the new region.
Your viewDidLoad method could be cut to two lines like follows
[super viewDidLoad];
self.petrolMap.delegate = self;
Addendum:
locationManager:didUpdateToLocation:fromLocation
is deprecated in iOS6.

Unfortunately this is a few years to late for you James - but hopefully it'll help others who are stuck in this situation (like myself).
I ended up adding...
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow];
Into my -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
You should normally add "animated:YES" at the end, but this again would ping it back to my current location, even if I changed the commander to "NO" - so tried deleting it and it worked!!!
Just for reference my whole code became:
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
if(userLocationShown) return;
MKCoordinateRegion region;
MapView.showsUserLocation = YES;
region.center.latitude = MapView.userLocation.coordinate.latitude;
region.center.longitude = MapView.userLocation.coordinate.longitude;
region.span = MKCoordinateSpanMake(0.02,0.02);
[MapView setRegion:region animated:YES];
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow];
[locationManager startUpdatingLocation];
[locationManager stopUpdatingLocation];
userLocationShown = YES;
and I added...
- (void)viewDidLoad {
[super viewDidLoad];
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
MapView.delegate = self;

Related

GPUImage terminates due to [AVAssetWriter startWriting] Cannot call method when status is 3'

I am having an issue running GPUImage. I have modified SimpleVideoFileFilter program(replaced the filter with a chromakeyfilter) and am using my own video. My program is terminating due to the following error:
[AVAssetWriter startWriting] Cannot call method when status is 3'
I have gone through the forums but not sure why the moviewriter is closing and then someone is writing to it.
I am using iPhone4 running iOS 7.0
Any clues are greatly appreciated. Thanks much!
Check whether your destination file exists already. If it does, remove it.
I was trying to add the file to a directory which did not exist. Example : /Videos/Video.mov , leaving it just /Video.mov worked.
Ok, I have a few ideas for you.
When you say "it just shows a frame and never plays the video" we have a good indication that your entire processing pipeline from start to finish is functional exactly once, then stops working.
That tells us that you are stringing things together correctly, but some of the components don't exist longer than a single frame buffer cycle, and subsequently the whole process stops.
it looks like filter and movieWriter are scoped to the class (I'm assuming they're not properties from the lack of an underscore, _filter and _movieWriter). So they will live on after this method has finished (correct me if I'm wrong...)
I think where you are encountering trouble is your (GPUImageView*)displayView
This should probably be declared as a class property (although it could work as just a variable) and then instantiated through the nib or the viewDidLoad method of the view controller.
As you have it now, this line: GPUImageView* filterView = (GPUImageView*)displayView; is making an assignment for filterView which is not used (and therefore unnecessary). It's not clear if displayView really is an instance of GPUImageView or if it will still be in existence when the current method finishes. (in fact you say it "is a UIView that I have programmatically created")
displayView will have to be a subclass of GPUImageView for this whole thing to work, and it will have to be scoped to the class, and not the method.
Declare it like this:
#property (strong, nonatomic)GPUImageView* displayView;
and then instantiate it and add it to your view hierarchy from within viewDidLoad
movieFile1 = [[GPUImageMovie alloc] initWithURL:movieFileURL1];
movieFile2 = [[GPUImageMovie alloc] initWithURL:movieFileURL2];
movieFile2.runBenchmark = YES;
movieFile2.playAtActualSpeed = NO;
filter = [[GPUImageChromaKeyBlendFilter alloc] init];
[(GPUImageChromaKeyBlendFilter *)filter setColorToReplaceRed:0.0 green:1.0 blue:0.0];
[(GPUImageChromaKeyBlendFilter *)filter setThresholdSensitivity:0.4];
GPUImageView *filterView = (GPUImageView*)displayView;
[filter addTarget:displayView];
[movieFile1 addTarget:filter];
[movieFile2 addTarget:filter];
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Movie.m4v"];
unlink([pathToMovie UTF8String]);
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(1920.0, 1280.0)];
[filter addTarget:movieWriter];
movieWriter.shouldPassthroughAudio = YES;
movieFile1.audioEncodingTarget = movieWriter;
[movieFile1 enableSynchronizedEncodingUsingMovieWriter:movieWriter];
[movieWriter startRecording];
[movieFile1 startProcessing];
[movieFile2 startProcessing];
[movieWriter setCompletionBlock:^{
[filter removeTarget:movieWriter];
[movieWriter finishRecording];
}];
if (outputPath) {
finalURL = [[stongObj tempFileURL] copy];
DebugLog(#"Start Filter Processing :%#",finalURL);
DebugLog(#"movieUrl :%#",movieUrl);
// [CSUtils removeChuckFilePaths:#[outputPath]];
//Create Image Movie Object
_movieFile = [[GPUImageMovie alloc] initWithURL:outputPath];
//_movieFile = [[GPUImageMovie alloc] initWithURL:[[NSBundle mainBundle] URLForResource:#"videoviewdemo" withExtension:#"mp4"]];
_movieFile.runBenchmark = NO;
_movieFile.playAtActualSpeed = YES;
_movieFile.delegate = self;
//Movie Writer Object
_movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:finalURL size:CGSizeMake([UIScreen mainScreen].bounds.size.height,[UIScreen mainScreen].bounds.size.height)];
//_movieWriter.delegate = self;
//Create Selecetive GPU Image Filter
[stongObj setGpuOutputFilter:selectedVideoFilterType];
//Create Group Filter
groupFilter = [[GPUImageFilterGroup alloc] init];
[groupFilter addTarget:imageOutputFilter];
// Only Single Filter is implemented.
//Apply Initial and Terminal Filter
[(GPUImageFilterGroup *)groupFilter setInitialFilters:[NSArray arrayWithObject:imageOutputFilter]];
[(GPUImageFilterGroup *)groupFilter setTerminalFilter:imageOutputFilter];
//_movieWriter -> groupFilter ->_movieFile
[_movieFile addTarget:groupFilter];
[groupFilter addTarget:_movieWriter];
_movieWriter.shouldPassthroughAudio = YES;
_movieFile.audioEncodingTarget = _movieWriter;
[_movieFile enableSynchronizedEncodingUsingMovieWriter:_movieWriter];
//Start Recording
[_movieWriter startRecording];
//Start Processing
[_movieFile startProcessing];
__weak typeof(self) weekSelf=self;
[_movieWriter setCompletionBlock:^{
__strong typeof(self) stongSelf=weekSelf;
DebugLog(#"Movie Write Completed");
//Finish Recording.
[stongSelf.movieWriter finishRecording];
//Release all object
// [self releaseAllObject];
//remove movieUrl,audioUrl,outputPath
[CSUtils removeChuckFiles:#[movieUrl,audioUrl,outputPath]];
}];
[_movieFile startProcessing]; app get crash in iOS 8 on this line but working fine on iOS 7
#Seasia Creative ,I have no enough reputation to add a comment by that list,I create a new list to answer U.
I check the output URL,console log "/var~~~~/tmpmerge.mp4",so i realize that ,i miss a "/" --->"/var~~~~/tmp/merge.mp4".
If the url is no correct, project runs into the same error.
hope to help some.

Using selected NSManagedObject across different controllers

I have an entity called Practice and I use a View Controller called SelectorViewController to select one of the practices, selectedPractice. I then return selectedPractice to a view Controller called RegularViewController where I display some of the selectedPractice attributes. All of this works fine. However the app has a number of other View Controllers which can be reached by modal segues from instances of RegularViewController. As a result, if I leave and then come back to RegularViewController, selectedPractice is reset as null. I would also like to save selectedPractice so that it is available at app initialisation if it has previously been set in SelectorViewController. How do I achieve this by making selectedPractice persistent across the app, and available at runtime?
Regards
Thanks to the post above, which was great, I managed to sort it. Here is my code, which may be very clumsy, but it works.
Firstly, as I loaded the fetchedObjects into a PickerView in SelectorView Controller, I set an attribute "isSelectedPractice" to "NO" with the following code:
for (Practice *fetchedPractice in [self.fetchedResultsController fetchedObjects]) {
[fetchedPractice setValue:#"NO" forKey:#"isSelectedPractice"];
[self.managedObjectContext save:nil];
I then identified for the selected Practice:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
Practice *practice = [[self.fetchedResultsController fetchedObjects] objectAtIndex:row];
self.selectedPractice = practice;
NSLog(#"The '%#' practice was selected using the picker", self.selectedPractice.name);
}
as the view Segue'd back to RegularViewController I set the isSelectedPractice attribute for selectedPractice to YES. I kept it this late as I didn't want more than one selection in the PickerView to result in multiple objects with isSelectedPractice YES.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"SavedPractice Segue"])
{
[self.selectedPractice setValue:#"YES" forKey:#"isSelectedPractice"];
[self.managedObjectContext save:nil];
NSLog(#"Setting SelectedPractice as '%#' in RegularViewController with isSelectedPractice as '%#'",self.selectedPractice.name,self.selectedPractice.isSelectedPractice );
RegularViewController *rvc= segue.destinationViewController;
rvc.delegate = self;
rvc.selectedPractice = self.selectedPractice;
}
else {
NSLog(#"Unidentified Segue Attempted!");
}
}
I then set the following Predicate in the setupFetchedResultsController method of RegularViewController:
request.predicate = [NSPredicate predicateWithFormat:#"isSelectedPractice = %#", #"YES"];
Many thanks for the help
Without seeing your actual project, one way I know will work but might be a little too round a bout would be to add an attribute "isSelectedPractice" to your entity. You could make it a BOOL, but I've had mixed results with BOOL's in Core Data, I prefer to just leave it as a NSString and set it to "yes" or "no". Then when you pull it down, modify it or add it to core Data as a entity with isSelectedPractice set to "yes". Then in your other controllers, do a
if (self.managedObjectContext == nil) {
self.managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
then do a fetch request to get entities with a predicate which is looking for isSelectedPractice equaling "yes". If you need actual code samples on how to do this let me know and I'll edit them in.

TableView not reloading after modalview dismissed

I have a page that checks if there is a list of employees on the bundle, and if there is it displays them in a table view. But if there is no list on the bundle it throws up a modal view controller. That then requires someone to login, the login is authenticated and then data is downloaded.
The ModalView is setup to be a delegate of the first page. I can call the delegate method just fine and pass the list, but when the ModalView is dismissed the table does not reload the tableview with the data. If i run the project again it loads the list up in the table view instantly.
Here is the method on the ViewDidLoad of the first page
[self checkLastLoginDate];
[self loadDataIntoArray];
if (currentData && dataLoadedIntoArray) {
NSLog(#"sweet the data is current");
[self createIndexedArray];
}
else{
NSLog(#"Data not loaded and not current");
//push login view
///if ipad do this
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
//the above code was working fine. I am just testing pushing a dynamic xib
LoginViewControlleriPad *loginControlleriPad = [[LoginViewControlleriPad alloc] initWithNibName:#"LoginViewControlleripad" bundle:nil];
loginControlleriPad.modalPresentationStyle = UIModalPresentationFormSheet;
loginControlleriPad.delegate = self;
[self presentModalViewController:loginControlleriPad animated:YES];
[self createIndexedArray];
[loginControlleriPad dismissModalViewControllerAnimated:NO];
[self.tableView reloadData];
}
The first two methods check to make sure the data exists on the bundle and that the last login date is within 15 days.
if it is then I create an IndexedArray and it displays nicely.
If the data is not on the bundle or the date is to old I check the device and use a modal view. The delegates are set and the ModalView Appears.
In the ModalView I use a syncronus and asyncronus request to hit a server for the required information. Then I create the list and pass it back to the first page.
Once the connection is made and we do a little work on the list we save it to the bundle.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:kEMPLOYEE_PLIST];
/////write to file/////
[cleanResults writeToFile:path atomically:YES];
employeeList = [[NSMutableArray alloc ]initWithContentsOfFile:path];
if (employeeList != nil)
{
[delegate passUserInfo:employeeList];
//cant get login view to dismiss
//[self dismissModalViewControllerAnimated:YES];
}
Once I get the list I right it to file and then read it back in. If there is info in the list I call the delegate method.
UPDATE
Here is the delgate method
- (void)passUserInfo: (NSMutableArray *)employeeDataArray
{
employeeData = [[NSMutableArray alloc] initWithArray:employeeDataArray];
[self.tableView reloadData];
/////FIX////////
[createIndexedArray];
}
Once that is called nothing happens. I tried dismissing the modal view, which works, but then the first page does not refresh and my app gets lost in the oblivion. I am just confused at were it is going and how i can refresh the tableview on the first page.
Is there a step I are missing? I have tried tracking it and lose it after this step.
I actually figured out that my code was setup right, i just needed to call a method that sorted the array into an alphabetic array. Once i called that method from the delegate method it worked like a snake charm.
UPDATE
I had a method that created an indexed array. When i called that inside the delegate method it reloaded the page and inserted the new into the table view. I am pretty sure it was reloading the whole time, i was just not calling the method that was populating the array that was being being displayed in the tableview.

Presenting UITabBarController Modally - Autorotate Problem

I'm attempting to present a UITabBarController modally using the following code:
// Declare all view controllers.
TabOne *tabOne = [[TabOne alloc] initWithNibName:#"TabOne" bundle:nil];
TabTwo *tabTwo = [[TabTwo alloc] init];
TabThree *tabThree = [[TabThree alloc] init];
// Set each view controller's delegate to self.
tabOne.delegate = self;
tabTwo.delegate = self;
tabThree.delegate = self;
// Set a title for each view controller.
tabOne.title = #"One";
tabTwo.title = #"Two";
tabThree.title = #"Three";
// Create a tab bar controller.
UITabBarController *tabBarController = [[UITabBarController alloc] init];
[tabBarController setViewControllers:[NSArray arrayWithObjects:tabOne,tabTwo,tabThree, nil]];
// Present the tab bar controller modally.
[self presentModalViewController:tabBarController animated:NO];
// Memory management.
[tabOne release];
[tabTwo release];
[tabThree release];
This all works as expected except that I get the following warnings in the console:
Using two-stage rotation animation. To use the smoother single-stage animation, this application must remove two-stage method implementations.
Using two-stage rotation animation is not supported when rotating more than one view controller or view controllers not the window delegate.
I've done some research on this and have checked that shouldAutorotateToInterfaceOrientation is implemented as follows:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
As far as I can tell, the problem is that the tab bar controller is not the root view controller, but I'm presenting this modal view some way into a deep view hierarchy. It's called from another modal view, which itself is called from a tab bar set in the application delegate.
I know this is a bit of an old chestnut, but it's got me stumped. Any thoughts?
Thanks in advance.
I've had a similar problem.
UITabBarController has some odd behavior with its orientation handling. When setting its orientation, it calls recursively into self.selectedViewController to decide whether to use one-stage or two-stage animation. That seems sensible, but the trouble is self.selectedViewController is initially nil (in particular, if you're displaying the UITabBarController modally for the first time), and that can confuse the controller. Depending on the iOS version, a nil selectedViewController will lead the UITabBarController to believe that one-stage animation is unsupported.
Try this: when you first load / initialize your UITabBarController, add the line
tabBarController.selectedIndex = 0;
I was getting this warning (including serious visual problems: the view controller was switching orientation but the status bar was not), and setting the index this way fixed the problem. The UITabBarController successfully called into its selected view controller, and detected the one-stage animation.

How to "preload" view controller without actually pushing it?

Background:
I've got a free app that is ad-supported. The basic idea is that when the app is launched, ad content (HTML) is downloaded from the server in the background, and only if the download was successful, then the content is being shown.
Previous solution:
I have implemented this successfully in a universal app. Originally, I loaded a NSData variable with an URL, and if it was successful, then I presented a modal view which contained an UIWebView (relevant code is in another question). The problem is that the external assets (images) don't get loaded in the original NSData request, so in a stroke of genius I thought of another way:
New solution:
The new way, and this is what I want help with, is that I'm instantiating the modal view controller (without displaying it yet), and having the web view begin loading the URL directly. When the webViewDidFinishLoad method is called, I fire a notification back to the parent which then performs the presentModalViewController.
Here are the methods which instantiate the view controller and present it modally:
- (void)launchAd
{
if ([ServerCheck serverReachable:#"openx.freewave-wifi.com" hideAlert:YES])
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(presentAdModal) name:#"AdLoaded" object:nil];
AdViewController *adView = [[AdViewController alloc] initWithNibName:nil bundle:nil];
[[adView view] awakeFromNib]; //THIS LINE IS WHAT THIS QUESTION IS ABOUT
navController = [[UINavigationController alloc] initWithRootViewController:adView];
[adView release], adView = nil;
[navController setModalPresentationStyle:UIModalPresentationFormSheet];
[navController setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[[navController navigationBar] setTintColor:[UIColor colorWithRed:0.94 green:0.00 blue:0.32 alpha:1.00]];
}
else
LogError(#"Not presenting ad.");
}
- (void)presentAdModal
{
LogInfo(#"Presenting advertisement modal.");
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"AdLoaded" object:nil];
[tabBarController presentModalViewController:navController animated:YES];
[navController release];
}
And in the AdView controller:
- (void)webViewDidFinishLoad:(UIWebView *)theWebView
{
LogInfo(#"Ad content did load; we can show it.");
[timeout invalidate], timeout = nil;
[self setTitle:#"From Our Sponsor"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"AdLoaded" object:nil];
}
Now what's above does work. However, it took a long time for me to figure out how to cause the view controller delegate methods in the AdView controller to fire before calling presentModalViewController. I did this by adding [[adView view] awakeFromNib];, but I know this isn't the right way to make this happen.
So, everything above does work beautifully, effectively having the view controller and its UIWebView "preload" before displaying it. I just want to know what I should be doing instead of [[adView view] awakeFromNib]; -- I want to do it the right way.
Or is this right? I guess some folks would say "If it works, then it's right", but I know this isn't true.

Resources