SWRevealViewController Error. Build Fails, but no error - ios

First of all, let me give you a heads-up. I'm moderately familiar with XCode (5) and Objective-C.
But, consider me a noob and please help me out.
I'm trying to build an app. I need a Slide out menu in all Views of the app.
I made a dummy project using SwRevealViewController Class. And I have made two slide out menus also. And it works.
I tried to use the same method in the App that I'm building.
But my build has failed with no Errors and a single warning, which I had in my previous dummy project....
I have already imported SwRevealViewController.h to AppDelegate.m and ViewController.m
I'm trying to use a TableViewController as slideout menu (which is empty, I haven't added any code to it yet). But the build is failing.
Edit:
" The error is as follows..
"#synthesize of 'weak' property is only allowed in ARC or GC Mode"
I'm using Core Data with my project. And I have to use webservice extensively in my App. So I have disabled ARC. "
I have also tried replacing table with other views, but the same result. Now I'm stuck.
I know its some thing with my code, but I couldn't find it.
I'm including code of AppDelegate.m and ViewController.m.
Please check it and tell me what is wrong. I'm at a loss here.
Edit:
" I cannot upload images due to Stack Overflow restrictions. So I have uploaded a screenshot of the error in tinypic. Here is the url.
http://tinypic.com/r/162vli/8 "
Thank you for all your help.
AppDelegate.h
// AppDelegate.h
// IndianBloodBank
//
// Created by Roshith Balendran on 8/5/14.
// Copyright (c) 2014 Olympus. All rights reserved.
//
#import <UIKit/UIKit.h>
#class SWRevealViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UINavigationController *UINV;
#property (strong, nonatomic) SWRevealViewController *splitMenu;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#end
AppDelegate.m
//
// AppDelegate.m
// IndianBloodBank
//
// Created by Roshith Balendran on 8/5/14.
// Copyright (c) 2014 Olympus. All rights reserved.
//
#import "AppDelegate.h"
#import "SWRevealViewController.h"
#import "HomePageViewController.h"
#import "SlideOutMenuTableViewController.h"
#import "SearchViewController.h"
#import "AboutUsViewController.h"
#import "SponsorsViewController.h"
#import "HowToDonateViewController.h"
#import "EmergencyViewController.h"
#implementation AppDelegate
#synthesize splitMenu,window,UINV;
#synthesize managedObjectContext = _managedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window = window;
HomePageViewController *HPVC = [[HomePageViewController alloc]init];
SlideOutMenuTableViewController *SOMTVC = SOMTVC = [[SlideOutMenuTableViewController alloc]init];
UINavigationController *frontNavigationController = [[UINavigationController alloc]initWithRootViewController:HPVC];
UINavigationController *rearNavigationController = [[UINavigationController alloc]initWithRootViewController:SOMTVC];
SWRevealViewController *revealController= [[SWRevealViewController alloc]initWithRearViewController:rearNavigationController frontViewController:frontNavigationController];
revealController.delegate=self;
revealController.rightViewController = SOMTVC;
self.splitMenu = revealController;
self.window.rootViewController = self.splitMenu;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
HomePageViewController.m
//
// HomePageViewController.m
// IndianBloodBank
//
// Created by Roshith Balendran on 8/5/14.
// Copyright (c) 2014 Olympus. All rights reserved.
//
#import "HomePageViewController.h"
#import "SWRevealViewController.h"
#import "AboutUsViewController.h"
#import "SponsorsViewController.h"
#import "HowToDonateViewController.h"
#interface HomePageViewController ()
#end
#implementation HomePageViewController
#synthesize btn1SearchBlood,btn2DonateNow;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[[UINavigationBar appearance] setBarTintColor:[UIColor colorWithRed:0.055 green:0.055 blue:0.059 alpha:1]];
self.navigationController.navigationBar.translucent=NO;
SWRevealViewController *revealViewController = [self revealViewController];
[revealViewController panGestureRecognizer];
[revealViewController tapGestureRecognizer];
UIBarButtonItem *menuButton = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:#"menu-icon"] style:UIBarButtonItemStyleBordered target:revealViewController action:#selector(revealToggle:)];
self.navigationItem.leftBarButtonItem = menuButton;
}

