FBSDKMessageDialog sharing link take very long time to load when in Messenger - facebook-ios-sdk

I tried to let users able to share my URL via Messenger with Facebook iOS SDK 4.6 . The problem is when the Messenger opened. The "send field" is empty and take sometimes to for the sharing link to appear. This is annoying . Are there anyway to solve this ?
Here is my code
FBSDKMessageDialog *messageDialog = [[FBSDKMessageDialog alloc] init];
if([messageDialog canShow]) {
FBSDKShareLinkContent *content = [[FBSDKShareLinkContent alloc] init];
content.contentURL = shareURL;
content.contentTitle = shareTitle;
content.imageURL = imageURL;
content.contentDescription = #"#xxxxx";
messageDialog.shareContent = content;
messageDialog.delegate = self;
[messageDialog show];
}

Related

How can I play a custom sound in WatchOS 3 that will playback on the watch speakers

I've read that we can now play custom sounds on the apple watch in watchos 3.
According to the announcement from Apple so apparently there is but I don't have an example to test it out: 3D spatial audio implemented using SCNAudioSource or SCNAudioPlayer. Instead, use playAudioSource:waitForCompletion: or the WatchKit sound or haptic APIs. Found here: https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInwatchOS/Articles/watchOS3.html
Can someone place a simple example of this. I'm not using SceneKit in my app as I don't need it but if that's the only way to play a custom sound then I'd like to know the minimum code required to accomplish this. Preferably in Objective c but I'll take it in whatever shape. I'm ok using SpriteKit if that's easier also.
Here's what I have so far but it doesn't work:
SCNNode * audioNode = [[SCNNode alloc] init];
SCNAudioSource * audioSource = [SCNAudioSource audioSourceNamed:#"mysound.mp3"];
SCNAudioPlayer * audioPlayer = [SCNAudioPlayer audioPlayerWithSource:audioSource];
[audioNode addAudioPlayer:audioPlayer];
SCNAction * play = [SCNAction playAudioSource:audioSource waitForCompletion:YES];
[audioNode runAction:play];
I can confirm, that #ApperleyA solution really works!
Here is the swift version:
var _audioPlayer : AVAudioPlayerNode!
var _audioEngine : AVAudioEngine!
func playAudio()
{
if (_audioPlayer==nil) {
_audioPlayer = AVAudioPlayerNode()
_audioEngine = AVAudioEngine()
_audioEngine.attach(_audioPlayer)
let stereoFormat = AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 2)
_audioEngine.connect(_audioPlayer, to: _audioEngine.mainMixerNode, format: stereoFormat)
do {
if !_audioEngine.isRunning {
try _audioEngine.start()
}
} catch {}
}
if let path = Bundle.main.path(forResource: "test", ofType: "mp3") {
let fileUrl = URL(fileURLWithPath: path)
do {
let asset = try AVAudioFile(forReading: fileUrl)
_audioPlayer.scheduleFile(asset, at: nil, completionHandler: nil)
_audioPlayer.play()
} catch {
print ("asset error")
}
}
}
This is Objective-c but can be translated into Swift
I ended up using AVAudioEngine and AVAudioPlayerNode to play audio on the Apple watch.
The gist of how to do this is as follows:
I call the following inside the init method of my AudioPlayer (it's an NSObject subclass to encapsulate the functionality)
_audioPlayer = [[AVAudioPlayerNode alloc] init];
_audioEngine = [[AVAudioEngine alloc] init];
[_audioEngine attachNode:_audioPlayer];
AVAudioFormat *stereoFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:44100 channels:2];
[_audioEngine connect:_audioPlayer to:_audioEngine.mainMixerNode format:stereoFormat];
if (!_audioEngine.isRunning) {
NSError* error;
[_audioEngine startAndReturnError:&error];
}
I have a cache setup so I don't recreate the AVAudioFile assets every time I want to play a sound but you don't need to.
So next create an AVAudioFile object:
NSError *error;
NSBundle* appBundle = [NSBundle mainBundle];
NSURL *url = [NSURL fileURLWithPath:[appBundle pathForResource:key ofType:#"aifc"]];
AVAudioFile *asset = [[AVAudioFile alloc] initForReading:url &error];
Then play that file:
[_audioPlayer scheduleFile:asset atTime:nil completionHandler:nil];
[_audioPlayer play];
UPDATE: If the app goes to sleep or is put to the background there is a chance the audio will stop playing/fade out. By activating an Audio Session this will be prevented.
NSError *error;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
if (error) {
NSLog(#"AVAudioSession setCategory ERROR: %#", error.localizedDescription);
}
[[AVAudioSession sharedInstance] setActive:YES error:&error];
if (error) {
NSLog(#"AVAudioSession setActive ERROR: %#", error.localizedDescription);
}
I didn't go over handling any errors but this should work. Don't forget to #import <AVFoundation/AVFoundation.h> at the top of your implementation file.
This worked for me in the simulator
let soundPath = Bundle.main.path(forResource: "cheerMP3", ofType: "mp3")
let soundPathURL = URL(fileURLWithPath: soundPath!)
let audioFile = WKAudioFileAsset(url: soundPathURL)
let audioItem = WKAudioFilePlayerItem(asset: audioFile)
let audioPlayer = WKAudioFilePlayer.init(playerItem: audioItem)
if audioPlayer.status == .readyToPlay
{
audioPlayer.play()
}
else
{
print("Not ready!!")
}
but only if I had a breakpoint at both audioPlayer.play() and after the last }.
dunqan, what did you put at the top of the file, the import statements? I wasn't able to include
import AVFoundation
without an error using Xcode 8.2.1

Take user to location when they get their location

I have code that gets user location and displays it on the mapView, but they have to zoom out and find themselves on the map, what I want is when the button is pressed it automatically takes them to where they are. Heres my code so far:
- (void)viewDidLoad
{
[super viewDidLoad];
MKCoordinateRegion bombersRegion = { {0.0,0.0}, {0.0,0.0} };
bombersRegion.center.latitude = 42.812548;
bombersRegion.center.longitude = -73.940815;
bombersRegion.span.latitudeDelta = 0.01f;
bombersRegion.span.longitudeDelta = 0.01f;
[bombersMapView setRegion:bombersRegion animated:YES];
MapPin *ann = [[MapPin alloc] init];
ann.title = #"Bombers Burrito Bar";
ann.subtitle = #"447 State Street Schenectady, New York 12305";
ann.coordinate = bombersRegion.center;
[bombersMapView addAnnotation:ann];
}
-(IBAction)getLocation:(id)sender{
bombersMapView.showsUserLocation = YES;
}
Thanks for the help.
I would really appreciate some sample code.
If you want the the map to stay centered on user's location try this
[bombersMapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
Take a look at this MKMapViewDelegate method. This will give you the users location which you can use to zoom in on. The method you're looking for is mapView:didUpdateUserLocation:.

GPUImageVideoCamera save video on ios 7

I'm trying to achieve the square video recording like 300*300 so I choose GPUImage but its not working on IOS 7 and giving errors like [UIView nextAvailableTextureIndex]: unrecognized selector sent to instance the error starts when we build the even the sample code
when trying to save the GPUImageVideoCamera
some times its stucks at [movieWriter startRecording]; 
is the GPUImage compatible with ios 7 or we have made some changes ?
here is the code
- (void)viewDidLoad
{
[super viewDidLoad];
videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack];
videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
videoCamera.horizontallyMirrorFrontFacingCamera = NO;
videoCamera.horizontallyMirrorRearFacingCamera = NO;
filter = [[GPUImageSepiaFilter alloc] init];
initWithRotation:kGPUImageRotateRightFlipVertical];
[videoCamera addTarget:filter];
GPUImageView *filterView = (GPUImageView *)self.view;
[filter addTarget:filterView];
sharing
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Movie.m4v"];
unlink([pathToMovie UTF8String]); // If a file already exists, AVAssetWriter won't let you record new frames, so delete the old movie
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(480.0, 640.0)];
[filter addTarget:movieWriter];
}
- (IBAction)stopRecording:(id)sender {
[filter removeTarget:movieWriter];
videoCamera.audioEncodingTarget = nil;
[movieWriter finishRecording];
}
- (IBAction)startRecording:(id)sender {
videoCamera.audioEncodingTarget = movieWriter;
[movieWriter startRecording];
[videoCamera startCameraCapture];
}
My guess is that you modified the .xib or storyboard and didn't set the class of the view that is showing the camera preview to GPUImageView.

iOS - passing a null managed object -

I've read a lot of similar posts but after two days, I thought I should ask my own question.
I have a separate CoreData Controller. This passes the entity object fine from AppDelegate to the RootViewController. It does not pass it to a specific (Category) view controller, and I cant figure out why.
The code in App Delegate where I try to pass the object is this:
rootViewController.managedObjectContext = self.coreDataController.mainThreadContext;
categoryListViewController.managedObjectContext = self.coreDataController.mainThreadContext;
NSLog(#"AD/core data controller is %#", coreDataController.mainThreadContext);
NSLog(#"AD- rootVC is %#", rootViewController.managedObjectContext);
NSLog(#"AD/category list is %#", categoryListViewController.managedObjectContext);
and the logs show that the core data controller and the root vc get populated, but the Category vc doesn't.
2012-12-02 14:28:33.187 [50351:907] AD/coredatacontroller moc is <NSManagedObjectContext: 0x21065160>
2012-12-02 14:28:33.188 [50351:907] AD/categorycontroller moc is (null)
2012-12-02 14:28:33.190 [50351:907] AD- rootVC moc is <NSManagedObjectContext: 0x21065160>
Any ideas why?
UPDATE
If I do as suggested by Valentin, and init the Category VC in the App Delegate, I certainly get the managed objects passed through, however, as I call the view from the Detail VC. When I do that, I get the error "Application tried to push a nil view controller on target ".
If I try to init the category VC (and load the context) in the detail VC, it does not convey, and the logs show the context to be nil.
Init the VC (in App Delegate):
categoryListViewController = [[CategoryListViewController alloc] initWithNibName:#"CategoryList-iPad" bundle:nil];
// we have loaded from our xib, so has our CoreDataController,
// so connect as its delegate and setup its persistent store
//
self.coreDataController.delegate = self;
[self.coreDataController loadPersistentStores];
UINavigationController *rootNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
// Set up MASTER and DETAIL delegation so we can send messages between views
rootViewController.detailViewController = detailViewController;
detailViewController.rootViewController = rootViewController;
splitViewController = [[UISplitViewController alloc] init];
splitViewController.viewControllers = #[rootNavigationController, detailNavigationController];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
splitViewController.delegate = detailViewController;
rootViewController.managedObjectContext = self.coreDataController.mainThreadContext;
categoryListViewController.managedObjectContext = self.coreDataController.mainThreadContext;
NSLog(#"AD - coreDataController is %#", coreDataController.mainThreadContext);
NSLog(#"AD - rootViewController is %#", rootViewController.managedObjectContext);
NSLog(#"AD - categoryListVC is %#", categoryListViewController.managedObjectContext);
Call the view (in DetailViewController):
-(void)categoryButtonTapped {
NSLog(#"%s", __FUNCTION__);
//categoryListViewController = [[CategoryListViewController alloc] initWithNibName:#"CategoryList-iPad" bundle:nil];
//categoryListViewController.managedObjectContext = coreDataController.mainThreadContext;
//categoryListViewController.managedObjectContext = self.coreDataController.mainThreadContext;
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:categoryListViewController];
nc.modalPresentationStyle = UIModalPresentationFormSheet;
NSLog(#"DVC FRC is %#", self);
NSLog(#"DVC FRC/moc is %#", coreDataController.mainThreadContext);
NSLog(#"DVC FRC/self.moc is %#", self.coreDataController.mainThreadContext);
[self presentViewController:nc animated:YES completion:nil];
//[self.navigationController pushViewController:categoryListViewController animated:YES];
}
Most probably your categoryListViewController is nil as well. Try to see if it gets alloc'ed/initialised correctly.

Unable to Integrate Instagram in iOS App

i am unable to post my photos on instagram using ios App. I got the following code from a post here on stackoverflow but it does not work. When Instagram starts, it displays error unable to open file. kindly help me.
NSURL *instagramURL = [NSURL URLWithString:#"instagram://location?id=1"];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:#"Image.ig"];
NSData *imageData = UIImagePNGRepresentation([UIImage imageNamed:#"Icon.png"]);
[imageData writeToFile:savedImagePath atomically:YES];
NSURL *imageUrl = [NSURL fileURLWithPath:savedImagePath];
docController = [[UIDocumentInteractionController alloc] init];
docController.delegate = self;
[docController retain];
docController.UTI = #"com.instagram.photo";
[docController setURL:imageUrl];
[docController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
}else{
UIAlertView *errorToShare = [[UIAlertView alloc] initWithTitle:#"Instagram unavailable " message:#"You need to install Instagram in your device in order to share this image" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorToShare show];
[errorToShare release];
}
Minimum resolution for instagram is 612x612. Always JPG.
For the sake of completion, the minimum resolution remains at 612x612 (this is due to displaying images on retina devices), but Instagram now supports both JPEG and PNG images. All non-square images sent to Instagram must be cropped before posting.

Resources