How would I customize an SDK's UIAlertController? - ios

So, I already understand & can create my own custom UIAlertController (fonts, background color, text color, tint color, etc). So that is not the issue here.
The problem I'm running into is:
When I'm using an SDK file (ex. Facebook's SDK), I'm not able to find where inside of the SDK's Objective-C Headers, that the default UIAlertController is begin initiated (and presented). If I could, I'd like to replace the default with my own custom alert.
As of right now, I've already create my custom class with a static function that returns my custom UIAlertController for my VC to present. I've also already tested the implementation & it's works fine.
What I tried first was to manually search through Facebook's SDK Objective-C headers to find where the default UIAlertController is being initiated & then presented, but obviously with little luck...
Next thing I tried was using Xcode's Find Navigator to search for, "AlertController". Alas, nothing found inside the SDK's header files (maybe I should change the search scope?).
Last thing I tried was simply searching Google, but all I could find there was tutorials on how to create a custom UIAlertController (which I already know how to do).
Although in my current situation, I am using Facebook's SDK. Best answer would be one that's more general rather than specific (if possible). That way if I'm using a different/new SDK in the future, I can still apply your method. Thanks.

I do not recommend editing and forking FB's SDK, that would be a nightmare to maintain.
Instead you should look into objc method Swizzling, which allows you to dynamically replace the body of existing functions with your own implementation. I believe you could use this to change the behavior of all UIAlertControllers (not without risk).
https://nshipster.com/method-swizzling/

Related

How to use Swift Playgrounds-style code input keyboard/text field in normal text view?

I'm making an iPad app that lets me write swift code into a text box and save it to a document. It doesn't do any compilation or any complicated stuff like that, so I'm just looking for a way to format the code correctly in the text box (ex: code autocomplete, autoindent if possible, and maybe syntax highlighting). In short, I'd like my app's text field and keyboard to look similar to those of Swift Playgrounds.
If Apple's provided the code (or a built-in keyboard option that can do even some of this), I'd appreciate a link to it. Otherwise, how would I go about building a custom keyboard and text field (or at least disable the features like autocomplete that would get in the way)?
Thanks.
As far as I know the only way to do what you describe is to build a Swift Playgrounds app that presents a code editor window. Apple does provide documentation on creating third party iPad Swift playgrounds. I suggest looking it up on Apple's site.

iOS - Unexpected VoiceOver behavior on customized UIPickerView

I have a somewhat customized UIPickerView in my app. Basically I use pickerView:viewForRow:forComponent:reusingView returning a simple UILabel. As I started working on making the app more accessible, I noticed that VoiceOver reads label and adds, say, "3 of 300" (i.e. row number "of" total rows). This is not a desired behavior.
While trying to troubleshoot this, I found that if I use pickerView:titleForRow:forComponent instead of pickerView:viewForRow:forComponent:reusingView, without any other changes, then I get the desired behavior of VoiceOver simply reading the "title" of the selected row. I tested this on iOS 9.
Question is: how do I get UIPickerView back to the "normal" VoiceOver behavior, while still using pickerView:viewForRow:forComponent:reusingView? Thanks for any help!
I asked Apple support for help on this. The official reply was: "Our engineers have reviewed your request and have concluded that there is no supported way to achieve the desired functionality given the currently shipping system configurations". (For posterity - this was when the newest iOS version was 9.4). They suggested to file a request for new functionality, which I may do.
To solve this problem I went with the following workaround.
Created a base class almost identical to the class I had, but implementing only pickerView:titleForRow:forComponent and not pickerView:viewForRow:forComponent:reusingView. This class presents vanilla non-customized picker.
Created a subclass of that base class, now implementing pickerView:viewForRow:forComponent:reusingView. This class presents a fully customized picker.
In my code elsewhere used UIAccessibilityIsVoiceOverRunning() to create an object of base class when VoiceOver is on, and an object of the subclass otherwise
Thus when a user is running VoiceOver, they get a visually ugly picker, but one that is perfectly well-behaved in terms of accessibility (i.e. no row number announcements). Which is a perfectly reasonable "compromise" I think, since the user is basically guaranteed not to care about the visual appearances.
One fix will be to check if voice over is running
UIAccessibilityIsVoiceOverRunning()
If so use titleForRow otherwise use viewForRow. That way you don't degrade normal experience.

