NSSpeechSynthesizer does not write AIFF-file - objective-c

using Xcode 5.1.1 on OS X 10.9.4,
consider the following code snippets:
- (IBAction)speak:(id)sender // text to loudspeaker, this works
{
[self setup]; // provide the synthesizer with its parameters
[speaker startSpeakingString: [textEntry stringValue]];
}
- (IBAction)storeSpeech:(id)sender // does not work
{
[self setup]; // provide the synthesizer with its parameters
[NSURL *outputFile =
[NSURL URLWithString:#"speech.aiff"];
[speaker startSpeakinString: [textEntry stringValue]
toURL:outputFile]; // the aiff-file is not created, why not?
}
Method speak outputs to the computers speaker. This works ok.
Method storeSpeech does not create any aiff-file. WHY NOT?

"speech.aiff" isn't much of a URL, is it?
Either use a URL that starts with file:// or use a path and a method that creates a file URL.

Related

NSFilePresenter methods never get called

I'm trying to write a simple (toy) program that uses the NSFilePresenter and NSFileCoordinator methods to watch a file for changes.
The program consists of a text view that loads a (hardcoded) text file and a button that will save the file with any changes. The idea is that I have two instances running and saving in one instance will cause the other instance to reload the changed file.
Loading and saving the file works fine but the NSFilePresenter methods are never called. It is all based around a class called FileManager which implements the NSFilePresenter protocol. The code is as follows:
Interface:
#interface FileManager : NSObject <NSFilePresenter>
#property (unsafe_unretained) IBOutlet NSTextView *textView;
- (void) saveFile;
- (void) reloadFile;
#end
Implementation:
#implementation FileManager
{
NSOperationQueue* queue;
NSURL* fileURL;
}
- (id) init {
self = [super init];
if (self) {
self->queue = [NSOperationQueue new];
self->fileURL = [NSURL URLWithString:#"/Users/Jonathan/file.txt"];
[NSFileCoordinator addFilePresenter:self];
}
return self;
}
- (NSURL*) presentedItemURL {
NSLog(#"presentedItemURL");
return self->fileURL;
}
- (NSOperationQueue*) presentedItemOperationQueue {
NSLog(#"presentedItemOperationQueue");
return self->queue;
}
- (void) saveFile {
NSFileCoordinator* coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:self];
NSError* error;
[coordinator coordinateWritingItemAtURL:self->fileURL options:NSFileCoordinatorWritingForMerging error:&error byAccessor:^(NSURL* url) {
NSString* content = [self.textView string];
[content writeToFile:[url path] atomically:YES encoding:NSUTF8StringEncoding error:NULL];
}];
}
- (void) reloadFile {
NSFileManager* fileManager = [NSFileManager defaultManager];
NSFileCoordinator* coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:self];
NSError* error;
__block NSData* content;
[coordinator coordinateReadingItemAtURL:self->fileURL options:0 error:&error byAccessor:^(NSURL* url) {
if ([fileManager fileExistsAtPath:[url path]]) {
content = [fileManager contentsAtPath:[url path]];
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
[self.textView setString:[[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding]];
});
}
// After this I implement *every* method in the NSFilePresenter protocol. Each one
// simply logs its method name (so I can see it has been called) and calls reloadFile
// (not the correct implementation for all of them I know, but good enough for now).
#end
Note, reloadFile is called in applicationDidFinishLaunching and saveFile gets called every time the save button is click (via the app delegate).
The only NSFilePresenter method that ever gets called (going by the logs) is presentedItemURL (which gets called four times when the program starts and loads the file and three times whenever save is clicked. Clicking save in a second instance has no noticeable effect on the first instance.
Can anyone tell me what I'm doing wrong here?
I was struggling with this exact issue for quite a while. For me, the only method that would be called was -presentedSubitemDidChangeAtURL: (I was monitoring a directory rather than a file). I opened a technical support issue with Apple, and their response was that this is a bug, and the only thing we can do right now is to do everything through -presentedSubitemDidChangeAtURL: if you're monitoring a directory. Not sure what can be done when monitoring a file.
I would encourage anyone encountering this issue to file a bug (https://bugreport.apple.com) to encourage Apple to get this problem fixed as soon as possible.
(I realize that this is an old question, but... :) )
First of all, I notice you don't have [NSFileCoordinator removeFilePresenter:self]; anywhere (it should be in dealloc).
Secondly, you wrote:
// After this I implement *every* method in the NSFilePresenter protocol. Each one
// simply logs its method name (so I can see it has been called) and calls reloadFile
// (not the correct implementation for all of them I know, but good enough for now).
You're right: it's the incorrect implementation! And you're wrong: it's not good enough, because it's essential for methods like accommodatePresentedItemDeletionWithCompletionHandler: which take a completion block as a parameter, that you actually call this completion block whenever you implement them, e.g.
- (void) savePresentedItemChangesWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler
{
// implement your save routine here, but only if you need to!
if ( dataHasChanged ) [self save]; // <-- meta code
//
NSError * err = nil; // <-- = no error, in this simple implementation
completionHandler(err); // <-- essential!
}
I don't know whether this is the reason your protocol methods are not being called, but it's certainly a place to start. Well, assuming you haven't already worked out what was wrong in the past three years! :-)

QLPreviewController not working in iOS 6

In iOS 6 the QLPreviewController no longer loads a PDF from a URL. It works fine in iOS 5. I have implemented the QLPreviewControllerDataSource methods as documented here.
#pragma mark - QLPreviewControllerDataSource
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller {
return 1;
}
- (id <QLPreviewItem>) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index;
{
NSURL *fileURL = [NSURL URLWithString:#"http://www.bliley.net/XTAL/PDF_Instructions/Test_File.pdf"];
return fileURL;
}
This works perfectly in iOS 5, however in iOS 6 the console outputs:
Couldn't issue file extension for path: /XTAL/PDF_Instructions/Test_File.pdf
Have you tried using fileURLWithPath instead of URLWithString? I had other issues that were fixed by doing so.
Also not sure if QLPreviewController will handle remote URLs. If not, you could download the file and then display it.
I downloaded the file from remote url and saved locally, then I display the PDF using the QLPreviewController .In iOS 6 its working.
First i saved the file from remote url using the following code :
NSString *local_location;
NSString *path = [[NSBundle mainBundle] pathForResource:#"sampleData" ofType:#"plist"];
path = NSTemporaryDirectory();
local_location= [path stringByAppendingPathComponent:[NSString stringWithFormat:#"My_Invoice.pdf"]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString: remoteurl]];
[request setDownloadDestinationPath:local_location];
[request startSynchronous];
For showing the Pdf :
QLPreviewController* preview = [[QLPreviewController alloc] init];
preview.dataSource = self;
[self presentModalViewController:preview animated:YES];
QLPreviewController delegate methods are :
- (NSInteger) numberOfPreviewItemsInPreviewController: (QLPreviewController *) controller
{
return 1;
}
- (id <QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
{
return [NSURL fileURLWithPath:local_location];
}
I am having a similar issue and seems like it might stem from a stricter enforcement of the file-type URL of QLPreviewItem
#property (readonly) NSURL *previewItemURL;
Discussion
This property is used by a Quick Look preview controller to get an item’s URL. In typical use, you would implement a getter method in your preview item class to provide this value.
The value of this property must be a file-type URL.
If the item is not available for preview, this property’s getter method should return nil. In this case, the Quick Look preview controller displays a “loading” view.
Availability
Available in iOS 4.0 and later.
Declared In
QLPreviewItem.h
UPDATE: I have opened a bug with Apple dealing with this issue for iOS 6 and it seems they have aced it as a bug so may offer a fix in the near future. The bug I opened had to do with using custom NSURLProtocols for the preview, but may apply to other aspects as well.
Link to class
But note that QLPreviewController expects a URL to a local resource
You would need to download and save the PDF file locally first and then create a proper file URL to the local file.

How to pass arguments to app built on Phonegap

I'm writing an app using JQM and Phonegap to deploy on iOS and I need it to read input arguments like a url arguments of a common website does in javascript by handling the object 'window.location.search'
In my situation, the app will be launched from a website, like this:
My App
This is working right now, I can already call my app, what I need now is to read the arguments arg1, arg2, etc. I've tried reading window.location.search but with no luck.
How can I do this? Do I need to write some Objective C code?
Any suggestions would be appreciated.
Thanks.
My problem was solved using the content of this link: https://gist.github.com/859540
The code is:
Objective-c part:
In MainViewController.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// perform any custom startup stuff you need to ...
// process your launch options
NSArray *keyArray = [launchOptions allKeys];
if ([launchOptions objectForKey:[keyArray objectAtIndex:0]]!=nil)
{
// we store the string, so we can use it later, after the webView loads
NSURL *url = [launchOptions objectForKey:[keyArray objectAtIndex:0]];
self.invokeString = [url absoluteString];
NSLog(#amp;" launchOptions = %#",url); // if you want to see what is happening
}
// call super, because it is super important ( 99% of phonegap functionality starts here )
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (void) webViewDidFinishLoad:(UIWebView*) theWebView
{
// only valid if ___PROJECTNAME__-Info.plist specifies a protocol to handle
if (self.invokeString)
{
// this is passed before the deviceready event is fired, so you can access it in js when you receive deviceready
NSString* jsString = [NSString stringWithFormat:#"var invokeString = \"%#\";", self.invokeString];
[theWebView stringByEvaluatingJavaScriptFromString:jsString];
}
// Black base color for background matches the native apps
theWebView.backgroundColor = [UIColor blackColor];
return [super webViewDidFinishLoad:theWebView];
}
In the index.html file using cordova-1.7.0:
function onDeviceReady()
{
alert(invokeString);
}
alert returned: myapp://?arg1=1&arg2=2
just the same string used to call it ... :)
I had the same issue, everything here in these answers is hella confusing and extra information.
Understanding and solving the problem in 2 easy steps:
Informative (you can skip if you don't care what happens in the background): Go to AppDelegate.m in Clases folder in the project and search for "handleOpenUrl", you should notice some code there with comments explaining what's up. I don't know objective-c, but intuitively that code there looks for window.handleOpenURL function and calls it giving it the parameter of the url called (e.g. 'myapp:///?parameter=value')
Basically all you have to do is globally(in window object) define the function handleOpenURL
function handleOpenURL (url) {
alert(url);
}
Note that this only gets executed when your app is opened with an
..
window.location will be the location of your phonegap index.html file, not the URL that was used to launch your app.
Some web searches suggested that a function called:
function handleOpenUrl(url) {
alert("opened from url " + url);
}
.. might automatically be called . I don't have my dev machine here to test though, Sorry!
If this doesn't work in Objective-C check out the handleOpenUrl method of the AppDelegate.m This gets called when your app is opened with a URL Scheme.
you should do it in obj-c and then with a plugin pass it to javascript code :
for doing it in obj-c first you should implement
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSURL *urlToParse = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
if (urlToParse) {
[self application:application handleOpenURL:urlToParse];
}
return YES;
}
and then you could access parameters like this :
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[url scheme] isEqualToString:#"myapp"]) {
//in here you do whatever you need the app to do
// e.g decode JSON string from base64 to plain text & parse JSON string
}
return YES; //if everything went well
}
function getParameterByName(name)
{
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.href);
if(results == null)
return "";
else
return results[1];
}
Call this function like var para1 = getParameterByName("para1");
on pageshow event in jquery mobile.
$('#page').on('pageshow',function(event){
var para1 = getParameterByName("para1");
});

incompatible pointer to integer conversion sending viewcontroller * to parameter of type BOOL

I was trying to work out how to read a text file stored on a web server and display the contents in a text view. I have followed the documentation from Apple website NSURLConnection of how to establish a NSURLConnection and receiveData and display the received data.
I have created a button where I want to load the text view on button click. For that I wrote this method
- (void)loadWeb:(BOOL)animated
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://nowayweb.com/mytext.txt"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
NSURLConnection *myConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (myConnection) {
downloadedData = [[NSMutableData data] retain];
}
else{
NSLog(#"Error");
}
}
But I am getting a warning in my .m file which can be seen in the screenshot as shown here:
It works fine and I can view the text in the text view, but I am wondering where am I making the mistake. If somebody throws some light on this, would be helpful.
Or is there a better way to load the contents from web by button click. Any help is appreciated.
Thanks
self is a pointer to an object, not a BOOL value. You should do this:
[self loadWeb: YES];
Except your method does not seem to use the parameter anyway, so you might as well get rid of it.
[self loadWeb];
and
- (void)loadWeb
{
// all the stuff inside
}
The reason it worked for you is a) you weren't using the parameter, b) the compiler will automatically convert self into a BOOL by chopping off all but the least significant byte of the pointer. If you had been using the parameter, most of the time it would have been YES by chance and occasionally it would have been NO by chance.
ObjC's BOOL is not a real boolean type. it is a typedef for a signed char.
The method's signature is:
- (void)loadWeb:(BOOL)animated
the expression [self loadWeb:self]; doesn't make sense, and it's not a real bool conversion. the compiler warns you that you are converting a pointer to a signed char.
It should read either:
[self loadWeb:YES];
-or-
[self loadWeb:NO];
-or-
BOOL someBOOLVariableOrParameter = ...; // YES or NO
[self loadWeb:someBOOLVariableOrParameter];

Adding QLPreviewController as subview doesn't load PDF

I'm trying to add a QLPreviewController's view as a subview (no--I cannot use a nav controller or modal). It only shows the fabric background of the QLPreviewController.
I create one and add it as a subview:
QLPreviewController* preview = [[[QLPreviewController alloc] init] autorelease];
preview.dataSource = self;
preview.delegate = self;
preview.view.frame = CGRectMake(0, 0, self.pdfPreviewView.frame.size.width, self.pdfPreviewView.frame.size.height);
self.pdfPreviewView.previewController = preview;
[self.pdfPreviewView addSubview:preview.view];
[preview reloadData];
My QLPreviewControllerDataSource methods work fine (viewing 1 pdf at a time):
- (id <QLPreviewItem>) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index
{
NSString *path = [[ResourceManager defaultManager] pathForPDF:self.currentPDF];
NSURL *url = [NSURL fileURLWithPath:path];
if ([QLPreviewController canPreviewItem:url]) {
return url; // This always returns
}
return nil; // This line is never executed
}
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller
{
return 1;
}
The data source method always returns the file url, and QLPreviewController says it can open the file, but it never actually does. I just get the background. The self.currentPDF is set before I create the QLPreviewController and does contain the correct information (from CoreData).
The delegate methods never get called. But I'm also not using it in a standard way, so that's not totally unexpected.
I've also tried calling [preview setNeedsLayout], [preview setNeedsDisplay'], and [preview refreshCurrentPreviewItem] but those just call the data source methods and don't change anything.
The PDFs are valid. I can open them in both Xcode and Preview, so that's not the problem. I'm kind of stumped as to why this won't work. Any help would be appreciated in getting this to work.
Turns out I was sending QLPreviewController the wrong path. It wasn't finding the PDF in the bundle correctly. I needed to use pathForResource:ofType:inDirectory.