'initWithNibName:bundle:' is unavailable LBTAFormController - objective-c

I am new to swift, and i am working on a swift and objective-c mixed project. I got stuck , if anyone could help, Thanks so much!
I would like to use LBTAFormController(LBTATools).
In my project, I created FormViewController.swift and FormViewController.xib.
I want to pushViewController to FormViewController.swift
FormViewController * loginForm = [[FormViewController alloc] initWithNibName:#"LoginFormViewController" bundle:nil];
[self.navigationController pushViewController:loginForm animated:YES];
in FormViewController.swift, I set up like this:
import UIKit
import LBTATools
class FormViewController: LBTAFormController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
However, I always got error
'initWithNibName:bundle:' is unavailable

Related

Dismissing all presented ViewControlelrs in a UINavigationController hierarchically

I was looking for a way to dismiss all the modally presented viewControllers in a UINavigationController hierarchically without knowing the name of them. so I ended up to the while loop as follow:
Swift
while(navigationController.topViewController != navigationController.presentedViewController) {
navigationController.presentedViewController?.dismiss(animated: true, completion: nil)
}
Objective-c
while(![self.navigationController.topViewController isEqual:self.navigationController.presentedViewController]) {
[self.navigationController.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
I want to dismiss all the presentedControllers one by one till the presentedViewController and topViewcontroller become equal.
the problem is that the navVC.presentedViewController doesn't changed even after dismissing.
It remains still the same even after dismissing and I end up to an infiniteLoop.
Does anyone knows where is the problem?
In my case nothing works but:
func dismissToSelf(completion: (() -> Void)?) {
// Collecting presented
var presentedVCs: [UIViewController] = []
var vc: UIViewController? = presentedViewController
while vc != nil {
presentedVCs.append(vc!)
vc = vc?.presentedViewController
}
// Dismissing all but first
while presentedVCs.count > 1 {
presentedVCs.last?.dismiss(animated: false, completion: nil)
presentedVCs.removeLast()
}
// Dismissing first with animation and completion
presentedVCs.first?.dismiss(animated: true, completion: completion)
}
I've found the answer. I can dismiss all presentedViewControllers on a navigationController by:
navigationController.dismiss(animated: true, completion: nil)
It keeps the topViewController and dismiss all other modals.
Form your question I understood that you want to dismiss all view controllers above the root view controller. For that you can do it like this:
self.view.window!.rootViewController?.dismiss(animated: false, completion: nil)
Not need to used self.navigationController.presentedViewController.
Might be help! my code is as follows:
Objective-c
[self dismissViewControllerAnimated:YES completion:^{
}];
// Or using this
dispatch_async(dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:nil];
});
Please check this code
-(void)dismissModalStack {
UIViewController *vc = self.window.rootViewController;
while (vc.presentedViewController) {
vc = vc.presentedViewController;
[vc dismissViewControllerAnimated:false completion:nil];
}
}
Glad to see you have found the answer, and I've done this by another way.
You can create a BaseViewController(actually lots of app do that), and defined a property like 'presentingController' in appdelegate that indicate the presenting ViewController, then in the viewWillAppear method, set the property so that it always indicate the top view controller.
-(void)viewWillAppear:(BOOL)animated{
AppDelegate *delegate=(AppDelegate *)[[UIApplication sharedApplication]delegate];
delegate.presentingController = self;
}
All the class inherited from BaseViewController will call it. When you want to dismiss all the controller, just loop as follow:
- (void)clickButton:(id)sender {
AppDelegate *delegate=(AppDelegate *)[[UIApplicationsharedApplication]delegate];
if (delegate.presentingController)
{
UIViewController *vc =self.presentingViewController;
if ( !vc.presentingViewController ) return;
while (vc.presentingViewController)
{
vc = vc.presentingViewController;
}
[vc dismissViewControllerAnimated:YEScompletion:^{
}];
}
}
Hope this will help you :)
I had a similar issue of deleting/dismissing existing/previous push notification when a new push notification arrives where different pictures are sent as a push notification.
In my situation, using Swift 5, I wanted to delete/dismiss previous push notification and display a new push notification all by itself regardless whether the user acknowledged the previous notification or not (i.e. without user's acknowledgement).
I tried Kadian's recommendation with a minor change and it worked flawlessly.
Here is my NotificationDelegate.swift
import UIKit
import UserNotifications
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .sound, .badge])
}
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
defer { completionHandler() }
guard response.actionIdentifier == UNNotificationDefaultActionIdentifier else {return}
let payload = response.notification.request.content
let pn = payload.body
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: pn)
//***Below cmd will erase previous push alert***
self.window!.rootViewController?.dismiss(animated: false, completion: nil)
//Below cmd will display a newly received push notification
self.window!.rootViewController!.present(vc, animated: false)
}
}

UIImagePickerController in Landscape embedded in a UINavigationController Objective-C

Im trying to present the ImagePicker in Landscape with a landscape only app that embedded in UINavigationController. None of the answers I've found are working. Apparently this is possible now. Ive found a way to do this in Swift from here, but I'm not using Swift. Perhaps someone can help me convert this Swift code to Objective-C or provide a real working example in Objective-C. It looks like many people would benefit from this. Thanks for helping in advance.
Working Swift Code that needs converting to Objective-C:
//Appdelegate.swift
func application(application: UIApplication, supportedIntefaceOrentationForWindow window: UIWindow?) ->UIInterfaceOrientationMask{
if let presentViewController = window?.rootViewController?.presentedViewController {
if (presentViewController.isKindOfClass(UIImagePickerController) && !presentViewController.isBeingDismissed() ) {
return UIInterfaceOrientationMask.Portrait
}
}
return UIInterfaceOrientationMask.Landscape
}
Objective-C Code I'm using to present the Image Picker gives a SIGBART error from the app delegate "Works fine with portrait enabled otherwise":
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.mediaTypes = [[NSArray alloc] initWithObjects:(NSString *)kUTTypeMovie, nil];
UIViewController *viewController = self.view.window.rootViewController;
[viewController presentViewController: imagePicker animated: YES completion:nil];
This is the Objective-C code.
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (([window.rootViewController.presentedViewController isKindOfClass:[UIImagePickerController class]]) && (window.rootViewController.presentedViewController.isBeingDismissed == NO)) {
return UIInterfaceOrientationMaskPortrait
}
return UIInterfaceOrientationMaskLandscape
}

