I was wanting to make an app similar to something like TextExpander, but I am not sure how you would intercept the text. As far as I can tell, I need to start with NSAccessability. Could anyone share some snippets, or at least point me in the right direction?
First off, you should be aware that, because of the sandboxing requirement, this isn't possible at all if you want to sell your app in the App Store.
If you don't intend to sandbox your app, you can use the NSEvent class method addGlobalMonitorForEventsMatchingMask: to create a global key event handler that gets called when keys are pressed in other apps (but not your own app, use addLocalMonitor... for that).
To actually insert snippets, like TextExpander, there are several ways. You can use the accessibility APIs, but that requires that the app(s) you're targeting support accessibility, which isn't always the case.
Another option is to use the Quartz Event Services (CGEvent) APIs which provide (among other things) a low-level method to simulate key events.
Edit: Nevermind. You're asking about Mac OS. I thought you were asking about iOS.
You should look at how TextExpander is used by other apps. The target app has to build in support for TE by making an object provided by TE a delegate of the text field. You can't run your code in someone else's app. They have to compile your code into their app. That's why there's a TextExpander SDK.
Once the TextExpander code is in the target app, the text field delegate gets the shared snippets by looking for snippets put into a shared pasteboard.
Related
I've been checking around the net to find some information or source code to achieve this. The thing is, that the Application I am developing uses a custom framework we are also developing. And our customer wants to add Push Notification support for the App.
But he wants the Framework we created to handle the Push Notifications (rather than the App). The following graph will explain a bit better the situation:
The problem is that the AppDelegate seems to be the only handling the Notifications from the OS, so the only solution I can think of is the App forwarding the notifications that come from the OS to the Framework. Any ideas or thoughts? Am I missing something?
Txs in advance
You will have to forward the calls. It should only require a few lines of code added to the appdelegate to interface with your framework though.
You could also do a hacky and more advanced approach where you swamp the IMP's of the AppDelegate methods and forward them through your framework. Just make sure you call the original imp once you're framework has done what it needs to. I wouldn't recommend this approach though as it may not remain stable for future ios versions.
Forwarding the calls is the way to go in my opinion.
Im new to iPhone development. I come from web-development/design and what bothers me in iPhone development is the unability for custom design... In other words... is there any way I could design my user interface (my view) with webkit so all my UI elemnts would be writen in html/css and logic in objective-c. I was thinking if there is a way I could triger some objective-c code when html button is pressed. Is there any way to do that (lets say via "localhost request" or I dont know) ?
BUT not with phonegap or similar, because then you just start writing your logic in javascript and i dont want that... I want my controller and model to be written in objective-c just the view module in html!
Look into PhoneGap. It has all of the abilities you specify, and can work on Android and other's too (of course you'd need to write the native logic in Java and other languages for that to work though).
The other responders are correct in that efficiency is a big concern, as all of your logic is gated on the Web/native interface. The UIWebView performs a LOT of it's duties on a single thread, and any of your interactions with it must as well.
If you really want to do this, however, there are solutions... Intercepting events from the UIWebView via delegate methods (such as shouldStartLoadWithRequest) that follow a protocol that you define can be used, but I'd suggest either doing everything in JS (trust me, it will actually be faster), or just bite the bullet and learn native iOS development more.
I'm currently using BWToolkit, does anyone know if there are any steps that need to be taken before submitting to the app store (as far as licensing)? Do I need to put any disclaimers anywhere etc? I know it's BSD licensed but I don't want to have my app rejected because I missed a simple legal step.. Any help?
I don't think that NSGod is right.
You may want to read this and/or that.
You are not going to like this answer.
You will not be able to use the BWToolkit.framework as-is. Some of its classes rely on private APIs which Apple has strictly forbidden for apps that are submitted to the app store.
For example, the developer ran a tool called class-dump on the AppKit.framework Mach-O object and generated the .h files for 4 secret classes: NSTokenAttachment (an NSTextAttachment subclass), NSTokenAttachmentCell (an NSTextAttachmentCell subclass), NSWindow (NSTimeMachineSupport), some additional methods on NSWindow, and NSCustomView.
I'm not that familiar with the inner workings of the framework, but depending on what classes you've made use of, it may be possible to create a custom build of the framework from the source that doesn't include the private APIs. Or, you could just include the source files for the classes you use in your project (provided of course that they don't rely on private APIs).
What particular classes did you make use of? If you used BWSplitView, you might look into using RBSplitView. (I talked to Rainer and have confirmed that there's no private APIs used in it, so you'd be okay).
I was wondering if and in how many way an app can access specific funcions of another app.
for example
open an url in safari/firefox/chrome
run a javascript in current browser-tab
play/pause itunes
rename selected files in Finder
I am aware of the existence of applescript but i was wondering if that's the only way i have to interact with those apps and others
thanks
There are three main ways an app exposes its function to the outside world.
One is by supporting an URL protocol. To open an URL, just use NSWorkspace. There are many methods; if an app registers a specific protocol like x-my-app://some-work, you can just do
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:#"x-my-app://some-work"] ];
If you want to open an URL whose protocol (say http) is supported by many apps and if you want to specify which app to use, use openURLs:withAppBundleIdentifier:options:additionalEventParamDescriptor:launchIdentifiers:
.
Another is the System Services. With this, an app can add entries in the Service menu and in the context menu of other apps; you can also call it programmatically.
Otherwise, it's via Apple events. Applescript is one way to deal with them, but not the only one. It's just a language to issue Apple events. There are many ways to deal with Apple events from Cocoa, see this detailed document by Apple.
Basically, an app can export its internal as an object-oriented manner (which is not just its Objective-C hierarchy; you can control how much of its internal objects and methods you expose, etc.) by an sdef file. Then, another app can use this object-oriented system via Apple events.
To send and receive Apple events, you can of course construct them by hand, but you can use higher-level objects like
Applescript via NSAppleScript
Scripting Bridge
or AppScript.
To learn what kind of aspects an app exposes, just open the AppleScript Editor and choose the menu File → Open Dictionary, and choose an app.
Now, it's rather hard to use features of an app which the app does not expose via any of these methods. You still have a few workaround.
UI Scripting. This is done by sending Apple Events to a headless app called System Events which is one of the core program in OS X. This way, you can programmatically emulate clicking a button, choosing a menu, etc. of another app. So, almost whatever you can do using GUI with another app can be done programmatically from another app. To see the hierarchy of UI objects accessible from UI scripting, use a utility which comes with XCode tools, at
/Developer/Applications/Utilites/Accessibility Tools/Accessibility Inspector.app
This is very rudimentary but does the job; if you regularly use UI scripting, consider obtaining UI browser, as Zygmunt suggests.
Finally, if you want to use a non-GUI non-exposed feature of another app, you can inject a code into another app.
Just expanding on Yuji's answer. If you were forced to go the UI scripting path, there's a nice application to analyze the interface - hxxp://pfiddlesoft.com/uibrowser/. However, the examples you mentioned should expose some APIs.
I might also recommend using Sikuli hxxp://groups.csail.mit.edu/uid/sikuli/ as an IDE to script around user interface robustly.
For some applications usually coming from GNU/Linux there is D-BUS hxxp://en.wikipedia.org/wiki/D-Bus - although I haven't used it on a Mac on my own yet. And let me also quote Wikipedia about Cocoa "It is one of five major APIs available for Mac OS X; the others are Carbon, POSIX (for the BSD environment), X11 and Java." hxxp://en.wikipedia.org/wiki/Cocoa_%28API%29 That's just a loose tip for further exploration as Yuji has already explained Apple events that are key to your question.
For the application I am writing, I need to access some other applications' items, for which Applescript seems the best way to go. I have been using the Appscript framework, which worked well, because it allowed me to thread it and not make my app lock up when an Applescript was taking a while. However, now I am attempting to make my application 64 bit compatible, and it seems like the Appscript framework does not support 64 bit. Is there a "good" way to use Applescript in Cocoa that will not lock up my application, but still give me the full control I need?
--firen
It seems like SBApplication should work, but I haven't used it before.
According to #cocoadevcentral:
SBApplication: use to make cross-application scripting calls with Objective-C instead of AppleScript. Ex: get current iTunes track.
Here is is the excerpt from the documentation:
The SBApplication class provides a mechanism enabling an Objective-C program to send Apple events to a scriptable application and receive Apple events in response. It thereby makes it possible for that program to control the application and exchange data with it. Scripting Bridge works by bridging data types between Apple event descriptors and Cocoa objects.
Although SBApplication includes methods that manually send and process Apple events, you should never have to call these methods directly. Instead, subclasses of SBApplication implement application-specific methods that handle the sending of Apple events automatically.
For example, if you wanted to get the current iTunes track, you can simply use the currentTrack method of the dynamically defined subclass for the iTunes application—which handles the details of sending the Apple event for you—rather than figuring out the more complicated, low-level alternative:
[iTunes propertyWithCode:'pTrk'];
If you do need to send Apple events manually, consider using the NSAppleEventDescriptor class.
Hope that helps!
As Blaenk mentioned Scripting Bridge may well be the way to go, although it can prove somewhat inefficient if you have to iterating through large arrays etc.
The simplest way to run an Applescript in Cocoa is using NSAppleScript.
Apple has some pretty good examples, which I found useful when I needed to do something similar. There are three articles you might want to take a look at. They all contain some sample code, which I always find very useful.
A Few Examples of using Scripting Bridge
Performance & Optimisation with Scripting Bridge
NSAppleScript Technote/Example
I created a gist with the full URLs as I can't post more than one link, what with being a newbie and all.
http://gist.github.com/130146
it seems like the Appscript framework does not support 64 bit.
Should work. Make sure you set the correct architectures and SDK (64-bit requires 10.5) in the Xcode project. File a bug report if you have a specific problem.