Get Instance of iOS Keyboard Without First Responder

My application uses Cordova so a number of functions are performed in the webview.
There is an object in one of my webviews that brings up the keyboard.
All the documentation and SO answers on changing the keyboard involve setting the values of the first responder. My problem is, on the native side, I do not have the first responder.
So my question is:
Can I get access to the keyboard object without the first responder, and if so how?
Swift/Obj-c answers welcome
You can use UIReturnKeyType for native controls, but unfortunately there is no way to control the return key for text fields within a webview. You might be able to figure out some sort of hacky solution though.
One idea is to manually modify the keyboard views. There's an Apache plugin that uses this to hide the form accessory bar on keyboards. You can see how they do it here. You would have to find the return key's view instead of the form bar though. Of course this isn't supported and is likely to break at some point.
Another option might be to use swizzling to modify UIWebView to use the UIReturnKeyType you want. You'd have to look into dumping the headers to find a possible starting point. This option also has the potential to break along with a chance Apple rejects your app.

How do I use a iOS custom keyboard extension as a programmable custom input view in Swift using storyboards or xibs

I want to design my own custom input view keyboard using a custom keyboard extension in swift. The existing Xcode 6.1 default set of keyboards do not fit my app needs. What I want is an enhanced number pad which I would modify, like in the Soulver app in the iOS app store. http://www.acqualia.com/soulver/iphone/
Ultimately I do not need a custom keyboard extension to offer to other apps but I do not mind if my app offers one. It looks to me like custom keyboards are the right place to start for for a custom input view keyboard.
I finally just about have digested constraints in the editor and would like to make use of a storyboard or xib.
I do need to be able to programmatically select the keyboard extension within the app.
The keyboard/custom view needs to be available to the app that contains it without activation in iOS settings.
Can this be done as an extension given the requirements, or can the custom keyboard extension be easily converted to a custom input view? Can you illustrate either one or point out sample Swift code I missed when searching? Thank you.
I am writing a keyboard extension in Swift right now and highly recommend not doing the same. Both Swift and the Keyboard Extension API are brand new, not well documented, creating significant learning curves, and both have significant bugs or weird implementation details to work around.
From the way you phrased your question it doesn't sound like you are very experienced in iOS development, and attempting to learn too many things at once is a recipe for disaster. If I could do my current project over, I would have done it in Objective C just to vastly simplify what I was learning.
But the good news is that you don't need the keyboard to run in other apps. This is good news because writing a custom input keyboard class within your own app is very simple and easy, and a great place to start. There is a good deal of existing documentation on how to do so, including this excellent post on stack overflow.
How do I retrieve keystrokes from a custom keyboard on an iOS app?
More detail:
The standard custom input view API in cocoa is very powerful, the one in the keyboard extension is almost entirely neutered, so you can do far more with a custom input view than you can with a keyboard Extension. To activate a keyboard extension requires getting the user to turn it on in their iPhone settings, there is no way around that and no way to pick which keyboard they choose within your app (other than to not allow custom keyboard extensions at all).
If you need to access the internet or data within your app for any reason (tracking usage information, activating an in-app purchase, accessing preferences) you must also convince your user to turn on "Full Access", which presents an incredibly scary alert that reads to users as if turning it on means you will be able to spy on them and steal their passwords
Getting back to why you don't want to use Swift in an extension. First, Objective C doesn't cause Xcode's code parser to crash many times a day, while developing in Swift does, sometimes crashing Xcode itself. In Objective C the debugger is almost always correct, in the current version of Swift often you can't see array or dictionary contents, sometimes what it shows is inaccurate, and when stepping through code often takes nonsensical routes. Developing in Objective Code means you won't have to update your code because of changes to Objective C itself, with Swift it's pretty much guaranteed they'll make significant syntax changes every major release (the last one in September did).
Developing a keyboard extension means sometimes your extension won't load for mysterious reasons, and you'll need to waste hours debugging why. My Swift keyboard extension is sometimes debugged solely with println() statements because I can't get the debugger to load. Since Apple's tools don't yet work well with Keyboard extensions, and also don't yet work well with Swift, using them together are multiplying your pain exponentially.
The end result is if you don't need to use this keyboard outside of your own application it's foolish to build it using the Keyboard extension API. If you do need to use the Keyboard extension API it's foolish to do it in Swift. This is written by a fool working full time trying to ship a Swift based keyboard extension.
If you want to use the standard cocoa custom input view API, then using Swift is probably fine. You will still have to deal with additional problems because it's such a young language, but you won't have lose so many days to mysterious, seemingly insoluble problems trying to figure out if they were caused by Swift, the Keyboard Extension API, failures in Xcode and it's debugger, or your own blunder.