Can someone help me convert this OBJ-C code to Swift?

Im trying to add the facebook audience network to my project but the tutorial is in objective C and I need it in swift. I already made the bridging header, now I need to add the code. Can someone convert it to swift for me? Thank you! Heres the link if you want to take a look at it:
https://developers.facebook.com/docs/audience-network/ios/banner
- (void)viewDidLoad
{
[super viewDidLoad];
FBAdView *adView = [[FBAdView alloc] initWithPlacementID:PLACEMENT_ID adSize:kFBAdSizeHeight50Banner rootViewController:self];
[adView loadAd];
[self.view addSubview:adView];
}
This should work, let me know if any trouble
override func viewDidLoad() {
super.viewDidLoad()
let adView: FBAdView = FBAdView(placementID:PLACEMENT_ID, adSize:kFBAdSizeHeight50Banner, rootViewController:self);
adView.loadAd();
self.view.addSubview(adView);
}

NSViewController initWithCoder - bundle has not been loaded

I have a viewController in my storyboard that I have set up like below:
I am using the following code to load it programmatically.
-(AttributeViewController*)AttributeVC{
if(!_AttributeVC)
{
_AttributeVC = (AttributeViewController*)[self.storyboard
instantiateControllerWithIdentifier:#"MyAttribute"];
}
return _AttributeVC;
}
my app crashes with:
-[NSViewController initWithCoder:] could not instantiate an NSViewController for a
nib in the "Attribute" bundle because the bundle has not been loaded.
Why is the view controller now trying to load the "Attribute" bundle that I don't have.
Thanks.
Try to include the storyboardWithName reference in there as well... This worked for me
-(AttributeViewController*)AttributeVC{
if(!_AttributeVC)
{
_AttributeVC *attributeVC = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"MyAttribute"];
}
return _AttributeVC;
}

Conversion of custom init routines in Swift

I need to subclass SVModalWebViewController.m (GitHub), which is itself a subclass of UINavigationController, and am incorporating this code into a new app that will be created entirely in Swift. I've run into several issues, so I decided to first convert just this very simple class into Swift to debug.
Initialization is a little different in Swift compared with Objective-C (read more about Swift initialization here), which is why I'm not returning self in the Swift code.
Here's the original Obj-C code (minus the *.h, which instantiates barsTintColor):
#import "SVModalWebViewController.h"
#import "SVWebViewController.h"
#interface SVModalWebViewController ()
#property (nonatomic, strong) SVWebViewController *webViewController;
#end
#implementation SVModalWebViewController
#pragma mark - Initialization
- (id)initWithAddress:(NSString*)urlString {
return [self initWithURL:[NSURL URLWithString:urlString]];
}
- (id)initWithURL:(NSURL *)URL {
self.webViewController = [[SVWebViewController alloc] initWithURL:URL];
if (self = [super initWithRootViewController:self.webViewController]) {
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self.webViewController
action:#selector(doneButtonClicked:)];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
self.webViewController.navigationItem.leftBarButtonItem = doneButton;
else
self.webViewController.navigationItem.rightBarButtonItem = doneButton;
}
return self;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:NO];
self.webViewController.title = self.title;
self.navigationBar.tintColor = self.barsTintColor;
}
#end
And here's the entire Swift version of the class (I simplified to just one init method since I didn't need to init with URL specifically):
import UIKit
class SVModalWebViewController: UINavigationController {
var webViewController: SVWebViewController!
var barsTintColor: UIColor?
// This was added because of a compiler error indicating it needed to be added
init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
init(address urlString: String!) {
let url: NSURL = NSURL.URLWithString(urlString)
self.webViewController = SVWebViewController(URL: url)
super.init(rootViewController: self.webViewController)
let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self.webViewController, action: Selector("doneButtonClicked:"))
if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
self.navigationItem.leftBarButtonItem = doneButton
} else {
self.navigationItem.rightBarButtonItem = doneButton
}
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// self.title may not be set, and is considered an optional in Swift, so we have to check first
if self.title {self.webViewController.title = self.title}
self.navigationBar.tintColor = self.barsTintColor
}
}
The issue I'm having relates to setting the Done button in the navigationItem. Currently they're not showing up at all when this code is called:
let webViewController = SVModalWebViewController(address: "http://www.google.com");
webViewController.barsTintColor = UIColor.blueColor()
self.presentModalViewController(webViewController, animated: true)
The modal view appears just fine and I'm able to correctly set the bar color property, but the Done button does not show up. It appears that I don't have proper access to the navigationItem of the UINavigationController. Note that I had to add the init with nibName method due to a compiler error without it. This wasn't required in the Obj-C code and I'll admit I'm not sure why it's needed in Swift - that could be part of the issue.
Any thoughts as to why I cannot set the self.navigationItem.leftBarButtonItem property of the UINavigationController? Thanks!
A UINavigationController does not have a navigationItem. Well, it does, but it's useless. It is the navigationItem of the child controller (in this case, the rootViewController, which you are also calling self.webViewController) that appears in the navigation bar.