The solution was simple, I just had to turn on ARC.
The basic requirement of SWRevealViewController Class is ARC enabled.
You cannot use this Class for slide out navigation with ARC disabled.
My bad guys. Thought I checked for errors with ARC enabled. My mistake.
So, if you encounter this error "#synthesize of 'weak' property is only allowed in ARC or GC Mode", just turn on ARC.

Related

Xcode error - unknown type name 'home'

this is my first question on stackoverflow.! Cheers.!
Please review my code from the link below. I have copy pasted appdelegate.h, appdelegate.m, viewcotroller.h&.m to a text document for reviewing purposes.
http://www.mediafire.com/view/85614p44t8eiqif/HomePageViewController.rtf
I will explain my problem in detail below.
I'm trying to recreate UICatalogue in a smaller scale all through code. I'm an app developement trainee. This is what I have done so far.
Keep in mind that my knowledge on Xcode and Objective-C is very limited. I'm using Xcode 5.1.1
I have created an instance variable (HPVC) for the Home Page view controller "HomePageViewController" in AppDelegate.h
I have set this HPVC as rootviewcontroller.
Declared and defined some instance variables.
*But I'm stuck in a loop from what I have searched so far.
I understand the importing has ended up in a loop. But I cant fix it.
Please check this and give me an answer. I can start my project If I can clear this obstacle.
Here is a screenshot of the error
http://www.mediafire.com/view/yjmwbb2dcb7rymd/Error.png
//
// AppDelegate.h
// NewUICatalogue1
//
// Created by Roshith Balendran on 18/04/14.
// Copyright (c) 2014 Roshith Balendran. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "HomePageViewController.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
HomePageViewController *HPVC;
}
#property (strong, nonatomic) UIWindow *window;
#end
//
// AppDelegate.m
// NewUICatalogue1
//
// Created by Roshith Balendran on 18/04/14.
// Copyright (c) 2014 Roshith Balendran. All rights reserved.
//
#import "AppDelegate.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
HPVC=[[HomePageViewController alloc]initWithNibName:#"HomePageViewController" bundle:nil];
self.window.rootViewController=HPVC;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#end
//
// HomePageViewController.h
// NewUICatalogue1
//
// Created by Roshith Balendran on 18/04/14.
// Copyright (c) 2014 Roshith Balendran. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface HomePageViewController : UIViewController
//Background Images for all the Views.
#property(nonatomic,strong) UIImageView *HomePageBG;
#property(nonatomic,strong) UIImageView *Page1ButtonBG;
#property(nonatomic,strong) UIImageView *Page2ControlsBG;
#property(nonatomic,strong) UIImageView *Page3TextFieldBG;
#property(nonatomic,strong) UIImageView *Page4TextView;
#property(nonatomic,strong) UIImageView *Page5Images;
#property(nonatomic,strong) UIImageView *Page6Segments;
#property(nonatomic,strong) UIImageView *Page7Toolbar;
#property(nonatomic,strong) UIImageView *Page8Alerts;
#property(nonatomic,strong) UIImageView *Page9Transitions;
//Home Page Elements.
#property(nonatomic,strong) UILabel *lblHomePageHeader;
#property(nonatomic,strong) UILabel *lblHomePageWelcome;
#property(nonatomic,strong) UIButton *BtnPage1;
#property(nonatomic,strong) UIButton *BtnPage2;
#property(nonatomic,strong) UIButton *BtnPage3;
#property(nonatomic,strong) UIButton *BtnPage4;
#property(nonatomic,strong) UIButton *BtnPage5;
#property(nonatomic,strong) UIButton *BtnPage6;
#property(nonatomic,strong) UIButton *BtnPage7;
#property(nonatomic,strong) UIButton *BtnPage8;
#property(nonatomic,strong) UIButton *BtnPage9;
#property(nonatomic,strong) UIButton *BtnChangeBGColor;
//Future Update. Add Button to change all button colors in Home Page.
#end
//
// HomePageViewController.m
// NewUICatalogue1
//
// Created by Roshith Balendran on 18/04/14.
// Copyright (c) 2014 Roshith Balendran. All rights reserved.
//
#import "HomePageViewController.h"
#interface HomePageViewController ()
#end
#implementation HomePageViewController
#synthesize HomePageBG;
#synthesize Page1ButtonBG;
#synthesize Page2ControlsBG;
#synthesize Page3TextFieldBG;
#synthesize Page4TextView;
#synthesize Page5Images;
#synthesize Page6Segments;
#synthesize Page7Toolbar;
#synthesize Page8Alerts;
#synthesize Page9Transitions;
#synthesize lblHomePageHeader;
#synthesize lblHomePageWelcome;
#synthesize BtnPage1;
#synthesize BtnPage2;
#synthesize BtnPage3;
#synthesize BtnPage4;
#synthesize BtnPage5;
#synthesize BtnPage6;
#synthesize BtnPage7;
#synthesize BtnPage8;
#synthesize BtnPage9;
#synthesize BtnChangeBGColor;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Home Page Background image added.
HomePageBG=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320, 568)];
HomePageBG.image=[UIImage imageNamed:#"Red"];
[self.view addSubview:HomePageBG];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
everything is correct but you forgot to import #import "HomePageViewController.h" on app delegate.m class

Application windows are expected to have a root view controller at the end of application

I have one problem and I've read following solution.This is my code
AppDelegat.h
#import <UIKit/UIKit.h>
#class ViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property(strong,nonatomic)ViewController *vobj;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window= [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.vobj = [[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController = self.vobj;
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
and it gives an error Application windows are expected to have a root view controller at the end of application launch
This is my code
https://www.dropbox.com/s/y3gzur3tb032nz3/slide.zip
Applications are expected to have a root view controller at the end of application launch
Application windows are expected to have a root view controller at the end of application launch warning
Application windows are expected to have a root view controller at the end of application launch - even with all known issues fixed
and other link...
Thank You.
I found the source of the problem, and I made it work. It is deeper than it seems. The general problem is that on your "synthesised" line, you have also set the 'view' outlet to be synthesised. The 'view' is automatically associated on view creation with the 'view' property inside a view controller by iOS, and you just did an override on that association.
Change your line to this
#synthesize slide1,slide2,slide3,segmentview,segment1,segment2,switch1,newslider,lbl;
and you will be fine. The problem was that although your view controller was instantiated and assigned as a root view controller, its 'view' property was set to nil. You could see that using the debugger. iOS probably interpreted the nil view as an unassigned root view controller, hence the error you were seeing.
On a side note, might I give you some advice on how to save time, redundancy and make your code cleaner? Consider the following code:
#interface ViewController : UIViewController
{
// UISlider *slide1;
// UISlider *slide2;
// UISlider *slide3;
// UIView *newslider;
// UIView *segment1;
// UIView *segment2;
// UISegmentedControl *segmentview;
// UILabel *lbl;
// UISwitch *switch1;
//
}
#property (strong,nonatomic)IBOutlet UISlider *slide1;
#property (strong,nonatomic)IBOutlet UISlider *slide2;
#property (strong,nonatomic)IBOutlet UISlider *slide3;
#property (strong,nonatomic)IBOutlet UIView *newslider;
#property (strong,nonatomic)IBOutlet UIView *segment1;
#property (strong,nonatomic)IBOutlet UIView *segment2;
#property (strong,nonatomic)IBOutlet UISegmentedControl *segmentview;
#property (strong,nonatomic)IBOutlet UILabel *lbl;
#property (strong,nonatomic)IBOutlet UISwitch *switch1;
-(IBAction)btnchangecolor:(id)sender;
#end
Then, your view controller implementation would be like this:
#implementation ViewController
//#synthesize slide1,slide2,slide3,segmentview,segment1,segment2,switch1,view,newslider,lbl;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)loadView {
[super loadView];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
-(IBAction)btnchangecolor:(id)sender
{
if (_segmentview.selectedSegmentIndex==0) {
_segment1.backgroundColor=[UIColor colorWithRed:_slide1.value/255 green:_slide2.value/255 blue:_slide3.value/255 alpha:1.0];
}
else
{
_segment2.backgroundColor=[UIColor colorWithRed:_slide1.value/255 green:_slide2.value/255 blue:_slide3.value/255 alpha:1.0];
}
_lbl.backgroundColor=[UIColor colorWithRed:_slide1.value/255 green:_slide2.value/255 blue:_slide3.value/255 alpha:1.0];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
When you create a #property, modern Xcode versions produce a #property with that name, and sets the internal variable of a property like "myVar" automatically to "_myVar". Before automatic synthesizing feature, you could set the name of the internal variable by writing "#synthesize myVar = _myInternalVar", which would allow you to write "_myInternalVar = newValue" or "self.myVar = newValue" (you can still do that, by the way, if you wish). Seeing your code however, there seems to be some redundancy. You create iVars, and then, you create IBOutlets and then you synthesise the outlets with the name of the iVars. It's not an error, it's not even a warning, but you could save so much time by writing only the "#property" elements and not anything else, that I though I might just throw it as an option :)

Property 'images' not found on object of type 'UIViewController *'

I'm trying to merge these two projects.
Bearded - An iPhone photo app
Thumbnail Picker View
At this point I'm just trying to keep these in separate view controllers and getting the functionality of the Thumbnail Picker working in it's own controller.
I'm getting the error, as stated in the title, "Property 'images' not found on object of type 'UIViewController *'"
The error is coming from the AppDelegate.m file:
#import "AppDelegate.h"
#import "ViewController.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize viewController = _viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[UIViewController alloc] init];
NSArray *paths = [[NSBundle mainBundle] pathsForResourcesOfType:#"jpg" inDirectory:nil];
NSMutableArray *images = [NSMutableArray arrayWithCapacity:paths.count];
for (NSString *path in paths) {
[images addObject:[UIImage imageWithContentsOfFile:path]];
}
self.viewController.images = images;
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
#end
Here is the AppDelegate.h:
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UIViewController *viewController;
#end
I've tried declaring a property like so:
#property (strong, nonatomic) UIImageView *images;
I can't seem to fix this even though I painstakingly merged these two codebases.
Here is the Xcode project of where I'm at at this point:
Xcode project
the "images" property you've declared in your .h file:
#property (strong, nonatomic) UIImageView *images;
is not the NSMutableArray you are trying to assign to it via this line:
self.viewController.images = images;
If you can get the types to be the same (i.e. either a single UIImageView object or a NSMutableArray containing many UIImages), then you should have better luck with assigning things to that property.
I solved it. The problem was that I was merging a project using Storyboards and one that was using programmatically generated ViewController. Well, part of the problem.
Since, I merged the projects I had to give the view controller with the ThumbnailView another name. I named it ElfViewController.
This is the working code:
AppDelegate.h
#import <UIKit/UIKit.h>
#class ViewController;
#class ElfViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) ElfViewController *viewController; // Changed here to ElfViewController
#property (strong, nonatomic) ViewController *firstViewController;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"
#import "ElfViewController.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize viewController = _viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ElfViewController alloc] init]; //Changed here to ElfViewController
self.firstViewController = [[ViewController alloc] init];
NSArray *paths = [[NSBundle mainBundle] pathsForResourcesOfType:#"jpg" inDirectory:nil];
NSMutableArray *images = [NSMutableArray arrayWithCapacity:paths.count];
for (NSString *path in paths) {
[images addObject:[UIImage imageWithContentsOfFile:path]];
}
self.viewController.images = images;
self.window.rootViewController = self.firstViewController;
[self.window makeKeyAndVisible];
}
#end
I'm still new to Objective-C and have only learned how to create ViewControllers in Storyboard and not programmatically.
Also I didn't know that you can declare a property to a specific View Controller rather than just a general UIViewContoller. That's another place I got tripped up.

ivar behave in 2 different way, with same usage

i tried 2 different apps to test few things.
the first app its simple
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
NSMutableString *text;
}
#property (nonatomic, retain)NSMutableString *text;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize text = text;
- (void)viewDidLoad
{
[super viewDidLoad];
text = #"FOO";
NSLog(#"%#", text);
self.text = #"FOO2";
NSLog(#"%#", self.text);
NSLog(#"1:%# - 2:%#", text, self.text);
}
this made things seems like synthesizing with same name, makes them the same variable. cause it print this:
2013-09-05 11:20:14.527 testIvar[12965:c07] FOO
2013-09-05 11:20:14.528 testIvar[12965:c07] FOO2
2013-09-05 11:20:14.529 testIvar[12965:c07] 1:FOO2 - 2:FOO2
even if i use %p to print the address memory of text and self.text i get the same address
*my other app test is this *
AppDelegate.h
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
NSManagedObjectContext *managedObjectContext;
NSManagedObjectModel *managedObjectModel;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
}
#property (strong, nonatomic) UIWindow *window;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#property ( strong, nonatomic ) UINavigationController *navigationController;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "MasterViewController.h"
#implementation AppDelegate
#synthesize managedObjectContext = managedObjectContext;
#synthesize managedObjectModel = managedObjectModel;
#synthesize persistentStoreCoordinator = persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
MasterViewController *masterVC = [[MasterViewController alloc]initWithNibName:#"MasterViewController" bundle:nil];
masterVC.MOC = managedObjectContext;
self.navigationController = [[UINavigationController alloc]initWithRootViewController:masterVC];
[self.window setRootViewController:self.navigationController];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
this app won't work if i do
masterVC.MOC = managedObjectContext;
but only work if i do
masterVC.MOC = self.managedObjectContext;
even if i print the mem address of managedObjectContext and self.managedObjectContext
i get 2 different addresses
how is that possible? same thing in 2 different app, behave in 2 different way?!?!?!?!?!?!?!?!?
masterVC.MOC = self.managedObjectContext; only works because the getter method has been overridden in that case.
See carefully and you will find that in your AppDelegate, there is a method
- (NSManagedObjectContext *)managedObjectContext
When you refer the object by self., the overridden getter method is called.

iOS move database update off the main thread - insert a splash view

I'm new to objective-c so please bear with this long explanation, I hope it will help other beginners. I have been successfully making some changes to an existing iPad app. However, the original install/update routine has hit the failed to launch in time barrier. The posts here have helped me greatly to understand the problem and which direction(s) to research.
I have compiled a solution from different posts here and elsewhere as I did not find a global line-by-line for beginners solution.
I understand that I need to pull the database init/update out of didFinishLaunchingWithOptions and return from here asap with an instantiated UIViewController that will do the DB stuff off the main thread (thanks to all the posters on the subject).
NOTE that the rootVC that is usually called here cannot init if the data is not ready and intact. So just going async on the DB routine doesn't help me because the rootVC gets there first and bombs out when it doesn't find the data it requires.
i.e. I need to delay the rootVC while we do anything we need to do and in peace. I choose to load the UILaunchImage to be seamless and add a spinner.
The question is:
1) Have I done it correctly so that I will never get bitten and 8badf00d again and especially without adding other side effects? Or should I have done it otherwise, maybe in a wrapper init method of the existing rootVC?
2) What about the dealloc, rootViewController or splashViewController? I would think that it is rather rootViewController by this stage. Confused.
3) It works but is this really replacing (and removing) splashViewController by rootViewController as the rootVC? Or am I piling them up...
BEFORE
RAppDelegate.h
#import <UIKit/UIKit.h>
#import "RDataManager.h"
#import "RRootViewController.h"
#import "RScreenViewController.h"
#interface RAppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
RRootViewController *rootViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, readonly) RRootViewController *rootViewController;
#end
RAppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[RDataManager sharedManager] updateDatabase]; // This is what takes time...
rootViewController = [[RRootViewController alloc] initAtScreen:kScreenTypeIndex withCar:carId];
rootViewController.wantsFullScreenLayout = YES;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
...
- (void)dealloc
{
[rootViewController.view removeFromSuperview];
[rootViewController release];
[window release];
[super dealloc];
}
AFTER
RAppDelegate.h
#import <UIKit/UIKit.h>
#import "RDataManager.h"
#import "RScreenViewController.h"
#import "RSplashViewController.h"
#interface RAppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
RSplashViewController *splashViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, readonly) RSplashViewController *splashViewController;
#end
RAppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
splashViewController = [[RSplashViewController alloc] init];
splashViewController.wantsFullScreenLayout = YES;
self.window.rootViewController = splashViewController;
[self.window makeKeyAndVisible];
return YES;
}
...
- (void)dealloc
{
[splashViewController.view removeFromSuperview];
[splashViewController release];
[window release];
[super dealloc];
}
RSplashViewController.h
#import <UIKit/UIKit.h>
#import "RRootViewController.h"
#interface RSplashViewController : UIViewController
{
UIImageView *splashImageView;
RRootViewController *rootViewController;
UIActivityIndicatorView *spinner;
}
#property (nonatomic, retain) UIImageView *splashImageView;
#property (nonatomic, readonly) RRootViewController *rootViewController;
#end
RSplashViewController.m
#import "RSplashViewController.h"
#import "RDataManager.h"
#interface RSplashViewController ()
#end
#implementation RSplashViewController
#synthesize splashImageView;
#synthesize rootViewController;
- (void) loadView
{
CGRect appFrame = [UIInterface frame];
UIView *view = [[UIView alloc] initWithFrame:appFrame];
self.view = view;
[view release];
NSString *splashFile = [[NSBundle mainBundle] pathForResource:#"LaunchImage-jaguar-Landscape~ipad" ofType:#"png"];
UIImage *splashImage = [[UIImage alloc] initWithContentsOfFile:splashFile];
splashImageView = [[UIImageView alloc] initWithImage:splashImage];
[self.view addSubview:splashImageView];
[splashImage release];
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
CGRect frame = spinner.frame;
frame.origin.x = CGRectGetMidX(self.view.frame) - CGRectGetWidth(spinner.frame) / 2;
frame.origin.y = 650;
spinner.frame = frame;
spinner.hidesWhenStopped = YES;
[self.view addSubview:spinner];
[spinner startAnimating];
}
- (void) viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// how we stop DB refresh from freezing the main UI thread
dispatch_queue_t updateQueue = dispatch_queue_create("updateDB", NULL);
dispatch_async(updateQueue, ^{
// do our long running process here
[[RDataManager sharedManager] updateDatabase];
// do any UI stuff on the main UI thread
dispatch_async(dispatch_get_main_queue(), ^{
[spinner stopAnimating];
[splashImageView removeFromSuperview];
rootViewController = [[RRootViewController alloc] initAtScreen:kScreenTypeGarage withCar:nil needSplashScreen:YES];
[self.view addSubview:rootViewController.view];
});
});
dispatch_release(updateQueue);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) dealloc
{
[super dealloc];
}
#end
To answer my questions.
1) Yes this is safe, either with SplashViewController or rootVC init wrapper. Ran it as ad-hoc for 2 minutes no problems. Double checked that the update was indeed running in a separate thread (Xcode debug window pane).
2) Non issue since I moved to a rootVC init wrapper solution and reverted to dealloc'ing rootViewController.
3) Problem solved by 2).
I also managed to reduce the update time by 90% which is the ideal solution anyway, but good to know that I am also safely out of the way of the watchdog timer.

Resources