I am facing app extension close issues , please tell me if anyone know what wrong am doing.I am using action extension after preform some action inside extension i need to return response back.
Sample Code
// With Success Case
- (void) completeActionWithItems: (NSString *) response {
NSExtensionItem *extensionItem = [[NSExtensionItem alloc] init];
extensionItem.attachments = #[[[NSItemProvider alloc] response typeIdentifier: (NSString *)kUTTypePlainText]];
[self.extensionContext completeRequestReturningItems: #[extensionItem] completionHandler: nil];
}
// With Error Case
- (void) completeActionWithError: (NSError *) error {
[self.extensionContext cancelRequestWithError: error];
}
With Success Case working fine but some time is not closing,
With Error Case not working above code.
Please let me know what went wrong.Thanks
When you create an action extension, this is the default method which will close the Action Extension View Controller:
- (IBAction)done {
// Return any edited content to the host app.
// This template doesn't do anything, so we just echo the passed in items.
[self.extensionContext completeRequestReturningItems:self.extensionContext.inputItems completionHandler:nil];
}
Since this method is already provided, you should just try calling it from your success method.
// With Success Case
- (void) completeActionWithItems: (NSString *) response {
NSExtensionItem *extensionItem = [[NSExtensionItem alloc] init];
extensionItem.attachments = #[[[NSItemProvider alloc] response typeIdentifier: (NSString *)kUTTypePlainText]];
[self.extensionContext completeRequestReturningItems: #[extensionItem] completionHandler: nil];
// Call to "done" method
[self done];
}
Related
Every time I am trying to log out the current user (not Fast User Switchting!) I get a message from macOS (excuse me if its not exactly the message, I am getting it in german): "Unable to logout, because application "com.my.app" does not quit".
What do I need in order to avoid this? I currently have this in my AppDelegate:
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
return NSTerminateNow;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
return true;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
selector: #selector(receiveLogOffOrShutdown:)
name: NSWorkspaceWillPowerOffNotification object: NULL];
}
-(void) receiveLogOffOrShutdown: (NSNotification*) note
{
[application stop:nil];
}
What I have observed for example is that receiveLogOffOrShutdown is never triggered. As well as applicationShouldTerminate never triggers a breakpoint.
Am I missing something here?
Use NSApp.terminate method
Objective C
-(void)relaunch {
int processIdentifier = NSProcessInfo.processInfo.processIdentifier;
NSString *path = [NSBundle mainBundle].executablePath;
NSArray *arg = [NSArray arrayWithObjects:[NSString stringWithFormat:#"%d",processIdentifier], nil];
[NSTask launchedTaskWithLaunchPath:path arguments:arg];
[NSApp terminate:self];
}
Swift
func relaunch() {
let processIdentifier: Int32 = NSProcessInfo.processInfo().processIdentifier
let path = NSBundle.mainBundle().executablePath! as NSString
// let myPath: String = "\(path.fileSystemRepresentation)"
NSTask.launchedTaskWithLaunchPath(path as String, arguments: ["\(processIdentifier)"])
NSApp.terminate(self)
}
func terminate(sender: AnyObject?)
When invoked, this method performs several steps to process the termination request
Hope this help you.
I have a problem with SoundCloud API in my application.
I have created an app, what get link to the track (e.g. something like this http://api.soundcloud.com/tracks/48760960) and get stream_url, what later can be played using SCAudioStream. There is no auth for users, I use only client id and client secret of my app. App is registered.
I create soundCloudManager this way:
- (id)init
{
if(self = [super init])
{
conf = [SCSoundCloudAPIConfiguration configurationForProductionWithClientID: kSCClientID
clientSecret: kSCClientSecret
redirectURL: kSCRedirectURL];
conf.accessTokenURL = kSCAccessTokenURL;
api = [[SCSoundCloudAPI alloc] initWithDelegate: self
authenticationDelegate: self
apiConfiguration: conf];
//[api checkAuthentication];
}
return self;
}
If uncomment [api checkAuthentication], then logs will says next:
"auth ready with URL:https://soundcloud.com/connect?client_id=&redirect_uri=&response_type=code"
Then I call this method to get data from track:
- (void)runSearchingStreamWithTrackID: (NSString *)trackID
{
[api performMethod: #"GET"
onResource: #"tracks"
withParameters: [NSDictionary dictionaryWithObject:trackID forKey:#"ids"]
context: #"trackid"
userInfo: nil];
}
And then this delegate's method calls:
- (void)soundCloudAPI:(SCSoundCloudAPI *)soundCloudAPI
didFailWithError:(NSError *)error
context:(id)context
userInfo:(id)userInfo
Text of error:
"HTTP Error: 401".
It means unauthorized. But why? Should I be authorized as soundCloud user to getting info about tracks?
I'm using this for SoundCloudAPI:
https://github.com/soundcloud/cocoa-api-wrapper
Please, help! :(
Today I fixed it. I just add this method to init :
[api authenticateWithUsername:kLogin password:kPwd];
After it this method was called:
- (void)soundCloudAPIDidAuthenticate
So, this test account was authorized.
Then I call this method:
- (void)runSearchingStreamWithTrackID: (NSString *)trackID
{
[api performMethod: #"GET"
onResource: #"tracks"
withParameters: [NSDictionary dictionaryWithObject:trackID forKey:#"ids"]
context: #"trackid"
userInfo: nil];
}
And no one of these methods will be called:
- (void)soundCloudAPI:(SCSoundCloudAPI *)soundCloudAPI
didFailWithError:(NSError *)error
context:(id)context
userInfo:(id)userInfo;
- (void)soundCloudAPI:(SCSoundCloudAPI *)soundCloudAPI
didFinishWithData:(NSData *)data
context:(id)context
userInfo:(id)userInfo;
- (void)soundCloudAPIDidAuthenticate;
- (void)soundCloudAPIDidResetAuthentication;
- (void)soundCloudAPIDidFailToGetAccessTokenWithError:(NSError *)error;
- (void)soundCloudAPIPreparedAuthorizationURL:(NSURL *)authorizationURL;
But there is log:
-[NXOAuth2PostBodyStream open] Stream has been reopened after close
And this method was called:
[NXOAuth2Client oauthConnection:connection didFailWithError:error];
error: HTTP 401
What do I wrong?
I understood the problem. Just download the SC API from the official site and install the latest SC API. Then do something like this:
- (void)searchStreamURLByTrackID: (NSString *)trackID
{
NSString *string = [NSString stringWithFormat:#"https://api.soundcloud.com/tracks/%#.json?client_id=%#", trackID, kSCClientID];
[SCRequest performMethod: SCRequestMethodGET
onResource: [NSURL URLWithString:string]
usingParameters: nil
withAccount: nil
sendingProgressHandler: nil
responseHandler:^(NSURLResponse *response, NSData *data, NSError *error){
NSString *resultString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"FOUND:\n%#", resultString);
}
];
}
After that obtain the stream url from the JSON in the resultString.
Finally, you have to write this code:
NSString *streamURL = [(NSDictionary *)jsonData objectForKey:#"stream_url"];
NSString *realURL = [streamURL stringByAppendingFormat:#".json?client_id=%#", kSCClientID];
AVPlayer *player = [[AVPlayer alloc] initWithURL:[NSURL URLWithString:realURL]];
Enjoy!
Did you check https://github.com/soundcloud/CocoaSoundCloudAPI ?
This is the more current version of the API wrapper (if you don't need iOS 3.0 support).
It also comes with a tutorial video: http://vimeo.com/28715664
If you want to stay with this library you should try to figure out where the log message ("auth ready with ...") appears. Did you implement any of the AuthorizationDelegate methods?
See https://github.com/soundcloud/cocoa-api-wrapper/blob/master/Usage.md#the-authentication-delegate-the-easy-way
Having a heck of a time with this one.
I've got a super-simple Cocoa app containing one WebView, a WebScripting API defined in the page, and a single NSObject defined on that API. When I turn on the debugger tools (in the embedded WebView), I can see the API on the JavaScript window object, and I can see my "api" property defined on that -- but when I call the API's "get" method, the arguments aren't being serialized -- when the Obj-C method gets called, the arguments are missing. See below, which hopefully illustrates:
I've combed through the docs, I've (apparently) set the appropriate methods to expose everything that needs to be exposed, and I can see the method being called. There has to be something stupid I'm missing, but as a relative newbie to this environment, I'm not seeing it.
Thanks in advance for your help!
Have you set WebKitDeveloperExtras to YES in your default user defaults when you send -[NSUserDefaults registerDefaults:]?
Depending on what version of Xcode you're using you could be getting a known error. If you're using LLDB on anything but the most recent version, it might not be giving you the right variables in the debugger. The solution has been to use GDB instead of LLDB until Apple fixes the problem. But I think they fixed the problem in the latest version. I'd change the debugger to use GDB and see if you're getting the right variables in Xcode. (Product-> Edit Scheme...-> Run -> Debugger). I came across this problem in iOS, though, so I don't know its applicability to OSX. Worth a try anyway.
I originally came across the problem here: https://stackoverflow.com/a/9485349/1147934
I process javascript in the main thread of my app from a local file stored in the apps directory. I check for beginning and ending tokens for the js functions I am executing and whether the function contains a variable.
Hopefully this can give you some good ideas for your issue. You could also do alerts in the js to see if the values post correctly as you run the app (I am sure you thought of that already, but it's worth mentioning.) Happy coding! I hope this helps!
in the .h file define:
NSMutableString *processedCommand;
NSArray *commandArguments;
In the .m file:
// tokens
#define kOpenToken #"<%%"
#define kCloseToken #"%%>"
// this will throw
-(void)executeJScriptCommand:(NSString *)aCommand {
[self performSelectorOnMainThread:#selector(executeThisCommand:) withObject:aCommand waitUntilDone:YES];
}
// this will throw
-(NSString *)executeCommand:(NSString *)command {
NSString *aCommand = [[[command stringByReplacingOccurrencesOfString:kOpenToken withString:#""]
stringByReplacingOccurrencesOfString:kCloseToken withString:#""]
stringByTrimmingLeadingAndTrailingWhitespaces];
if ([aCommand hasPrefix:#"="])
{
// variable. get value
[self getVariableFromCommand:aCommand];
}
else {
[self executeThisCommand:aCommand];
}
NSString *returnValue = [NSString stringWithString:processedCommand];
self.processedCommand = nil;
self.commandArguments = nil;
return returnValue;
}
-(void)executeThisCommand:(NSString *)aCommand {
BOOL hasError = NO;
// clear result
self.processedCommand = nil;
self.commandArguments = nil;
BOOL isFromJS = NO;
NSString *function = nil;
NSMutableArray *commandParts = nil;
#try {
// first, break the command into its parts and extract the function that needs to be called, and the (optional) arguments
commandParts = [[NSMutableArray alloc] initWithArray:[aCommand componentsSeparatedByString:#":"]];
if ([[[commandParts objectAtIndex:0] lowercaseString] isEqualToString:#"js-call"]) {
isFromJS = YES;
[commandParts removeObjectAtIndex:0];
}
// get our function, arguments
function = [[commandParts objectAtIndex:0] retain];
[commandParts removeObjectAtIndex:0];
if ([commandParts count] > 0){
if (isFromJS == YES) {
NSString *arguments = [[commandParts objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if ([arguments length] > 0) {
self.commandArguments = [arguments JSONValue];
}
}
else {
self.commandArguments = [NSArray arrayWithArray:commandParts];
}
}
// build invoke
SEL sel = NSSelectorFromString(function);
if ([self respondsToSelector:sel]) {
[self performSelectorOnMainThread:sel withObject:nil waitUntilDone:YES];
// using invocation causes a SIGABORT because the try/catch block was not catching the exception.
// using perform selector fixed the problem (i.e., the try/catch block now correctly catches the exception, as expected)
}
else {
[appDelegate buildNewExceptionWithName:#"" andMessage:[NSString stringWithFormat:#"Object does not respond to selector %#", function]];
}
}
#catch (NSException * e) {
hasError = YES;
[self updateErrorMessage:[NSString stringWithFormat:#"Error processing command %#: %#", aCommand, [e reason]]];
}
#finally {
[function release];
[commandParts release];
}
if (hasError == YES) {
[appDelegate buildNewExceptionWithName:#"executeThisCommand" andMessage:self.errorMessage];
}
}
// this can return nil
-(NSString *)getQueryStringValue:(NSString *)name {
NSString *returnValue = nil;
if (queryString != nil) {
returnValue = [queryString objectForKey:[name lowercaseString]];
}
return returnValue;
}
when I try to share on twitter I do the following steps
if (!twitterEngine)
{
twitterEngine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate: self];
twitterEngine.consumerKey = kOAuthConsumerKey;
twitterEngine.consumerSecret = kOAuthConsumerSecret;
UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine: twitterEngine delegate: self];
if (controller)
[currentController presentModalViewController: controller animated: YES];
else
[self postTwitterStatus];
}
else {
[self postTwitterStatus];
}
after I got the twitter login view and after I put my pass and user and click add app
I get crash on asembly code, which I don't have an error message, but I saw something weiered also that in the delegates
- (void) OAuthTwitterController: (SA_OAuthTwitterController *) controller authenticatedWithUsername: (NSString *) username {
NSLog(#"Authenicated for %#", username);
[self postTwitterStatus];
}
I got that authintication succeeded but I get that the username == null
how can I solve this issue
Thanks
I did NOT get THIS error, but a similar one using Twitter+OAuth by Ben Gottlieb. If you are using this thing, it is required to use https and not http to connect to twitter.
go to: SA_OAuthTwitterEngine.m and change to:
- (SA_OAuthTwitterEngine *) initOAuthWithDelegate: (NSObject *) delegate {
if (self = (id) [super initWithDelegate: delegate]) {
//CHANGED FROM 'HTTP' TO 'HTTPS':
self.requestTokenURL = [NSURL URLWithString: #"https://twitter.com/oauth/request_token"];
self.accessTokenURL = [NSURL URLWithString: #"https://twitter.com/oauth/access_token"];
self.authorizeURL = [NSURL URLWithString: #"https://twitter.com/oauth/authorize"];
}
return self;
}
give it a try, i'm not sure it's the same as your problem..
Every thing looks fine to me. check with this example and see weather you are getting username in this.
I am developing an application which has a Twitter login. I have integrated MGTwitterEngine for that, and everything is working fine.
My problem is that when the user logs in, I need some details -- whatever info is returned by MGTwitterEngine for that logged-in user.
When I had a look in the library docs, I found the below delegate method which might give some user information, but when I log in ,this method never gets called.
- (void)userInfoReceived:(NSArray *)userInfo forRequest:(NSString *)connectionIdentifier {
NSLog(#"User Info Received: %#", userInfo);
}
Can somebody please suggest to me how to get the user's information from MGTwitterEngine or how I should use this method?
_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate:self];
_engine.consumerKey = #"PzkZj9g57ah2bcB58mD4Q";
_engine.consumerSecret = #"OvogWpara8xybjMUDGcLklOeZSF12xnYHLE37rel2g";
UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine: _engine delegate: self];
if (controller)
[self presentModalViewController: controller animated: YES];
else {
tweets = [[NSMutableArray alloc] init];
[self updateStream:nil];
}
I found the answer of my question:-
- (void) OAuthTwitterController: (SA_OAuthTwitterController *) controller authenticatedWithUsername: (NSString *) username {
NSLog(#"Authenticated with user %#", username);
[_engine getUserInformationFor:username];//this line to be added to get userInfo method called
}