UIViewController method from AppDelegate - objective-c

This is my 1st question in stackoverflow.com.
I'm trying to call upon a method [- (void)alterTime] from ViewController.m in AppDelegate.m. Yes, I have #imported "ViewController.h" in AppDelegate.h. Importing the controller into AppDelegate.m makes no difference. Also, "Background fetch" is ON.
Here is the code inside AppDelegate.m that I'm trying to implement:
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
NSLog(#"Current Time Altered");
//Get current view controller
ViewController *mainViewController = (ViewController *)self.window.rootViewController;
[mainViewController alterTime];
//Cleanup
completionHandler(UIBackgroundFetchResultNewData);
}
This is the piece of code giving me problems:
[mainViewController alterTime];
It states: "No visible #interface for 'ViewController' declares the selector 'alterTime'".

So that error means that it failed to find the method name (selector), in the class ViewController.
Make sure in your ViewController header you have the alterTime method declared there, effectively making it public.
If that is okay, then double check to make sure that your rootViewController is of type (owned by) ViewController

Declare - (void)alterTime in your ViewController.h file.
#interface ViewController : UIViewController
- (void)alterTime;
#end

Related

Simple passing of data through delegation in objective C

I'm using Xcode to write an app in objective c. I am trying to pass data from a container view controller to the parent view controller using delegation. I have successfully passed the data to the parent view controller, but all of the documentation sets what I have sent to the .h header file in the .m implementation file using viewDidLoad or viewDidAppear. I was wondering, since the view is already present, if there is a way to detect that data has been changed in a view and automatically run a method or code to update the view with the new information. Something along the idea of didReceiveNewData or didEditExistingValues (of course those arent real methods). Thank you for your help!
Edit: What I have done so far:
I want to pass the data from MainFeedTableViewController to MainFeedViewController (The first is in a container inside of the second). I want to set the title of the custom navigation bar in MainFeedViewController to something described in the MainFeedTableViewController.
In the MainFeedTableViewController.m (the view sending data) I have:
#import "MainFeedTableViewController.h"
#import "FeedViewController.h"
#interface MainFeedTableViewController ()
#end
#implementation MainFeedTableViewController
- (IBAction)swipeLeftDetected:(UIGestureRecognizer *)sender {
UIStoryboard *mc = self.storyboard;
FeedViewController *fv = [mc instantiateViewControllerWithIdentifier:#"FeedViewController"];
fv.navigationBarTitleToSet = #"HOPING TO SET TITLE TO THIS";
[self performSegueWithIdentifier:#"MainToLocalFeed" sender:self];
}
and some other unrelated stuff..
In the MainFeedTableViewController.h I have:
#import <UIKit/UIKit.h>
#interface MainFeedTableViewController : UITableViewController
#end
In the MainFeedViewController.m (the one receiving the data) I have:
#import "FeedViewController.h"
#interface FeedViewController () <UINavigationBarDelegate>
#property (weak, nonatomic) IBOutlet UINavigationBar *navigationBar;
#end
#implementation FeedViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)setNavigationBarTitle:(NSString *)navigationBarTitle{
self.navigationItem.title = navigationBarTitle;
}
And in the MainFeedViewController.h I have:
#import <UIKit/UIKit.h>
#interface FeedViewController : UIViewController
#property NSString *navigationBarTitleToSet;
#end
I want to run the setNavigationBarTitle method with either data from the .h (navigationBarTitleToSet) or just from the sending view controller, if possible to run a method with delegation. Thanks a ton and I hope this is possible :)
It turns out I needed to add a second navigation bar to account for the container view, allowing me to navigate around the current stack with the parentViewController method and then navigationItem.title. For anyone who happens to find this with a container, make sure you add one immediately after the embed segue. I'm still not sure if you can use methods through delegation, but I can't ponder any situations where it would be necessary anymore, due to viewDidLoad. Thanks to #Tander for the help!

Getting an error when trying to assign a data controller to a UICollectionViewController in XCode