The Correct Way to do Custom Keyboards in iOS?

I am looking to implement a custom toolbar that sits above my keyboard for a text field with some custom values. I've found a ton of tutorials online but this question is for asking what's the best way to do this.
This tutorial here http://blog.carbonfive.com/2012/03/12/customizing-the-ios-keyboard/ provides the most common way I can see across many tutorials, with creating a new subclass of UIView and using delegates to get that information across.
That's the commonality. However, I came across this tutorial which in the view controller itself just creates the toolbar, assigns it to the textField inputAccessory and it's good to go. In fact, I tried out the code and without any effort, I have now a custom keyboard.
http://easyplace.wordpress.com/2013/03/29/adding-custom-buttons-to-ios-keyboard/
This just seems a bit too easy to me though and I'd think the proper, Apple recommended way would be to create that UIView subclass and use delegates so that the view controller with the text fields acts as that delegate.
I'm specifically targeting iOS 7 in my app.
What are people's thoughts on this? If the second easier link is supported and is likely to pass Apple's guidelines, it's a good starting point but if delegates are the way to go, I'd rather look into that from the start.
Your thoughts will be appreciated.
There is no 'Apple Approved' way to do this, and its hard to believe anything you do here would get your app rejected. The custom keyboard you reference in your post has the iOS6 look and will appear outdated in an iOS6 app. I'll mention some iOS7 suggestions shortly, but the constant danger of mimicking what the System looks like today is guaranteed to look outdated later. In Mac/Cocoa development, Apple use to say at the WWDC that if you did something custom, make it look custom, don't take a standard Apple widget and try to duplicate it. But that advice is mostly ignored.
For iOS 7, you can create buttons that appear just like the system ones do (not pressed), but of course when someone presses them, they won't act like system buttons (i.e. animate up and "balloon" out.
I'm currently using a fantastic add-on keyboard, my fork of KOKeyboard (which uses the buttons above). This is such a cool addition. While the buttons look like iPad buttons, each one has 5 keys in it. By dragging to a corner you select one of the four, and tapping in the middle gives you that key. This might be overkill for your app, but it really helped me with mine. It looks like this:
(the Key / Value is in the under laying view.) The center control lets you move the cursor - its like a joy stick - and can be used to both move and select text. Amazing class, I wish I'd invented it!
Also, for any solution, you want to use a UIToolbar as the view holding the keys, for the reason that it supports blur of the view it overlays, just like the keyboard does. You can use the UIToolbar with no bar button items in it (if you want), and just add subviews. This is a "trick" I learned here, as there is no other way to get blur!
David's KOKeyboard (er…, the one he used - see David's comment below) looks nice. I suspect that he is using the official Apple mechanism:
inputAccessoryView
Typically, you'd set that value on a UITextView, but it can be any class that allows itself to become the first responder.
The provided view will be placed above the default apple keyboard.
It is correct that there is no official mechanism (and it is suggested against) to modify any system provided keyboard. You can add to it, as above. You can also entirely replace it for with your own mechanism. Apply will forgo the keyboard setting on your view and use a custom input mechanism if you set
inputView
set it to any view - Apple will still manage its appearance and dismissal as it does the custom keyboards.
Edit: Of course, iOS 8.x added significant access to keyboards. (not mentioned here)

Resources