Opening a link from a UITextView in a UIWebView in another ViewController - uiwebview

Ok so the project that I'm working on has a twitter feed that I put into a table I put the main part of the tweet in a UITextView. I want it to be able to open links in the text in a UIWebView. I managed to intercept the open url call by using the following.
#import "MyApplication.h"
#import "haydnboardAppDelegate.h"
#implementation MyApplication
- (BOOL)openURL:(NSURL *)url
{
return [self openURL:url forceOpenInSafari:NO];
}
-(BOOL)openURL: (NSURL *)url forceOpenInSafari:(BOOL)forceOpenInSafari
{
if(forceOpenInSafari)
{
// We're overriding our app trying to open this URL, so we'll let UIApplication federate this request back out
// through the normal channels. The return value states whether or not they were able to open the URL.
return [super openURL:url];
}
//
// Otherwise, we'll see if it is a request that we should let our app open.
BOOL couldWeOpenUrl = NO;
NSString* scheme = [url.scheme lowercaseString];
if([scheme compare:#"http"] == NSOrderedSame
|| [scheme compare:#"https"] == NSOrderedSame)
{
// TODO - Here you might also want to check for other conditions where you do not want your app opening URLs (e.g.
// Facebook authentication requests, OAUTH requests, etc)
// TODO - Update the cast below with the name of your AppDelegate
// Let's call the method you wrote on your AppDelegate to actually open the BrowserViewController
couldWeOpenUrl = [(haydnboardAppDelegate *)self.delegate openURL:url];
}
if(!couldWeOpenUrl)
{
return [super openURL:url];
}
else
{
return YES;
}
}
#end
I changed my main.h file as well to:
return UIApplicationMain(argc, argv, #"MyApplication", nil);
I tried to call the open url function in the code but it won't call the function at all it doesn't do anything when I click on the links in the TextView. What do I do to get it to call the function to change the view?
Edit:
Managed to get the Function in my app delegate to run but when it tries to push the view controller nothing happens. I get the error viewController not in window hierarchy so I decided to change the function so that it calls a function in the viewController but still nothing happens but there is no error message when pushViewController is called in the viewController. I found that this is because the navigationController = nil how do I fix this?

Related

How to setup react-native-navigation with react-native-siri-shortcut (rootView issue)

Need some guidance on how to get RNN to work with react-native-siri-shortcut.
Please bear with me if my post is too verbose as I'm a noob with xCode and objective C, so don't want to miss anything out.
So I've got a couple of questions/problems with trying to get the 2 libraries to work together:
1. Setting up the initialProperties with a RCTRootView
react-native-siri-shortcuts sets up the app in AppDelegate.m like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
// Check if the app launched with any shortcuts
BOOL launchedFromShortcut = [launchOptions objectForKey:#"UIApplicationLaunchOptionsUserActivityDictionaryKey"] != nil;
//Add a boolean to the initialProperties to let the app know you got the initial shortcut
NSDictionary *initialProperties = #{ #"launchedFromShortcut":#(launchedFromShortcut) };
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:#"doesthismatter"
initialProperties:initialProperties // Add the initial properties here
launchOptions:launchOptions];
...
}
In V2 of RNN, the rootView is not being used anymore, instead we just call:
[ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:launchOptions];
Therefore we are not able to pass the initialProperties through to the rootView.
2. Accessing the rootView in other parts of the code
Continuing on from the set up react-native-siri-shortcut:
// This method checks for shortcuts issued to the app
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler
{
UIViewController *viewController = [self.window rootViewController];
RCTRootView *rootView = (RCTRootView*) [viewController view];
// If the initial properties say the app launched from a shortcut (see above), tell the library about it.
if ([[rootView.appProperties objectForKey:#"launchedFromShortcut"] boolValue]) {
ShortcutsModule.initialUserActivity = userActivity;
rootView.appProperties = #{ #"launchedFromShortcut":#NO };
}
[ShortcutsModule onShortcutReceivedWithUserActivity:userActivity];
return YES;
}
Since RCTRootView isn't being used to register our app, will this part of the code work?
I've already searched the repo for issues related to initialProps and reactView and the few issues that I did find, never got answered and were closed due to inactivity.
Any help would be greatly appreciated.
Actually, searching for the launchedFromShortcut property on github I realised it's not consumed in the Javascript side. Therefore it's only usage is as flag to tell wether the app was launched from a shortcut and passing it to the RNN's RNNReactRootViewCreator seems unnecessary.
Removed that necessity the integration turned out to be pretty simple, we only need to add launchedFromShortcut = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey] != nil; to didFinishLaunchingWithOptions and check it's value on continueUserActivity.
The AppDelegate.m would look as follows:
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <ReactNativeNavigation/ReactNativeNavigation.h>
#import <RNSiriShortcuts/RNSiriShortcuts-Swift.h>
#implementation AppDelegate
BOOL launchedFromShortcut;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
launchedFromShortcut = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey] != nil;
[ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:launchOptions];
//
// Regular RNN bootstrap code omitted for brevity sake
//
return YES;
}
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler
{
if (launchedFromShortcut) {
ShortcutsModule.initialUserActivity = userActivity;
launchedFromShortcut = NO;
}
[ShortcutsModule onShortcutReceivedWithUserActivity:userActivity];
return YES;
}
#end

Cancel button in searchBar ios 8

tell me how to change the text on the Cancel button in searchBar?
Image: http://i.stack.imgur.com/8G1ZM.png
you can do that in this delegate method of UISearchBar
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
[theSearchBar setShowsCancelButton:YES animated:NO];
for (UIView *subView in theSearchBar.subviews){
if([subView isKindOfClass:[UIButton class]]){
[(UIButton*)subViewsetTitle:#"Button Title"forState:UIControlStateNormal];
}
}
}
UPDATE
after a long way searching the only way i got working in swift
is to set a custom UIBarButtonItem but you will need to show the search bar on the navigation
in ViewDidLoad()
self.searchDisplayController?.displaysSearchBarInNavigationBar = true
and in Delegate Method
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
var barButton = UIBarButtonItem(title: "Button Title", style: UIBarButtonItemStyle.Done, target: self, action: "here")
self.searchDisplayController?.navigationItem.rightBarButtonItem = barButton
}
i hope that works with you
«Another UPDATE
as you said in comments you will need to localize your application, in your case you will only need to localize the storyBoard
first navigate to your project settings then info, under localizations click the + button and add your own languages then check only StoryBoard
and now you have localized your app but you might don't see the changes until you remove the app and install it again or if the device language is set to english you will need to write 2 lines of code to change the language manually here is it
var str:NSString = "ar" // ar stands for arabic you put here you own language small character
var myArray:NSArray = [str]
NSUserDefaults.standardUserDefaults().setObject(myArray, forKey: "AppleLanguages")
and your button will looks like this
if you want to know more about localization see this Internationalization Tutorial for iOS [2014 Edition]
if you still need help till me :)
There are 2 solutions.
set key/value
[self.searchController.searchBar setValue:#"취소" forKey:#"_cancelButtonText"];
This solution works well, but you have to know that _cancelButtonText property is not public property.(You can not find this property in the documentation page.)
And It's not sure that this solution can pass the apple review process. So, use solution 2 please.
use a delegate.
You can change cancel button title(iOS8) within willPresentSearchController method.
(Assume that the searchBar is in tableView headerView)
- (void)willPresentSearchController:(UISearchController *)searchController{
// You have to set YES showsCancelButton.
// If not, you can not change your button title when this method called
// first time.
self.searchController.searchBar.showsCancelButton = YES;
UIView* view=self.searchController.searchBar.subviews[0];
for (UIView *subView in view.subviews) {
if ([subView isKindOfClass:[UIButton class]]) {
// solution 1
UIButton *cancelButton = (UIButton*)subView;
[cancelButton setTitle:NSLocalizedString(#"취소", nil) forState:UIControlStateNormal];
}
}
}
Also, You can get infomation about the searchBar through a view debugging tools in Xcode. Set a breakPoint at the willPresentSearchController method.
Good luck.
Actually, the cancel button is not a top view in the Search bar. You should search for it recursively.
-(UIButton*)findButtonInView:(UIView*)v{
for (UIView *subView in v.subviews){
if([subView isKindOfClass:[UIButton class]]){
return (UIButton*)subView;
}else if([subView isKindOfClass:[UIView class]]){
UIButton* btn = [self findButtonInView:subView];
if(btn){
return btn;
}
}
}
return nil;
}
//...
UIButton* searchButton = [self findButtonInView:self.searchBar];

Text field stays under the custom keyboard in UIWebView for iOS 8

I'm creating a web App for iOS and I have a custom keyboard. When I use the default keyboard, it immediately shows the keyboard and the text field is above the keyboard. I would have the same result if I change the keyboard to my custom keyboard. But the problem is for the time that I gives the focus to the text field when my custom keyboard is enabled. It has some delay to load and when it loads, text field stays under the keyboard. Here is my code for custom keybaord:
#import "KeyboardViewController.h"
#import "CustomKeyboardView.h"
#interface KeyboardViewController () <CustomKeyboardViewDelegate>
#property (nonatomic, strong) CustomKeyboardView *customKeyboardView;
#end
#implementation KeyboardViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.customKeyboardView = [[CustomKeyboardView alloc] init];
self.inputView = (UIInputView *) self.customKeyboardView;
self.customKeyboardView.delegate = self;
}
- (void)handleCharacter:(NSString *)character sender:(CustomKeyboardView *)sender
{
[self.textDocumentProxy insertText:character];
}
-(void)handelDelete:(CustomKeyboardView *)sender
{
[self.textDocumentProxy deleteBackward];
}
-(void)handleDismissKeyboard:(CustomKeyboardView *)sender
{
[self dismissKeyboard];
}
-(void)handleChangeKeyboard:(CustomKeyboardView *)sender
{
[self advanceToNextInputMode];
}
- (void)textWillChange:(id<UITextInput>)textInput {
// The app is about to change the document's contents. Perform any preparation here.
}
- (void)textDidChange:(id<UITextInput>)textInput {
// The app has just changed the document's contents, the document context has been updated.
[[NSNotificationCenter defaultCenter] postNotificationName:UITextViewTextDidChangeNotification object:textInput];
}
#end
The implementation of CustomKeyboardView class is similar to this library. Any help would be appreciated.
Try use the background threads, you have a delay because u execute a lot of code before you build your keyboard view first.

create a InApp browser implementation in iOS app

I have a requirement were in i have to create a view to display webpages with back, forward and refresh button in iOS app.
how to implement this functionality?
Use UIWebView.
Set the delegate to the view controller.
self.webView.delegate = self;
Other remarkable properties,
self.webView.scalesPageToFit = YES;
To load a URLRequest,
[self.webView loadRequest:theRequest];
or for only strings, use
[self.webView loadHTMLString:htmlString baseURL:nil];
And some delegates here. web view has its own history, you can use it by calling its back and forward methods.
#pragma mark - UIWebView delegate
// You can handle your own url scheme or let the web view handle it.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
NSLog(#"url=%#, %#, %#",
request.URL, request.URL.query, request.URL.host);
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
if ([request.URL.scheme compare:#"customescheme"] == NSOrderedSame) {
if ([request.URL.host compare:kSomethingDotCom] == NSOrderedSame) {
[self mymethod];
} else if ([request.URL.host compare:kAnotherDotCom] == NSOrderedSame) {
[self method2];
} else {
NSLog(#"Unsupported service.");
}
return NO;
}
}
return YES;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[_activityIndicator stopAnimating];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
[_activityIndicator stopAnimating];
[Resources showAlert:#"Could not load." withTitle:#"Error!"];
NSLog(#"%#", [error localizedDescription]);
}
#pragma mark - Actions
- (IBAction)didPressBackButton:(id)sender
{
[_webView goBack];
}
- (IBAction)didPressForwardButton:(id)sender
{
[_webView goForward];
}
Similarly you can have the stop method. To refresh reload the request again. Before going back or forward you can check the methods canGoBack or canGoForward.
See docs at, http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWebView_Class/Reference/Reference.html
It is a piece of cake, all you need is UIWebview component and its delegates and you need to create a custom navigation bar that is it.

Unwanted delay with UIGestureRecognizerStateEnded

I need to do some actions when the user starts touching the screen, moves a finger and then ends a touch. Touch began works fine, move as well, but touch end runs with a delay between 0.5-1 sec. Below there's a code:
-(id) init {
if (self = [super init]) {
//Adding a listener for catching touch events and get call back to selector method
[self addGestureListener:#selector(gestureCallback:)];
CCScene *scene = [CCScene node];
[scene addChild: self];
[[CCDirector sharedDirector] runWithScene:scene];
}
return self;
}
- (UIPanGestureRecognizer *)addGestureListener:(SEL)selector {
UIPanGestureRecognizer *recognizer = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:selector] autorelease];
[[[CCDirector sharedDirector] openGLView] addGestureRecognizer:recognizer];
return recognizer;
}
-(void) gestureCallback:(UIPanGestureRecognizer *) recognizer {
if (recognizer.state == UIGestureRecognizerStateBegan) {
NSLog(#"start");
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
NSLog(#"moved");
} else if (recognizer.state == UIGestureRecognizerStateEnded) {
NSLog(#"ended");
}
}
In the log (last 2 lines) I see this:
2012-10-15 11:29:03.609 App[6169:c07] moved
2012-10-15 11:29:04.267 App[6169:c07] ended
Any ideas?
Have a look at the GestureRecognizer's delaysTouchesEnded propery. From Apple's docs:
When the value of this property is YES (the default) and the receiver is analyzing touch events, the window suspends delivery of touch objects in the UITouchPhaseEnded phase to the attached view. If the gesture recognizer subsequently recognizes its gesture, these touch objects are cancelled (via a touchesCancelled:withEvent: message). If the gesture recognizer does not recognize its gesture, the window delivers these objects in an invocation of the view’s touchesEnded:withEvent: method. Set this property to NO to have touch objects in the UITouchPhaseEnded delivered to the view while the gesture recognizer is analyzing the same touches.
I am only getting this delay on the simulator. I do not see the same delay when I am using a physical device.

Resources