Default implementation of splitViewController:shouldHideViewController:inOrientation: - objective-c

Hi, the default implementation of splitViewController:shouldHideViewController:inOrientation: method in the UISplitViewControllerDelegate protocol is as given below. -
return UIInterfaceOrientationIsPortrait(orientation);
How to locate this implementation in Xcode? I can go over to the declaration of this method in UISplitViewController.h file in Xcode, but not the implementation. So how does one know the default implementation of any built-in method?

The method shouldHideViewController was only introduced in iOS 5.
If your target build settings 'deployment target' are set to anything before iOS 5, the Xcode editor won't offer you this method through autocompletion (or any other that aren't available to your target iOS version).
To check the iOS Deployment Target in Xcode, select your target, and look under the Summary tab. Make sure this is at least iOS 5.
For some methods only introduced in iOS, such as setTintColor methods, you can dynamically check the version in your code, but in this example (shouldHideViewController), I think you're going to want to choose to use it, and go with iOS 5 only, or choose to not use it and use popovers.

Related

How to include WebView in Objective C without crashing

When I include a WebView component on a form in my Objective C project in XCode7 for a Cocoa application on OSX and try to compile, it compiles and then has a runtime error of:
NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (WebView) for key (NS.objects); the class may be defined in source code or a library that is not linked
What's the fix?
In XCode7, if you use a WebView widget, you have to add the framework. Go to the Project Navigator and click the first icon, which is your project icon. In the middle of your screen on that IDE then, you'll see General > Linked Frameworks and Libraries. Click the + and add WebKit.framework. Now when you compile, the linkage will be there and it will work.
The drawback I think is that it says it's a 10.11 component, and so if I want to deploy my app to a 10.9 system or 10.10 system, it won't work. I'm not 100% certain of this without testing, however, but do have this hunch.
ADDENDUM:
I set my project to be 10.8 compliant and then found I can run just fine on 10.8 all the way to the latest OSX.

Xcode 6 does not localize Interface Builder

Xcode 6 Beta 4 using Swift.
I use localization in my project and I have experience in localization from Xcode 5.
Localization in program code using NSLocalizedString() works fine.
Localization of Info.plist strings work fine, too.
When it comes to localize the strings from Interface Builder it only works in Interface Builder preview but not in simulator and not on my device (iPhone 5S).
Am I missing something or can anyone confirm this as a bug in in Xcode 6 Beta 4?
It seems like the problem is with the size classes.
If "Use Size Classes" checkbox is enabled for storyboard, the Xcode actually generates 3 versions of it ("<Name>.storyboard", "<Name>~ipad.storyboard" and "<Name>~iphone.storyboard").
So iOS just tries to load .strings file which name matches the name of active storyboard (<Name>~iphone.strings in case app is running on the iPhone). And being not able to find that file, it falls back to Base localization.
There are a couple of ways to work around this bug:
The most obvious one. Just disable size classes for the storyboard.
If you need size classes, you can add localized <Name>~iphone.strings and <Name>~ipad.strings files to the project manualy and copy your translations over.
Apple release notes of XCode 6 GM covers this :
Localization:
A storyboard or XIB will not localize correctly if all of the following three conditions are true:
The storyboard or XIB uses size classes.
The base localization and the build target are set to Universal.
The build targets iOS 7.0.

Some Parse methods not working in iOS SDK

I added the Parse SDK today (1.2.15) to an existing project which targets iOS7 and is built in Xcode5. I followed the instructions on https://parse.com/apps/quickstart#ios/native/existing exactly. Some things work, like creating and saving a PFObject. Certain functions however cannot be found by the compiler. For instance [PFUser enableAutomaticUser]; generates the error
AppDelegate.m:21:13: No known class method for selector 'enableAutomaticUser'
and [PFAnalytics trackAppOpenedWithLaunchOptions:launchOptions]; generates the error
AppDelegate.m:20:6: Use of undeclared identifier 'PFAnalytics'
Are the docs out of date and have these methods moved? I have tried restarting Xcode and cleaning my project. I can see the PFAnalytics.h file if I expand Parse.Framework in Xcode, and when I look at PFUser.h I can see a declaration of enableAutomaticUser;. Why can Xcode see some Parse classes and methods but not others?
My problem was that Framework Search Paths in Build Settings contained two directories, and one was invalid, resulting in this very strange behavior where some methods in Parse worked and others didn't.

How to create Apple mail plugin

