working on iPhone osm maps app (Route me).well initialising and downloading online maps was easy but real problem lies in saving the tiles through the code while u are online and reuse them while you are offline.i checked blogs regarding the same but everyone is saving the images externally and importing it in project and then showing them,which is not my requirement.please help me to save the tile image route me picks from online source
here is how i am using online route me maps
-(void) viewDidLoad
{
[RMMapView class];
mapView.contents.tileSource = [[RMOpenStreetMapSource alloc] init];
currentMarker = [[RMMarker alloc]initWithUIImage:[UIImage imageNamed:#"radarLocatorLite.png"] anchorPoint:CGPointMake(0.5, 0.5)];
markerManager = [mapView markerManager];
locationManager.delegate=self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest ;
locationManager.distanceFilter =0;
[mapView.contents setZoom:17.0f];
[markerManager addMarker:currentMarker AtLatLong:currentLocation.coordinate];
[self initCompassView];
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
currentLocation =newLocation;
[mapView moveToLatLong:newLocation.coordinate];
[markerManager moveMarker:currentMarker AtLatLon: newLocation.coordinate];
[currentRoutePath addLineToLatLong:newLocation.coordinate];
[[mapView.contents overlay] addSublayer:currentRoutePath];
// NSLog(#"i reached inside location update%f",currentRoutePath.lineWidth);
}
I have an iOS app that uses static map images saved in a sqlite database. There are some references as to how to do that, but it took me lots of trial-and-error effort to make sense of them and make it work.
It seems that you should be able to have a sqlite database and save the downloaded images into it as your app downloads them. Then you'd have to know what tile source to use: the sqlite database if the app is offline, the OSM site when online.
The structure of the database is:
tilekey text // a hash that route-me uses to locate the correct tile
zoom integer
row integer
col integer
zoom integer
image blob this stores the actual image of the map
I use a Python script to populate the database, as I want the app to always use the static map images from the database, never to use a real-time download from OSM.
Please let me know if you'd like more information, but if you search for using static maps with route-me, you should find how this is done. Good luck!
finally resolved problem by just a minor change in few places
Step 1: Go to this site "http://shiki.me/blog/offline-maps-in-ios-using-openstreetmap-and-route-me/" and follow instructions to download tile images from online and create of zip of the folder.remember the tile images folder are in order ->zoom level folder->x coord foler->y coord image respectively.
step 2: unzip the zip file in ur app at some folder
step 3:go to the file "RMAbstractMercatorWebSource.m" in map view project
and replace the following folders
-(NSString*) tileFile: (RMTile) tile
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Tiles"];
NSString *absPath=[NSString stringWithFormat:#"%#/%d/%d/%d.png", path,tile.zoom, tile.x, tile.y];
NSLog(#"file path >>>.............%#",absPath);
return absPath;
}//I unzipped the zip file at tiles folder
-(NSString*) tilePath
{
return nil;
}
-(RMTileImage *)tileImage:(RMTile)tile
{
RMTileImage *image;
tile = [tileProjection normaliseTile:tile];
NSString *file = [self tileFile:tile];
if(file && [[NSFileManager defaultManager] fileExistsAtPath:file])
{
image = [RMTileImage imageForTile:tile fromFile:file];
}
else if(networkOperations)
{
image = [RMTileImage imageForTile:tile withURL:[self tileURL:tile]];
}
else
{
image = [RMTileImage dummyTile:tile];
}
return image;
}
this in turns first look in cache then check the specified directory and finally go for online osm tile images
Related
So I have a Universal link that leads to a view controller in my app. On that particular view controller I display a couple of images as well as a web view. The webView displays a url chosen by the user. How do I save this custom url so that it is displayed every time someone clicks the link? I think the code to this is under:
#synthesize deepLinkingCompletionDelegate;
-(void)configureControlWithData:(NSDictionary *)data {
NSString *string = data[#"favoriteArticle"];
Alex from Branch.io here:
To accomplish this, you need to do two things.
Step 1
Store the URL of the article you want to load as one of the Branch link custom parameters. Full instructions on how to do that here, but essentially:
BranchUniversalObject *branchUniversalObject = [[BranchUniversalObject alloc] initWithCanonicalIdentifier:#"item/12345"];
branchUniversalObject.title = #"My Content Title";
branchUniversalObject.contentDescription = #"My Content Description";
branchUniversalObject.imageUrl = #"https://example.com/mycontent-12345.png";
[branchUniversalObject addMetadataKey:#"favorite_article" value:#"https://example.com/path/to/article"]; // this is used to route inside the app
[branchUniversalObject addMetadataKey:#"property2" value:#"red"];
BranchLinkProperties *linkProperties = [[BranchLinkProperties alloc] init];
linkProperties.feature = #"sharing";
linkProperties.channel = #"facebook";
[linkProperties addControlParam:#"$desktop_url" withValue:#"https://example.com/path/to/article"]; // this is used for desktop visitors
[linkProperties addControlParam:#"$ios_url" withValue:#"https://example.com/path/to/article"]; // this is used for iOS mobile visitors without the app installed
Step 2
Then when the app opens after a link click, watch for that data key. Again, full instructions, but basically:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// initialize the session, setup a deep link handler
[[Branch getInstance] initSessionWithLaunchOptions:launchOptions
andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {
// start setting up the view controller hierarchy
UINavigationController *navC = (UINavigationController *)self.window.rootViewController;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *nextVC;
// If the key 'favoriteArticle' is present in the deep link dictionary
// then load the picture screen with the appropriate picture
NSString * favoriteArticle = [params objectForKey:#"favorite_article"];
if (favoriteArticle) {
nextVC = [storyboard instantiateViewControllerWithIdentifier:#"ArticleVC"];
[nextVC setArticleUrl: favoriteArticle];
} else {
nextVC = [storyboard instantiateViewControllerWithIdentifier:#"MainVC"];
}
// navigate!
[navC setViewControllers:#[nextVC] animated:YES];
}];
return YES;
}
After this, in your ArticleVC, retrieve the favoriteArticle value and use it for your webview.
Step 2 (Alternate)
The configureControlWithData method you mentioned is used in the automatic deep link routing implementation. You may be able to adapt this to work with a webview, but I haven't personally tried that. It would look something like this:
#synthesize deepLinkingCompletionDelegate;
- (void)configureControlWithData:(NSDictionary *)data {
NSString *favoriteArticle = data[#"favorite_article"];
// load the webview with the URL stored inside favoriteArticle
}
I am using GPUImageMovie with initWithPlayerItem and its not starting the movie file on startProcessing. It was working fine with initWithUrl but I need playback controls for the player as told in this thread. I am using the following code
-(void)loadVideo
{
_playerItem = [[AVPlayerItem alloc]initWithURL:movieURL];
_player = [AVPlayer playerWithPlayerItem:_playerItem];
movieFile = [[GPUImageMovie alloc] initWithPlayerItem:_playerItem];
movieFile.runBenchmark = YES;
movieFile.playAtActualSpeed = YES;
filter = [[TSFilter alloc] init];
_movieView = [[GPUImageView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:_movieView];
[self.view sendSubviewToBack:_movieView];
[movieFile addTarget:filter];
[filter addTarget:_movieView];
_player.rate = 1.0;
[movieFile startProcessing];
[_player play];
}
And finally after spent a lot of time I found the solution to this silly problem. I came to that solution when I tried bundled file instead of a file in a document directory. I think it is the bug in AVPlayerItem:initWithUrl method that is not working with the NSUrl value from document directory. Let me explain it in detail
When I get the Url of the file from document directory its value is
/var/mobile/Applications/7B3229B0-D18E-405D-BBA0-E9D57F2842C4/Documents/SkyFall_clip.m4v
but if I bundled this file and get the url from [NSBundle mainBundle] then its value is
file:///var/mobile/Applications/7B3229B0-D18E-405D-BBA0-E9D57F2842C4/Documents/SkyFall_clip.m4v
So I found that "file://" keyword is missing in the url for the document directory file. So i just append "file://" in the beginning of the url and it starts working. Although this should not be the case because both are the valid NSUrl and working for other classes like UIImage.
Note: Implement the string append operation is such a way that it append only if it is missing.
I am currently trying to save video files to iCloud. I am using Core Data to save filename strings (filename.MOV) for each video, to then retrieve them from the ubiquity container. It all works locally (files save, and can be accessed from their URLs), but I am struggling to obtain the videos over iCloud. The Core Data syncs, so I have access to the file names, but when I try to obtain the video from the URL, I am unable to.
This is how I save the video after obtaining its url (videoURL below) from UIImagePicker, and creating a unique string from the current date:
NSString *videoFileName = [stringFromDate stringByAppendingPathExtension:#"MOV"];
NSURL *ubiquityContainer = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
NSURL *saveToURL = [ubiquityContainer URLByAppendingPathComponent:videoFileName];
BOOL ok;
ok = [[NSFileManager defaultManager] setUbiquitous:YES itemAtURL:videoURL destinationURL:saveToURL error:nil];
if (!ok) NSLog(#"error saving");
I then have a Core Data table view to list all of the videos. Here I observe changes in the Core Data to sync with iCloud and reload (this all still works fine):
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reloadFetchedResults:)
name:#"SomethingChanged"
object:[[UIApplication sharedApplication] delegate]];
}
- (void)reloadFetchedResults:(NSNotification*)note {
[self performFetch];
}
At this point, I want the ubiquity container to update, so that when I choose a video, and segue to a view controller to watch it, the video file can be found. (self.video is my Core Data video entity) (asset is is the video asset, which I can play back)
NSURL *ubiquityContainer = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
ubiquityContainer = [ubiquityContainer URLByAppendingPathComponent:self.video.url];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:ubiquityContainer options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]];
AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
This is where I run in to trouble. On the device where I took the video it works, but on another device, no file is found (objectAtIndex:0 is beyond bounds).
This is the metadata query I call at view did load:
NSMetadataQuery * query = [[NSMetadataQuery alloc] init];
NSString * filePattern = [NSString stringWithFormat:#"%#", self.video.url];
[query setPredicate:[NSPredicate predicateWithFormat:#"%K LIKE %#",
NSMetadataItemFSNameKey, filePattern]];
[query startQuery];
My metadata query may be at fault, or there may be more issues. Any help would be greatly appreciated!
I assume you are on iOS, which means on your second device the media file hasn't been downloaded (iOS doesn't download iCloud files until you actually access them, OS X downloads everything - see the docs).
To ensure the file is on the device use startDownloadingUbiquitousItemAtURL:error: or coordinateReadingItemAtURL:options:error:byAccessor: if you want to know when it's done (in the Accessor block). You will need to call the later anyway to do your coordinated read, so the first method has limited usefulness.
I have UIImagePicker to select the image. After selecting the image I am editing it and now I want to save that image.
Can anyone please tell me how can I save the image to Photo Album?
take a look at this tutorial
http://iosdevelopertips.com/camera/camera-application-to-take-pictures-and-save-images-to-photo-album.html
here is my code to get image if the image is edited then edited image will be taken into account.
if not edited then original image will be taken
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
UIImage *image;
if (picker.editing == YES) {
image = [info objectForKey:#"UIImagePickerControllerEditedImage"];
}
else {
image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
// [picker release];
// [self dismissModalViewControllerAnimated:YES];
}
You can use this function
UIImageWriteToSavedPhotosAlbum(UIImage *yourImage, id completionTarget, SEL completionSelector, void *contextInfo);
See the answer to this question...And about completionTarget and completionSelector, from documentation...
The use of the completionTarget, completionSelector, and contextInfo
parameters is optional and necessary only if you want to be notified
asynchronously when the function finishes writing the image to the
user’s Camera Roll or Saved Photos album. If you do not want to be
notified, pass nil for these parameters.
My iPhone application downloads image files from a server, stores it into NSTemporaryDirectory() and then loads the image in the UI asynchronously. Code flow is like this:
Show view with loading activity indicator and run a image downloader in the background.
Once the image is downloaded, it is written to a file.
A timer in the loading view keep checking for the availability of file in the temp directory and once available, loads the image from file and adds the image to the UI.
Before adding the image, it is scaled to required size.
Problem is, I use UIGraphicsGetImageFromCurrentImageContext to scale the image. Looks like the memory used by the image context is not getting cleaned. The app memory just keeps increasing as more files get downloaded.
Some code below:
Code to scale the image:
-(UIImage*)scaleToSize:(CGSize)size image:(UIImage *)imageref
{
UIGraphicsBeginImageContext(size);
[imageref drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
Loading image from temp directory:
-(void)loadImageFromFile: (NSString *) path
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
UIImage * imm = [[[UIImage alloc] initWithContentsOfFile:path] autorelease];
[self performSelectorOnMainThread:#selector(insertImage:) withObject:imm waitUntilDone:YES];
[pool release];
}
Adding image to view (subset of code):
self.imageContainer = [[UIImageView alloc] initWithFrame:CGRectMake(0,80,320,250)];
[self addSubview:self.imageContainer];
self.imageContainer.image = [self scaleToSize:CGSizeMake(320.0f, 250.0f) image:imm];
[imageContainer release];
What am I missing here ?
One way of avoiding the leak from UIGraphicsGetImageFromCurrentImageContext is to not call it at all by resizing the container instead of resizing image directly:
self.imageContainer.contentMode = UIViewContentModeScaleAspectFit;
self.imageContainer.frame = CGRectMake(self.imageContainer.frame.origin.x, self.imageContainer.frame.origin.y, 320.0f, 250.0f);