I want to do some stuff from the appDelegate in Xcode. One of these things are to change a UILabel.
ViewController *viewController = [[UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"id"];
viewController.label.text = #"heeej";
I was told this would do the trick. Doesn't work. Label doesn't change. Does anyone know what the problem is?
There are several problems:
Don't do anything in the AppDelegate except for loading the window an the initial view controllers (if needed).
You are instantiating a new view controller in the first line. I assume you already have a view controller and you want to change the label in that view controller. Than you need a reference to that view controller and use this reference to send messages to it.
The label should not be a property of the view controller. You should try to follow the design pattern Model-View-Controller or the pattern Model-View-ViewModel. Ask you preferred search engine what those are if you don't know.
id as an identifier for anything in Objective-C is a bad idea because this is used as an object type.
Edit: You don't need a reference to change a property in the view controller. Use notifications to update the label. The system sends a notification with the name UIApplicationWillEnterForgroundNotification' (see [here][1]). Add the view controller as an observer to the[NSNotificationCenter defaultCenter]` for this name and react on the notification. Read the Apple documentation if you don't know what I am talking about.
Related
I am just starting up in Xamarin iOS (native) development, so bear with me as I try to explain what we're trying to do.
I have a single storyboard Main.storyboard, where I have designed and built a single Tab Bar controller, and several custom View Controllers, some of which are linked up as tabs. On the first tab, I have a login screen if they are not logged in. However, if they ARE logged in, I want to show the view defined in a different View Controller (Account) that exists within the same storyboard.
In the ViewDidLoad() override for the LoginController, I have the following code that I thought would show the "logged in" Account View Controller:
this.PresentViewController(new AccountController(), true, null);
This line of code executes without error, however the Login view is still shown. The ViewDidLoad() override in the AccountController does NOT fire.
Question 1: Is this the right method to call in order to replace your current view controller with another?
Now, if I place this exact same line of code in an async button handler method (particularly, the Facebook SDK Login Button's Completed event), it actually hits the ViewDidLoad() override in the AccountController, but I receive a NullReferenceException on a line that is simply referencing a button that is defined within the storyboard/view.
Question 2: Why would the same exact call from an event handler behave so differently?
Lastly, if I set the AccountController up as a tab bar tab instead, the code in ViewDidLoad() that is referencing the button works as expected.
Up to this point, all of my loading and unloading of different views was being handled automagically by the UITabBarController, but now that I'm trying to do some manual transitions, I am having a tough time finding appropriate documentation that isn't outdated and applies to my specific setup.
Generally , we can use PresentViewController to navigate to another page in Navigation Controller , this should be a safe and easy way.
Push :
Pop :
However , PresentModalViewController is a model ViewController , although it seems like the same as PresentViewController . It not needs to be in the stack of Navigation Controller ,and always used in a single view needs to show temporarily , soon will dismiss it.
If scene needs to reset RootViewControllerwhen runtime , this can be thought as the third way to navigate .
var storyboard = UIStoryboard.FromName("Main", null);
var anotherController = storyboard.InstantiateViewController("AnotherViewController") as AnotherViewController;
UIWindow window = UIApplication.SharedApplication.KeyWindow;
if(window != null)
{
window.RootViewController = anotherController;
}
In addittion , this will be un-safe way to use , better used them in current ViewController dismiss method :
DismissViewController(true, () => {
// Set Root View Controller
});
While Junior's answer pointed me in the right direction, the ultimate solution was to adjust the first tab to be a new NavigationController, and use (manual) Segues to navigate between the views.
The segues were added to the storyboard, and the View Controllers ultimately make calls to PerformSegue('namedSegue', this) to navigate to the next view.
Searched entire Internet but couldn’t find the modern solution for my problem.
I want to use NSObjectController in pair with Core Data through Cocoa Bindings and struggle to set it up properly. Worth noting that I’m using latest version of Xcode and Swift.
What I’ve done:
For testing purposes I’ve done the following:
Created an macOS app with “Use Core Data” option selected (the app is not document based);
Dragged 2 NSTextFields into the Storyboard Dragged NSObjectController to the view controller scene;
Added Employee Entity to Core Data model with 2 attributes “name” and “surname”;
Done everything from the answer in How do I bind my Array Controller to my core data model?
Set NSObjectController to entity mode and typed in “Employee”,
Prepares Content selected, Use Lazy Fetching selected so all three options checked;
Binded the NSObjectController’s Managed Object Context in bindings inspector to the View Controller’s managedObjectContext;
Binded NSTextFields as follows: Value - Object Controller, Controller key - selection, Model Key Path - name (for 1st text field) and surname (for 2nd).
That’s it.
First set of questions: What I did wrong and how to fix it if it’s not completely wrong approach?
I’ve read in some post on stackoverflow that doing it that way allows automatic saving and fetching from Core Data model. That’s why I assumed it should work.
So here is a Second set of questions:
Is it true?
If it is then why text fields are not filled when view is displayed?
If it is not then how to achieve it if possible (trying to write as less code as possible)?
Third question: If I used approach that is completely wrong would someone help me to connect Core Data and NSObjectController using Cocoa bindings and show me the way of doing so with as less code written as possible using the right approach?
Taking into account that there no fresh posts about this topic in the wilds I think the right answer could help a lot of people that are developing a macOS app.
Thanks in advance!
I think your basic approach is correct, although it is important to understand that you need a real object, an instance, in order for it to work.
Creating a NSManagedObject subclass is generally desirable, and is almost always done in a real project, so you can define and use properties. You can do it easily nowadays by selecting the data model in Xcode's Project Navigator and clicking in the menu: Editor > Create NSManagedObject Subclass…. Technically it is not necessary, and in a demo or proof-of-concept, you often muddle through with NSManagedObject.
Assuming you are using the Xcode project template as you described, wherein AppDelegate has a property managedObjectContext, the following function in your AppDelegate class will maintain, creating when necessary, and return, what I call a singular object – an object of a particular entity, in this case Employee, which your app requires there to be one and only one of in the store.
#discardableResult func singularEmployee() -> NSManagedObject? {
var singularEmployee: NSManagedObject? = nil
let fetchRequest: NSFetchRequest<NSManagedObject> = NSFetchRequest(entityName: "Employee")
let objects = try? self.managedObjectContext.fetch(fetchRequest)
singularEmployee = objects?.first
if singularEmployee == nil {
singularEmployee = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: self.managedObjectContext)
}
return singularEmployee
}
Then, add this line of code to applicationDidFinishLaunching
singularEmployee()
I am trying to use NSView to navigate between NSViewControllers using Swift in an OS X application.
I am not sure what are you trying to ask here. I would suggest to go through these links
Mac OS X Cocoa multiview application navigation
Easy Switching of "View Controllers" in Mac Apps (similar to iOS)
Hope this helps,cheers.
Edit:
If you are new to swift i would suggest to go through https://developer.apple.com/swift/ first. Your methods will look like the following in swift
func switchSubViews(newSubview : NSView) {
//Implementation
}
func prepareViews(){
//Implementation
}
First create a custom view in your xib file. This will be where the various view controllers will put their own views. In your the code which will navigate between the view controllers create a variable to reference the custom view in your xib file;
var masterView : NSView!
Back in interface builder, connect the custom view to your variable. masterView now refers to the custom view and gives you the means to change it.
You can replace that view with the view of the view controller that you want to be active at any given time.
For this example, assume that I have three view controllers (as examples);
var pDemog : patientDemographicsController!
var pExams : patientExamsListController!
var pReports : patentReportsViewController!
The first view controller can be set up as follows;
masterView.addSubview(pDemog.view)
Later when needed you can replace the view with the view of a different view controller
masterView.replaceSubview(pDemog!.view with: pExams!.view)
and back again;
masterView.replaceSubview(pExams!.view with: pDemog!.view)
or to another;
masterView.replaceSubview(pExams!.view with: pReports!.view)
That's the mechanism for changing the view. You can add animations as referenced above, but it's not necessary. Also, you should prepare the views in the view controllers as follows; (this is just one example, you need it for each view controller)
pDemog.view.setFrameOrigin(NSPoint(x:0, y:0))
pDemog.view.setFrameSize(masterView.frame.size)
do this before you start setting the views in the masterView.
Today I'm working with an interesting problem. I'm trying to code simple bookmarks, and by that I mean the most basic functionality; store the url, and load the url when you tap it.
Right now, the idea is that I would use the following:
currentURL = currentWebView.request.URL.absoluteString;
To retrieve the current URL, and then possibly store that within NSDefaults.
(Open to any other suggestions on better ways of preforming this)
However, the problem that I'm having is that, assuming I've gotten that far (retrieved the URL and stored it), how would I go about putting then somewhere in a list format that displays the url that was bookmarked, and then loading them (from that separate bookmarks view) in the main view that the UIWebView is contained in?
Your time is much appreciated
--Jake
NOTE: If you need more information or anything I could possibly help you with in order to come to a solution, just ask
Simple
Suppose your viewcontroller where your webview resides, is WebViewController and where list shows is BookmarkViewController.
Create a property in BookmarkViewController
#property(nonatomic,retain)WebViewController *maincontroller;
Send the reference of your WebViewController to BookmarkViewController when you create BookmarkViewController object
bookmarkobject.maincontroller=self;
and then In didSelectRowAtIndexPath
either use
1) [maincontroller.webView loadRequest:url];
or
make a method in WebViewController with parameter url and call this method from didSelectRowAtIndexPath
2) [maincontroller loadUrlInWebView:url];
and dismiss your modal
or create a property of url in WebViewController and in didSelectRowAtIndexPath
3) [maincontroller urlstring:url];
and in viewWillAppear load this url in your webview
Hope any of these 3 methods will help you.
at the risk of a public flogging, I was hoping someone could clarify my understanding of communicating between the app controller and a window controller. Here is the scenario using xcode4.
using the default AppDelegate.h and .m as the "controller" (which is also a delegate to MainMenu.xib). Have an ivar called int counter.
Created page.xib and PageController.h and .m (subclass NSWindowController). Imported it into AppDelegate.m
Used IBAction to create and view the page object. Like this:
if (!page1) {
PageController *page1 = [[Page
if (!page1) {
page1 = [[PageControoer alloc] initWithWindowNibName:#"page"];
}
[page1 showWindow:sender];
So the new window pops and we can press buttons, etc. The code for the new window is all in PageController.h and .m. and things basically work.
That is the context, here is where I'm confused.
a) question: let's say I want to access that original ivar in AppDelegate.h called counter from PageController. Either retrieving or updating the variable. What approach would I take?
b) confirm: let's say I'm back in the AppDelegate and want to get access to a selector from page1. I believe I can do this as so: [page1 runaction]; or [[page1 variable] setStringValue:#"hello"];
(this complies but I'm not sure it really works because I can't get the changes into the xib view.)
ok and the stumper. Say another view was created with another view controller call it Page2Controller.h and .m.
c) how should data flow between page and page2 -> via the AppDelegate or directly? what would the syntax look like to connect them together?
I've been following tutorials, but they don't really cover this back and forth messaging. Thanks for all the help!
a) Generally, if you want to have data that is accessed by your controllers, it should be in a model which they are given access to in some way. You can access things in the app delegate using this method:
AppDelegate* appDelegate = [[NSApplication sharedApplication] delegate];
[appDelegate <some method>];
b) I don't understand what you're asking. If the app delegate has a pointer to page1, then yes, you can call it directly.
c) Again, you should have a data model of some sort. The controllers should update the data model when the user changes the view. You can use notifications, IBActions, and direct calls to do the updating, for example. You should look up the Model, View, Controller design pattern.