I'm going to create a mail plugin for the OS X Mail.app application for some additional features.
I have no idea where to start as there is no official documentation for plugins.
Can anyone please help me, how can I start the project.
Is there any initial link or tutorial, please suggest?
As noted, writing Apple Mail plugins is not straightforward, since it only has a private plugin API, which is entirely undocumented and can change with any new version of Mail.app. The best code example is GPGMail, which is open source & still active (already working on Yosemite support). Here is what I successfully did to get started (will put it up on github once finished):
How to build a minimal Apple Mail plugin (as of Mavericks & Xcode 6.0.1)
you need to create an OSX "Bundle" project in XCode
wrapper extension is mailbundle (under Packaging in the project Build settings)
a bundle needs to be stored under ~/Library/Mail/Bundles (as Build Phase add a Copy Files action with that as absolute path destination and the *.mailbundle from your build/ folder as item to copy)
for development, I have set up /Applications/Mail.app as executable in my run scheme, so that Run in XCode will build it, copy the bundle and start mail; note that at this point you'll get an error from Mail that your plugin cannot be started and was disabled
you need to provide a list of SupportedPluginCompatibilityUUIDs in the Info.plist, I stole it from GPGMail, these change with new Mail/OSX versions
use class-dump to generate the header files from Mail.app's private API
starting point is MVMailBundle, which you have to inherit from and which has a registerBundle method to hook you in
I extracted that from the huge generated header file in a small MVMailBundle.h header to include where needed (as done by GPGMail)
create a new class MyMailBundle, inheriting from NSObject
it needs an initialize method
and set it as "Principle class" in the Info.plist so that it gets run when the bundle is loaded by Mail.app
#import <Cocoa/Cocoa.h>
#interface MyMailBundle : NSObject
+ (void)initialize;
#end
initialize implementation: previously, you could use the simple way and directly inherit as done in Letterbox, however, since 64-bit runtimes of Objective-C you have to use the dynamic way as done by GPGMail:
using NSClassFromString to dynamically get the MVMailBundle class
and class_setSuperclass from <objc/runtime.h> to have your own class inherit from it
and then call registerBundle on it casted as MVMailBundle (requires include of MVMailBundle.h)
#import <objc/runtime.h>
#import "MVMailBundle.h"
#import "MyMailBundle.h"
#implementation MyMailBundle
+ (void)initialize
{
NSLog(#"Loading MyMail plugin...");
// since 64-bit objective-c runtimes, you apparently can't load
// symbols directly (i.e. through class inheritance) and have to
// resort to NSClassFromString
Class mvMailBundleClass = NSClassFromString(#"MVMailBundle");
// If this class is not available that means Mail.app
// doesn't allow plugins anymore or has changed the API
if (!mvMailBundleClass)
return;
// dynamically change super class hierarchy
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
class_setSuperclass([self class], mvMailBundleClass);
#pragma GCC diagnostic pop
// register our plugin bundle in mail
[[((MyMailBundle *)self) class] registerBundle];
NSLog(#"Done registering MyMail plugin.");
}
#end
add some NSLog logging calls to verify the right thing is happening, they'll be visible in XCode's console when running/debugging Mail.app from within XCode or alternatively in the system logs of Console.app
This should successfully run the plugin in Mail with no error!
The next steps involve crazy things like MethodSwizzling and ClassPosing to modify Mail's behavior, where GPGMail can be a helpful example. (Haven't been there myself yet)
For reference, here are some of the resources that helped me:
GPGMail
Adam Nash: Getting Ready to Write an Apple Mail.app Plug-in for Mac OS X - some good links, but apparently he never finished the project, so no code
James R. Eagan: Demystifying Mail.app Plugins on Leopard - using PyObjC to write a plugin in Python, explains the basic mechansims, very useful
Aaron Harnly: Mail Plugin Template - for XCode 2 I think, unfortunately the template (download a zip) doesn't work as template in Xcode anymore, but the code is still useful to look at
Aaron Harnly: Letterbox sources - from the same guy, but also from 2007, very outdated; contains a readme from the template, though it doesn't really help if you can't use the template.
There is no official supported way to build such a tool - you need to start trying to hook in to Mail.app without any official support.
If you want to persist on this sort of thing, then you'll need to understand how Mail.app internals work, which is a bunch of using the debugger and class dump to inspect libraries in other apps:
https://github.com/nygard/class-dump
You'll probably also want a way to inject code into other applications, for example:
https://github.com/rentzsch/mach_inject
And every time Apple update Mail.app you'll potentially need to redo everything :)

How to Write OS X Finder plugin

I'm looking for a guide or sample code for writing Mac OS X Finder plugins? It would like to know how to do some simple actions:
adding image overlayers to icons
adding context menu items
listen to file changes
I found the following two resources:
Writing Contextual Menu Plugins for OS X: An outdated document from 2002 that uses the COM API targeting Mac OS X 8/9.
SCPlugin: Open-source SVN Mac application that includes a Finder plug-in.
I am tempted to review the SCPlugin code, but was hoping to find an easier sample to digest.
The Finder Icon Overlay example project represents a small and very basic but actually working example of the answer below.
https://github.com/lesnie/Finder-Icon-Overlay
I know this is so old, but some may be still interested in topic (?)
Here is what I have it done under Leopard (10.6). At first proper Finder's headers are needed. Use class-dump tool to get it. Then write your code as a SIMBL plugin (refer to documentation how to do it), swizzling some methods. For instance to draw something over icon in ListView, drawIconWithFrame: method of TIconAndTextCell method must be overriden.
Here's the code for method swizzling:
+ (void) Plugin_load
{
Method old, new;
Class self_class = [self class];
Class finder_class = [objc_getClass("TIconAndTextCell") class];
class_addMethod(finder_class, #selector(FT_drawIconWithFrame:),
class_getMethodImplementation(self_class, #selector(FT_drawIconWithFrame:)),"v#:{CGRect={CGPoint=dd}{CGSize=dd}}");
old = class_getInstanceMethod(finder_class, #selector(drawIconWithFrame:));
new = class_getInstanceMethod(finder_class, #selector(FT_drawIconWithFrame:));
method_exchangeImplementations(old, new);
}
I am overriding "drawIconWithFrame:" method with my method "FT_drawIconWithFrame:". Below is sample implementation for this method.
- (void) FT_drawIconWithFrame:(struct CGRect)arg1
{
[self FT_drawIconWithFrame:arg1];
if ([self respondsToSelector:#selector(node)]) {
if ([[[[NSClassFromString(#"FINode") nodeWithFENode:[(TNodeIconAndNameCell *)self node]] fullPath] lastPathComponent] hasPrefix:#"A"])
[myPrettyIconOverlayImage drawInRect:NSMakeRect(arg1.origin.x, arg1.origin.y, arg1.size.height, arg1.size.height) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
}
}
Essentially it draws "myPrettyIconOverlayImage" over every icon for file with filename starts with letter "A". This logic is up to you.
Pay attention to this line: [self FT_drawIconWithFrame:arg1]; this is how to call 'super' in order to get normal icon and name etc. I know, looks weird, like loop, but actually it isn't. Then wrap in into SIMBL plugin, install SIMBL and ...run.
Due to changes in Lion some work have to be done from scratch (make new "Finder.h" file with all declarations needed in it, find proper classess and methods to override), but this technique still works.
Happy hacking!
For Yosemite (MacOS 10.10 & newer), you can use Apple's FinderSync framework, which allows Finder extensions to:
Express interest in specific folder hierarchies
Provide "badges" to
indicate the status of items inside those hierarchies
Provide dynamic
menu items in Finder contextual menus, when the selected items (or
the window target) are in those hierarchies
Provide a Toolbar Item
that displays a menu with dynamic items (even if the selection is
unrelated)
Sadly, programming a Finder plugin actually does still require getting your hands dirty with COM. If you look at the SCFinderPlugin subproject of the SCPlugin project, you will find that it follows exactly the same techniques outlined in your first link, including setting up a vtable for COM, writing AddRef/ReleaseRef functions, and so on. Writing a plugin, where you're simultaneously managing old-school Carbon memory management, COM-style memory management, and Cocoa/new-style Carbon memory management, can be an incredible pain—and that totally ignores the fact that you'll be interacting in three or more radically different APIs, with different naming conventions and calling semantics. Calling the situation hysterically poor would be a vast understatement.
On the bright side, the Finder in Mac OS X 10.6 Snow Leopard has been fully rewritten in Cocoa--and with that come vastly superior plugin interfaces. If you are lucky enough to be in a situation where you can actually only target Snow Leopard, you probably should grab an ADC Premier or higher membership, download the prerelease builds, and code against that. Besides, your plugin may not work on 10.6 anyway without a Cocoa rewrite, so it might make good sense to take a look at Snow Leopard before it gets released, regardless.
There is no official or supported plugin system for the Finder. Starting with OS X 10.6, you will need to inject code into the Finder process and override objective C methods in the Finder process.
I've done this for a proprietary project. I can tell you that the reason that there are no examples or tutorials for this is because it is a significantly difficult and time consuming development task. For this reason, there's plenty of incentive for individuals or organizations who have accomplished this to guard the specifics of their process closely.
If there's any way at all that you can accomplish your goal using the Services API, do it. Writing a Finder plugin will take you 1-2 solid months of painstaking development and reasonably deep knowledge of C and Objective-C internals.
If you're still convinced that you want do to this, grab mach_star. Good luck.
As far as I know, there's no official plugin architecture for the Finder. You may be able to add image overlays to icons through an external application without having to hook into the Finder, although it wouldn't be on the fly. I don't think there is a way to add contextual menu items aside from Folder Actions and Automator. You can also look into writing an external application to monitor File System changes using the FSEvents API.
Here's a completed solution for Finder icon badges and contextual menus in Lion and Mountain Lion using the techniques described by Les Nie.
Liferay Nativity provides a scripting bundle that will swizzle the relevant Finder methods and a Java client for setting the icons and context menus. It also includes equivalent projects for Windows and Linux.
The project is open source under LGPL, so feel free to contribute any bug fixes or improvements!
The pickings are slim; it's never been really clear to me whether Finder Plugins are actually supported. A few more leads, though:
SampleCMPlugIn - Carbon-based of course, since so is Finder. Note that almost any Finder plugin is probably going to stop working with 10.6.
Automator can save things as a "Finder plugin." It's a more supported version of what you're discussing, but of course less flexible.
To add Finder/File browser icon overlays and context menus, in a cross-platform manner, from Java, take a look at the Liferay Nativity library.
I also make mention of this in another SO post, which also contains links to Apple's 'Finder Sync' docs and API.