MFMessageComposeViewController issues in iOS8 - uiviewcontroller

I've run into a strange bug with MFMessageComposeViewController in iOS8, that is only reproducible within my own app. It's affecting the app right now in the App Store, built with the iOS7 SDK running on iOS8, as well with the iOS8 SDK in my own test devices (iPhone and iPad)
The issue is that when I bring up the MFMessageComposeViewController, it shows me the controller without a text field or a Send button anymore. I haven't changed my code between iOS7 and iOS8, so not sure why this is happening. The code itself is very simple:
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.messageComposeDelegate = self;
[picker setRecipients: #[#"5551112222"]];
[picker setBody: #"Test"];
[self presentViewController:picker animated:YES completion: ^{
NSLog(#"MFMessageComposeViewController completion handler");
}];
This is what it looks like:
Any ideas for what I can try for a work-around? I've tried setting the textField and recipients in the completion handler; tried calling becomeFirstResponder on the top-most view controller; no luck. Again, this was/is working perfectly fine in iOS7.
EDIT:
So I found Apple's own sample code for MFMessageComposeViewController from this link: https://developer.apple.com/library/ios/samplecode/MessageComposer/Listings/MessageComposerViewController_m.html
When I build and run this app, the MFMessageComposeViewController shows up perfectly, and pre-filling the phone number and text fields works as well. But when I copy their files into my app, make their storyboard my main storyboard, press the "Compose SMS" button and I see the same exact problem!
What is going on here? Very confused. Could it be some configuration in my own app that is preventing the message composer from displaying correctly?

Finally, after tearing down most of my app, I was able to figure out the issue. Turns out, I was overriding a UIViewController system method in a category (instead of sub-classing):
#implementation UIViewController (UIViewController_Additions)
-(BOOL)canBecomeFirstResponder {
return YES;
}
This has been working fine till iOS7, but something must have changed internally in iOS8 and `MFMessageComposeViewController. A case of the "4-year-old-hack coming to bite you in the ass"
This practice is discouraged by Apple as well, according to this link (though I couldn't find the original Apple source): https://stackoverflow.com/a/14259595/145552

Related

WKWebView Canvas issue. Links inside canvas aren't doing anything

I'm having an issue with WKWebview.
I'm loading a canvas from html into the Webview.
This is the link:
https://cdn-factory.marketjs.com/en/color-fill-playable-ad-demo/index.html
it runs perfectly the html game loads and everything seems to be okay, the touch events are working when you play the mini game tough there is a button "install now"
that should open the app store url and when i tap it nothing happens.
On browser it works and i have tried few of those games but nothings works.
Any advise? the webview preference allowjs and allow inline media are set to true.
Aside that i couldn't find any info on it.
Help is appreciated :D thanks !
iOS: 13.4.1
Swift: 5
iPhone xs max
Okay i figured it out.
In case someone will bash into it in the future.
So the webpage used:
window.open("http://asdfsadfsda")
javascript code to open the url in a new window.
WKWebview wont do anything unless you will implement the WKUIDelegate and the method
webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration,
for navigationAction: WKNavigationAction,
windowFeatures: WKWindowFeatures) -> WKWebView?;
another important thing in order to make this method to get called is to set in the webview preferences like this:
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
configuration.allowsInlineMediaPlayback = true;
configuration.preferences.javaScriptCanOpenWindowsAutomatically = true
configuration.preferences.javaScriptEnabled = true
And then you can handle the new page opening in the delegate method.
If you still want a new window you should create a new webview and return it in the delegate method.
In my case it was to do nothing and just take the url etc..
so i returned nil.
Good luck :)

When using React-native, why does my iPhone or emulator hang with a white screen unless Chrome Debugging is on?

When running an app using react-native 0.4.4, I see that the app will hang the iOS emulator or the phone unless Chrome Debugging is turned on. Does anyone have an idea what is going on?
I'm not getting any errors at all on Chrome when I open it. I have noticed that the "sample" React-native app doesn't have any problems when running without Chrome, so it seems like it's something within my own code, but I have no idea what!
I took the react-native example code and started adding code from my existing project to it one file at a time until I found the offending line.
Here it is:
render: function () {
let buttonStyle = styles.disabledLgButton;
let buttonTextStyle = styles.disabledLgButtonText;
if (this.state.submitEnabled) {
buttonStyle = styles.activeLgButton;
buttonTextStyle = styles.activeLgButtonText;
}
It took me a while to figure it out, even when I was staring at the code that was breaking things.
I have gotten into the bad(?) habit of using certain ecmascript 6 features such as let. Chrome will deal with let without any difficulty, but the JavaScript engine on the phone chokes. As soon as I changed those let lines to var, the phone was happy rendering on its own without Chrome's help.

Using the Google Maps SDK in views other than the main view

I am trying to use the Google Maps SDK for iOS in a subview of the main view which I created in the storyboard and linked to the view controller via an IBOutlet (I called it extraView, subclassed from UIView). When I follow the steps in the SDK getting started guide, the SDK works just fine, but it uses the uppermost view in the hierarchy (the main view), which I don't want. I want my map to be in a smaller portion of the screen and use the rest of the screen for something else. When I attempt to assign the mapView_ object (see the getting started guide) to self.extraView instead of self.view, the whole screen is black and I get an error in the console output:
"Application windows are expected to have a root view controller at the end of application launch"
Has anyone else figured this out? I can't find anything in the documentation and the sample code Google provides does not use a storyboard.
Here's how...
add a UIView into the view controller where you're working
set it's class to be GMSMapView in the identity inspector.
Then control-drag it to your code as you would for any other outlet.
You can lazily instantiate it in its setter...
- (void) setMapView:(GMSMapView *)mapView {
if (!mapView) {
mapView = [[GMSMapView alloc] initWithFrame:mapView.bounds];
}
_mapView = mapView;
}
To display a map Google's sample code becomes...
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:1.285
longitude:103.848
zoom:12];
self.mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
I solved my problem just removing the loadview code that i took from the example.
Just adding a view as sberley said should works.
just on thing more, on the identity inspector, that attribute that you have to change is class, at least it is on xcode 4.5

UITabbarController dismiss modal UINavigationController

I got a very interesting problem here. My iPhone app has an UITabbarController as rootViewController in the AppDelegate.
If the app is opened the first time, it must be configured basically. For this purpose I create an UINavigationController and tell the tabbarController to present it modally:
firstRun = [[firstRunViewController alloc] init];
navCtrl = [[UINavigationController alloc] initWithRootViewController:firstRun];
[[self tabBarController] presentModalViewController:navCtrl animated:NO];
When the configuration is done, I'd like to get rid of the firstRunViewController. I'm using this technique very often, using -dismissModalViewControllerAnimated:.
But in this constellation this doesn't work. It doesn't matter from what controller I'm calling the dismiss.
I tried it via the tabbarController, the rootViewController, the currently active viewController, of cause self and several other controllers.
EVERY TIME I call -dismissModalViewControllerAnimated: I get this exception:
'UIViewControllerHierarchyInconsistency', reason: 'presentedViewController for controller is itself on dismiss for: <UINavigationController:…
Can anybody help? Thanks in advance, with kind regards, Julian
EDIT
In my AppDelegate I'm using a UITabbarController as rootViewController for the main window:
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
Then I'm creating an UINavigationController and tell the UITabbarController to present the modalViewController:
UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:firstRun];
[[self tabBarController] presentModalViewController:navCtrl animated:NO];
When I now call -dismissModalViewControllerAnimated: on the firstViewController I'm getting the error from above.
In my opinion you are abusing UITabbarController. This class, even though a subclass of UIViewController, does not really use much of the UIViewController infrastructure.
What you want is a slight extension of what you have now. Create a new UIViewController subclass in your appDelegate, and add it as the single object to an array, and set the tabBar's viewControllers to this array. Set your subclass' hidesBottomBarWhenPushed to YES so it hides the tab bar when it becomes visible.
Now your app will launch and your UIViewController subclass will become the frontmost view. You can make this view the one you wanted to present modally, or you can present that view from your subclass using some kind of animation. Oh, and if you use the launch view as the background image for your subclass, you can really make this a smooth transition - I do this now.
When your modal view is done, then you can instantiate whatever views you want to then display, and set the UITabBarController to use those views with tabBarController.viewControllers (or the animated version). Poof, you UIViewController will get replaces (and under ARC just disappear).
I don't have a chance to test my hypothesis, but I suspect that this issue could depend on the fact that you are presenting the modal view too early, whereby too early means before the main window has had the chance to set up the tab bar controller. So, I would suggest this changes:
create a method to instantiate your navigation controller:
- (void)initializeAndPresentNavigationController {
UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:firstRun];
[[self tabBarController] presentModalViewController:navCtrl animated:NO];
}
instead of presenting the navigation controller directly from appDidFinishLaunching, call the above method asynchronously:
[self performSelector:#selector(initializeAndPresentNavigationController) withObject:nil afterDelay:0.0];
Here the trick of calling the method as I do in 2 is that the call to initializeAndPresentNavigationController will be simply pushed on the main loop, and executed after your app has had the possibility to build its initial UI.
Hope it works for you.
I finally found the answer myself!
I just couldn't see the wood for the trees! I'm quite happy right now! :)
I did really silly things: In the last viewController of the setup viewControllers I had to change the tabars viewControllers corresponding to whether the user is administrator or not. So I did:
appDelegate.tabBarController.viewControllers = [NSArray arrayWithObjects:appDelegate.readState,
appDelegate.navCtrl,
appDelegate.settings, nil];
You can see that I was adding the AppDelegate's "navCtrl" to the tabbar's viewControllers. So I was trying to dismiss a viewController I just added to the parentViewControllers (UITabbarController) sub-controllers.
Dismissing something I want to present just in the same moment is NOT advisable! :))

Crash when Adding a WebView to a Multiview Tab Bar App

I am new to this and working thru a "teach yourself book". I have two questions. How to trouble-shoot this in the future and how to get the darn thing to work now.
I have a simple three Tab Bar app that points to three UIViewController. The three views work fine until I add a Webview to one of the XIBs. As soon as I bring up the view with the WebView included in the simulator, I am kicked out of the App.
The Debugger console says"'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key bannerView.'" I don't know what that means.
.h file code....
#interface ConvNavController : UIViewController {
IBOutlet UIWebView *bannerView;
}
-(IBAction)loadbannerView:(id)sender;
#property (nonatomic, retain)IBOutlet UIWebView *bannerView;
=========
.m file code
-(IBAction)loadbannerView:(id)sender{
NSURL *bannerURL;
NSString *bannerURLString;
bannerURLString=[[NSString alloc] initWithString:#"http://www.tak2000.com/banner_test.html"];
bannerURL =[[NSURL alloc] initWithString:bannerURLString];
[bannerView loadRequest:[NSURLRequest requestWithURL:bannerURL]];
[bannerURL release];
[bannerURLString release];
}
I used a simple button connected to loadbannerView.
Webview code worked great in a simple one view example. Why is it dying when I use it in multi UIViewController app? BTW: I used the "Windows Based App" template as a starting point. I also ensured the Class Identity was UIWebView.
Thanks in advance...
bannerView is a property, so it should be
[self.bannerView loadRequest ....]
and make sure in interface builder that you've connected your UIWebView to the bannerView outlet.