I am working on play video on GMSMarker pin and below is my code. The display and hide/show pin view, everything work fine. Except video not play. I am using story board with pinview.
#interface MapViewController () <GMSMapViewDelegate>
#property (strong, nonatomic) IBOutlet GMSMapView *mapView;
#property (strong, nonatomic) IBOutlet UIView *pinView;
#property (strong, nonatomic) GMSMarker *london;
#property (strong, nonatomic) AVPlayer *player;
#property (strong, nonatomic) AVPlayerLayer *playerLayer;
#end
#implementation MapViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:51.5 longitude:-0.127 zoom:18];
self.mapView.camera = camera;
self.mapView.delegate = self;
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(51.5, -0.127);
_london = [GMSMarker markerWithPosition:position];
_london.title = #"London";
_london.tracksViewChanges = YES;
_london.map = self.mapView;
[self setUpVideoPlayer];
}
- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker {
[self.player play];
return self.pinView;
}
-(void)setUpVideoPlayer{
NSString *videoFilePath = [[NSBundle mainBundle] pathForResource:#"SampleVideo" ofType:#"mp4"];
AVAsset *avAsset = [AVAsset assetWithURL:[NSURL fileURLWithPath:videoFilePath]];
AVPlayerItem *avPlayerItem =[[AVPlayerItem alloc]initWithAsset:avAsset];
self.player = [[AVPlayer alloc]initWithPlayerItem:avPlayerItem];
self.playerLayer =[AVPlayerLayer playerLayerWithPlayer:self.player];
[self.playerLayer setFrame:self.pinView.frame];
[self.pinView.layer addSublayer:self.playerLayer];
[self.player seekToTime:kCMTimeZero];
}
Please help me to fix the issue. Why the video is not playing.
Thanks in advance.
Normally, info window will not regenerate after showing it(its adding as an image). To show video frames it need to regenerate when video play. It means window need to refresh automatically. To do it you need to set one property for your GMSMarker. Line as follows,
_london.tracksInfoWindowChanges = YES;
So your full code is
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(51.5, -0.127);
_london = [GMSMarker markerWithPosition:position];
_london.title = #"London";
_london.tracksViewChanges = YES;
_london.tracksInfoWindowChanges = YES;
_london.map = self.mapView;
Google documentation is https://developers.google.com/maps/documentation/ios-sdk/marker#set_an_info_window_to_refresh_automatically
I believe that the reason why your code doesn't work is the fact that Google Maps for iOS renders Custom Info Views as Images. I'm not sure, but I believe, since I have also tried with animations and it also doesn't work. When I use animation, I first see the initial state of animation and when I open marker info window again, I see the final state, without animation. Also, when I add a text field on custom info window view, I can't click on that text field. When I try with the video like you, I see a blank window like the player is going to start and hear the sound, but the video never starts.
I have found this note on many questions on Stackoverflow (they say that it is from Google Docs), but I don't see it on Google Docs:
Note: The info window is rendered as an image each time it is displayed on the map. This means that any changes to its properties, while it is active, will not be immediately visible. The contents of the info window will be refreshed the next time that it is displayed.
Source: Google Maps Showing speech bubble in marker info window iOS
Maybe you can try with tracksInfoWindowChanges = YES:
- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker {
marker.tracksInfoWindowChanges = YES;
self.player play];
return self.pinView;
}
Source: How to force refresh contents of the markerInfoWindow in Google Maps iOS SDK
I know that you have set it in viewDidLoad method, but maybe setting it in a
- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker
method maybe will work, but I don't believe. A lot of people say that setting markerInfoWindow to YES works, but I have tried, and it doesn't work.
I have tried to use iOS Maps and video plays without problems. I have never had a problem with using Apple Maps. So, I'm sure that Google Maps isn't a good solution for this problem. Maybe you could fix it by some hack, but I have lost several hours to find a solution, without results. Maybe it can be done, for example, to move a UIView above map when the user moves his finger on the map or zooms in/out, or some other solution, but I prefer system solutions above hacks. In this case, I don't see system solution, maybe I'd find it if I spent more time to research. If I were you, I wouldn't use Google Maps for this.
Edit: I've just seen that my solution works on simulator. On real device (iPhone 7+) it doesn't work, i.e. I see player controls are animating, I see sound, but I don't see the video. But even if it works on real device like it works on simulator, user can't play or pause video, because he only sees images which are updating regularly.
Related
i am using google map api for display the location and search bar for search the location but when the GSMMarker display it snippet window hide inside the uisearchbar so any own please help me.
-(void) setupMarkerOnMap:(CLLocation *)loc PlaceName:(NSString *) strCityName
{
[[self getGoogleMap] clear];
[self getNextButton].enabled = YES;
placeMarker = [GMSMarker markerWithPosition:loc.coordinate];
placeMarker.map = [self getGoogleMap];
[placeMarker setTappable:NO];
placeMarker.snippet = strCityName;
placeMarker.icon = [UIImage imageNamed:#"LocationMarker.png"];
GMSCameraUpdate *updateCamera = [GMSCameraUpdate setTarget:placeMarker.position zoom:10.0];
[[self getGoogleMap] animateWithCameraUpdate:updateCamera];
[[self getGoogleMap] setSelectedMarker:placeMarker];
}
these my code snippet for marker add in google map and i attached image which can help you.
anyone can help me.
Thanks
First of all, Make sure that your Google map does not stack together with the search bar. Then you can use delegate to help you move the animate the marker's position inside the Google Map when you tap on any of the marker. Example code:-
Implement the Google Map Delegate
#interface YourViewController ()<GMSMapViewDelegate>
#property (weak, nonatomic) IBOutlet GMSMapView *mapView;
#end
Set the mapView Delegate to the current view controller
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
}
Whenever a marker is tapped, the
-(BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker{
[mapView animateToLocation:marker.position];
return YES;
}
If you have everything setup correctly and the map is big enough, info window should be displayed nicely inside the map.
I have an app that has a piano built into it. Each key (Button1) when pressed down starts to play the note and when the user lifts their finger I want the note to stop playing. What happens is that the audio does not stop playing when the stop function is set to Touch Up Inside on the key (Button1). If I change the the Action from the piano key (Button1) to a different button (Button2) it stops playing as it should if I press the button 2.
.h
#import <AVFoundation/AVAudioPlayer.h>
#interface FifthViewController : UIViewController <AVAudioPlayerDelegate> {
AVAudioPlayer *theNote;
}
.m
#import <AVFoundation/AVAudioPlayer.h>
#import <AVFoundation/AVFoundation.h>
//White
-(IBAction)note1w:(id)sender { //Touch Down
[self whiteKey:self];
[self downKey:self];
NSString *path = [[NSBundle mainBundle] pathForResource:#"white1" ofType:#"aif"];
theNote = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theNote.delegate = self;
theNote.currentTime = 0;
[theNote play];
}
-(IBAction)stopMusic { //Touch Up Inside - This is the action that I change from the Button1 (The Piano Key) to Button2 (A Reg UIButton) and it works.
[theNote stop];
}
I tried your code in a project and it worked fine. I suspect you misconfigured the touchUp connection (perhaps connected touchUpOutside as I have accidentally done on occasion).
I ended up creating a work around to fix the problem. I already had a long press gesture recognizer in the app so I added to the recognizer state ended [self stopMusic]; and it ran fine. I couldn't replicate the problem in another app. It must be a conflict with other code that is being ran.
In my project I manually create views without using storyboard. I have tried to play a Video when I tap an image. It works fine. But everytime when I check it shows memory leak when I tap the image, I have searched about this a lot and applied but no use.
In my Appdelegate.h file:
#property (strong, nonatomic) MPMoviePlayerController *theMoviePlayer;
#property (strong, nonatomic) UIImageView *image1;
In .m file:
-(void) startPage{
.....
_image1 = [[UIImageView alloc] initWithFrame:CGRectMake((self.window.frame.size.width/2)-25, 40, 50, 50)];
[_image1 setUserInteractionEnabled:YES];
_image1.image = [UIImage imageNamed:#"image_2.jpg"];
_tapImage1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(image1Tapped:)];
[_image1 addGestureRecognizer:_tapImage1];
.....}
In imageTapped(),
-(void) image1Tapped:(UITapGestureRecognizer *)sender
{
.....
[_image1 removeFromSuperview];
_theMoviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
[_theMoviePlayer setControlStyle:MPMovieControlStyleFullscreen];
[_theMoviePlayer.view setFrame:CGRectMake(0,-55, self.window.frame.size.width, self.window.frame.size.height)];
[_theMoviePlayer setScalingMode:MPMovieScalingModeAspectFill];
UIWindow *backgroundWindow = [[UIApplication sharedApplication] keyWindow];
[backgroundWindow addSubview:_theMoviePlayer.view];
[_theMoviePlayer.view bringSubviewToFront:backgroundWindow];
[_theMoviePlayer play];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movieFinished:)
name:MPMoviePlayerPlaybackDidFinishNotification object:_theMoviePlayer];
...}
I get a memory leak everytime it enters imageTapped: method. Any help will be appreciated.
#property (strong, nonatomic) MPMoviePlayerController *theMoviePlayer;
#property (weak, nonatomic) UIImageView *image1;
another think is that your theMoviePlayer is not remove, try to make its view transparency for see if is already working behind the new one
I am trying to help you.
In -(void) startPage you allocate _image1 object
And you are removing object in method -(void) image1Tapped:(UITapGestureRecognizer*)sender
using [_image1 removeFromSuperview]; method
means now _image1 is nil and when -(void) image1Tapped:(UITapGestureRecognizer *)sender method called at that time when u fetch _image1 object at that time _image1 is already nil
so its give Memory Leak warning.
And solution for this one is:
1.**Show/Hide _image1 object** or
every time you need to do proper allocation and remove image1 object in this method -(void) image1Tapped:(UITapGestureRecognizer *)sender, based your requirement.
First try this solution and there will be Memory Leak Warning removed.
The Compiler check all over steps in advance so it recognize as Warning.
In Some cases if your logic is wrong then compiler inform us Wrong logic.
if u want to check that click on blue arrow of memory warning button it will give exaplanation of your logic or warning with assumption.
I found the problem, its with the device iPad(iOS version 5). It shows no leaks when I checked with iPad4 (iOS version 7).
Good morning.
I'm having trouble with a UIImagePickerController not showing anything other than white. I have a 320x320 UIImageView, in my main header file:
IBOutlet UIImageView *_cameraView;
Along with:
#property (nonatomic, retain) UIImagePickerController *_cameraPicker;
#property (nonatomic, retain) UIImage *_noCam;
_noCam is an image which is placed in the view if the user has no camera. That works fine.
I'm trying to show (without the standard camera GUI, but that can wait for now) the camera on top of this square view. In my main class I have:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(#"viewDidAppear did appear too");
//camera view etc
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
//code here to not allow picture taking, probably put up something saying you don'thave a camera on your device
NSLog(#"no cam available");
_noCam = [UIImage imageNamed:#"noCam.png"];
[_cameraView setImage:_noCam];
} else {
//take the shot
_cameraPicker = [[UIImagePickerController alloc] init];
_cameraPicker.delegate = _cameraView;
_cameraPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
NSLog(#"cam is available");
}
}
I'm guessing I have a problem with setting the delegate. _self gives me an error of type:
'from incompatible type 'ViewController *const _strong'
I'm using NSLogs to check the methods are working, it tells me the viewDidLoad and viewDidAppear method were called and that a camera was detected But then I just get the white view.
Any help would be hugely appreciated.
Thanks.
You need to display the picker somehow, you can either use the default GUI:
[self presentModalViewController:_cameraPicker animated:YES];
Or check out the cameraOverlayView of UIImagePickerController.
In my app I need to display stores around the user location. Each store has name, tagline, and a logo, and we want to display all these information on the callout bubble that comes up on the map once I touch a pin. Considering that I need to load the image remotely, and that waiting three seconds to see the callout after touching the pin is not acceptable, what would be the best solution?
The file of an array of around 20 stores is like 10kb, but if we load the logo for all of them straight away, maybe it would be like 110kb (considering an estimate of 5kb per image), which I`m not sure if it is a good idea.
In one of my project that case works just fine.
I'm using SDWebImage for the remote async load of the image.
I did:
subclass the MKPinAnnotationView:
.h
#interface TLStoreResultMapAnnotationView : MKPinAnnotationView
#property (assign)BOOL imageSet;
#end
.m
#import "TLStoreResultMapAnnotationView.h"
#import "TLStoreResultMapAnnotation.h"
#import "UIImageView+WebCache.h"
#implementation TLStoreResultMapAnnotationView
#synthesize imageSet=_imageSet;
- (void)layoutSubviews {
if(self.selected && (!self.imageSet)) {
TLStoreResultMapAnnotation *annotation = (TLStoreResultMapAnnotation *)self.annotation;
NSURL *url = [NSURL URLWithString:[annotation.store.imageURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
UIImageView *storeImageView = (UIImageView *)self.leftCalloutAccessoryView;
storeImageView.frame = CGRectMake(storeImageView.frame.origin.x,storeImageView.frame.origin.y,30.0,30.0);
storeImageView.contentMode = UIViewContentModeScaleAspectFill;
storeImageView.clipsToBounds = YES;
[storeImageView setImageWithURL:url
placeholderImage:[UIImage imageNamed:#"webloading.png"] options:SDWebImageCacheMemoryOnly];
self.imageSet = YES;
}
[super layoutSubviews];
UIImageView *storeImageView = (UIImageView *)self.leftCalloutAccessoryView;
storeImageView.frame = CGRectMake(storeImageView.frame.origin.x,storeImageView.frame.origin.y,30.0,30.0);
}
#end
of course your need to adapt the code a bit.