I've set up a LibraryDataController class that gets data from an sqlite database. This is its .h file:
#import <Foundation/Foundation.h>
#import <sqlite3.h>
#interface LibraryDataController : NSObject{
sqlite3 *database;
}
#property (nonatomic) NSMutableArray *masterPhotoList;
-(NSInteger)listCount;
-(NSString*)objectInListAtIndex:(NSUInteger)index;
-(void)createEditableCopyOfDatabaseIfNeeded;
-(void)initializeDefaultList;
-(void)closeDatabase;
#end
I also have a library view that has a LibraryDataController member:
#import <UIKit/UIKit.h>
#class LibraryDataController;
#interface LibraryViewController : UICollectionViewController
#property (nonatomic, strong) LibraryDataController *dataController;
#end
My problem occurs on the app startup where I load information from the sqlite database into a data controller (The init function does this successfully). Then I try to assign the database to the library view. The library view is the second view on a tab bar, and the tab bar controller is the root view.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UITabBarController *tabController = (UITabBarController *)self.window.rootViewController;
LibraryViewController *libraryView = [[tabController viewControllers] objectAtIndex:1];
LibraryDataController *aDataController = [[LibraryDataController alloc] init];
libraryView.dataController = aDataController;
return YES;
}
The error comes from the libraryView.dataController = aDataController; line. Any ideas about what my problem is? I'm thinking it may have to do with the UICollectionView as I am very new to it. This code is almost identical to code I used successfully with a UITableView and I was under the impression the two views were very similar. Thanks for your help.
The error message
[UICollectionViewController setDataController:]: unrecognized selector sent to instance 0x71a5170
shows that libraryView (which is the second view controller of the tab bar controller) is an instance of UICollectionViewController, and not LibraryViewController, as you expected.
The solution is to set the "Custom Class" of the view controller in the storyboard file to "LibraryViewController" (using the "Identity inspector).

creating a global NSMutableSet

In reference to the answer of this SO question: Keeping track of changes in a UIView
I need help setting up the global aspect of the NSMutableSet. In my appdelegate.h file I've got this:
#interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
ViewController *viewController;
NSMutableSet *statesTouched;
}
and this in my appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
statesTouched = [[NSMutableSet alloc]init];
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
In my viewcontroller.h file I'm adding the object like this:
[statesTouched addObject:touchedStateName];
but I'm getting an undeclared identifier for statesTouched. I've never tried putting something like this into my app delegate and I'm a little confused at how this should be working. Thanks!
This is because is an instance variable of your AppDelegate, not your view controller. If you move the declaration and the initialization to your view controller, the error will go away. It would not make it a global variable, though, which is good if it works for you.
If it does not work for you, make the variable a truly global one: move the declaration out of the app delegate, and add extern keyword, like this:
extern NSMutableSet *statesTouched;
Now add the definition in the .m file, like this:
NSMutableSet *statesTouched;
Make sure the definition is outside the #implementation block.

How do I set a property of an object from another file in cocoa?

I'm coding an iPhone app.
Instead of writing all the code here, this is basicly what I want to do:
testViewController.m:
- (void)viewDidLoad { label.text=#"text"; }
This works.
Now I want to change the label text from the testAppDelegate file.
- (void)applicationDidBecomeActive:(UIApplication *)application {
testViewController *tvc=[[testViewController alloc] init];
tvc.label.text=#"another text";
[tvc release];
}
This isn't working!
How can I do this?
Thanks for all answers :)
In applicationDidBecomeActive you are creating a new instance of the view controller (this is what alloc / init) setting the label text in your new instance and then releasing it.
You need to be referring to the actual instance of your view controller that is on the screen. This is probably already referred to somewhere in your application delegate - is it the root view controller, for example? When is it created in the first place?
You may need to set a property on your application delegate to hold a reference to this view controller. The code you have is fine except that you are talking to a new controller instead of the one that is presented on the screen - assuming of course that your label is a property on the view controller.
In .h file: define property:
#property (nonatomic, retain) UILabel *label;
In .m file: implement set/get methods for that propery (for example, automatically):
#synthesize label;
Declare testViewController as outlet in testAppDelegate.h, perform its binding in xib, probably MainMenu.xib, now try changing value of its label in -
- (void)applicationDidBecomeActive:(UIApplication *)application
I'm sorry! Should have specified more what I was doing. Now I've learned.
I had a tab-bar view controller template.
I solved this by adding in the delegate .h file:
#class testViewController
#property(nonatomic,retain) UIViewController *testViewcontroller;
and in the .m file:
#synthesize testViewController=_tvc;
- (void)applicationDidBecomeActive:(UIApplication *)application
{
_tvc.label.text=#"another text";
}
And of course imported the testViewController.h and declearing the methods there too.
Thanks for all your responses :)

objective C Basic question

i made a simple application using view based template.and i put only nslog inside view didload method in viewController file and also inside applicationDidFinishLaunch method (in appDelegate )to checked which class file called first.
after the run i got: viewController Run first and then appdelegate ..but i think appdelegate should first then other's called according to the need ... plz give me the proper reasion.
Noted that --i did not call viewController (didnot make object) in my appDelegate(inside application didFinishLaunch) . i am using ios4
If your View Controller is a property of the AppDelegate, similar to the code reference
#interface AppDelegate_Shared : NSObject <UIApplicationDelegate, UIAlertViewDelegate, OMFDataLoadDelegate> {
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
UIWindow *window;
UITabBarController *tabBarController;
}
then it is probably getting allocated by the AppDelegate when it is being allocated. According to the Apple documentation viewDidLoad is run after the view is loaded into memory, which can be a little confusing, since the language can make you believe it's when it's loaded onto the screen.
http://developer.apple.com/iphone/library/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006926-CH3-SW25
Move your NSLog statement to viewDidAppear for the result you were expecting. Here's two sample snippets with the way you should expect the statements to load.
ViewController.m
- (void) viewDidLoad {
NSLog(#"1st - this occurs when appDelegate allocates this object");
}
- (void) viewDidAppear {
NSLog(#"3rd - this should appear after the applicationDidFinishLaunchingStatement");
}
AppDelegate_Shared.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"2. Starting AppDelegate_Shared");
[window addSubview:self.tabBarController.view];
[window makeKeyAndVisible];
NSLog(#"4. Leaving AppDelegate_Shared");
return YES;
}
If the initial view hasn't loaded then clearly the application has not finished launching.
The messages are sent in the right order.