I don't know why this code error.
Please help.
I read some articles and I think the problem is about context.
What Should I do?
This program is about shows data in coredata to label in viewcontroller.
AppDelegate.h
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#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;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "Test.h"
#import "ViewController.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSManagedObjectContext *context = [self managedObjectContext];
Test *t = [NSEntityDescription insertNewObjectForEntityForName:#"Test"
inManagedObjectContext:context];
t.name = #"please";
return YES;}
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *label;
#property (nonatomic,strong) NSArray *temp;
#property (nonatomic,strong) NSManagedObjectContext* managedObjectContext;
#end
ViewController.m
#import "ViewController.h"
#import "Test.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize managedObjectContext;
#synthesize temp;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Test"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error;
self.temp = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
for(Test *info in temp){
_label.text = info.name;
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Test.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface Test : NSManagedObject
#property (nonatomic, retain) NSString * name;
#end
Test.m
#import "Test.h"
#implementation Test
#dynamic name;
#end
I don't know why this code error.
Please help.
I read some articles and I think the problem is about context.
What Should I do?
In your view controller, replace the line:
#synthesize managedObjectContext;
With this:
- (NSManagedObjectContext *) managedObjectContext {
return ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext;
}
Instead of storing another, different object context in your view controller, this property will return the object context that you set up in the app delegate.
There are other ways to do this, such as creating a Core Data helper class following the Singleton pattern (as #NewYork167 suggests), but this should at least solve your current problem.
For any future reference, you can also try subclassing the NSManagedObjectContext like this:
#interface MyManagedObjectContext : NSManagedObjectContext
+ (MyManagedObjectContext *)mainThreadContext;
#end
#implementation MyManagedObjectContext
+ (MyManagedObjectContext *)mainThreadContext;
{
static MyManagedObjectContext *moc;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
moc = [[self alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
// Setup persistent store coordinator here
});
return moc;
}
#end
Reference: Best practices for passing NSManagedObjectContext around to UITabBarController child view controllers?
[self.managedObjectContext deletedObjects:lastPoint];
This line shows me an error
No visible #interface for 'NSManagedObjectContext' declares the selector 'deletedObjects'.
Here is my code
can any one solve this?
Appdelegate.h
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#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;
#end
Appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/* crete the fetch request first*/
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]initWithEntityName:#"Rectangle"];
NSError *requestError = nil;
/*And execute the fetch request on the context*/
NSArray *rectangle = [self.managedObjectContext executeFetchRequest:fetchRequest error:&requestError];
/*make sure we get the array*/
if ([rectangle count] > 0) {
/*delete the last person in the array*/
Rectangle *lastPoint = [rectangle lastObject];
[self.managedObjectContext deletedObjects:lastPoint];
if ([lastPoint isDeleted]) {
NSLog(#"Successfully deleted the last point...");
NSError *savingError = nil;
if ([self.managedObjectContext save:&savingError]) {
NSLog(#"successfully saved the context");
} else {
NSLog(#"Failed to save the context");
}
} else {
NSLog(#"Failed to delete the last point");
}
} else {
NSLog(#"Could not find any rectangle entities in the context.");
}
return YES;
}
The error message
No visible #interface for 'NSManagedObjectContext' declares the
selector 'deletedObjects'.
tells you that the class NSManagedObjectContext doesn't implement the method deletedObjects. You can check this in the API documentation.
You can use deleteObject: to delete single objects. So change your code to:
[self.managedObjectContext deleteObject:lastPoint];
As the documentation says deletedObjects is the read only property, so it has only getter method without any parameters
So you should access it just by using next
self.managedObjectContext.deletedObjects
I have variable in my AppDelegate.m called message, that i would like to use in a view controller, but it's not working. I've tried this solution:
If i import the AppDelegate.m into my ViewController.m, i get an error: clang: error: linker command failed with exit code 1 (use -v to see invocation), but if i don't import it i get this: No known class method for selector 'message' at this line: self.toSort = [AppDelegate message];. But when i import ViewController.m into AppDelegate.m i don't get the linker command error, however the other error already exists.
My AppDelegate.h
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, strong) PNChannel *myChannel;
- (void)getMessage;
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.m"
static NSArray *_message = nil;
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// [self.window makeKeyAndVisible];
self.myChannel = [PNChannel channelWithName:currentChannel.username
shouldObservePresence:YES];
[self getMessage];
}
+ (NSArray *)message
{
if (_message)
return _message;
AppDelegate *appDelegate =(AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate getMessage];
return nil;
}
- (void)getMessage {
[PubNub requestFullHistoryForChannel:self.myChannel withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {
_message = contentArray;
NSLog(#"test log %#", _message);
}];
}
ViewController.m
#import "ViewController.h"
//#import "AppDelegate.h"
//#import "AppDelegate.m"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated {
//AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
//[appDelegate getMessage];
self.toSort = [AppDelegate message];
[self getMessageList];
}
I'm sure i did some beginner mistake, but i can't figure it out. The "test log" works, so i think i have to call it in a different way.
Already tried this, but also get an error because message is not a property.
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSArray *variableTest = appDelegate.message;
NSLog(#"TEST : %#",variableTest);
UPDATE: I've tried this, but the test log shows null, so something is still wrong.
AppDelegate.h
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, strong) PNChannel *myChannel;
#property (strong, nonatomic) NSArray *message;
- (void)getMessage;
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// [self.window makeKeyAndVisible];
self.myChannel = [PNChannel channelWithName:currentChannel.username
shouldObservePresence:YES];
[self getMessage];
}
return YES;
}
+ (NSArray *)message
{
if (self.message)
return self.message;
AppDelegate *appDelegate =(AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate getMessage];
return nil;
}
- (void)getMessage {
[PubNub requestFullHistoryForChannel:self.myChannel withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {
self.message = contentArray;
NSLog(#"dev log %#", self.message);
}];
}
ViewController.m
- (void)viewWillAppear:(BOOL)animated {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSArray *variableTest = appDelegate.message;
NSLog(#"TEST : %#",variableTest);
}
My try based on o Pi's answer:
#interface MessageHistoryData : NSObject {
NSArray *yourData;
}
#property(nonatomic,retain) NSArray *yourData;
+(MessageHistoryData *)getInstance;
#end
#import "MessageHistoryData.h"
#implementation MessageHistoryData #synthesize yourData;
static MessageHistoryData *instance =nil;
+(MessageHistoryData *)getInstance {
#synchronized(self) {
if(instance==nil) {
instance= [MessageHistoryData new];
}
}
return instance;
}
#end
in my ViewController.m (MessageHistoryData is imported into the .h)
-(void)setupArray {
[PubNub requestHistoryForChannel:my_channel from:nil to:nil limit:100 reverseHistory:NO withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {
MessageHistoryData *data = [MessageHistoryData getInstance];
data.yourData = contentArray;
NSLog(#"Dev log2 %#", data.yourData);
}];
}
I set up a sample project to verify that this works.
In the AppDelegate.h file, publicly declare the message property and -getMessage method:
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (readonly, nonatomic) NSString *message;
- (void)getMessage;
#end
In the AppDelegate.m file, implement your methods as you normally would (I explicitly set the property for the sake of example):
#import "AppDelegate.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
- (void)getMessage {
self.message = #"This is a message";
}
#end
In your ViewController.m file, you should import the AppDelegate header, and you should be free to access the properties:
#import "AppDelegate.h"
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
NSLog(#"The delegate's message is: %#", delegate.message); // Logs "The delegate's message is: (null)"
[delegate getMessage];
NSLog(#"The delegate's message is: %#", delegate.message); // Logs "The delegate's message is: This is a message"
}
#end
If the above doesn't work, you should test your PubNub class and ensure it's behavior is predictable.
I don't recommend EVER storing information in your AppDelegate, as that makes the class responsible for doing more than just being your application's delegate with the system. Information like this should be stored in a dedicated store, or made available through a custom PubNub subclass that is accessed as a singleton (if there's no global state to be managed!) or an instance by instance basis.
Let me know if you need any clarification or if the solution above doesn't work for you.
EDIT: Singleton Suggestion
As per my comment, here is one way to handle sharing network data across view controllers
#interface NetworkClient : PubNub
#property (readonly, nonatomic) NSString *message;
/**
* Returns a shared network client to be used throughout the app
*/
+ (instancetype)sharedClient;
- (void)configureWithChannel:(PNChannel*)channel;
- (void)clearChannel;
- (void)getMessagesWithCompletionHandler:(void (^)(NSArray *, PNChannel *, PNDate *, PNDate *, PNError *))
#end
Where sharedInstance uses the technique described here to setup your instance. From there, you can access the client using [NetworkClient sharedClient] and retrieve any data through the instance methods or properties on the client.
I'm also guessing you are new to singletons or iOS in general, so I'm going to recommend you read this article about using singletons, and the blog objc.io to familiarize yourself with some best practices that will absolutely make your life easier.
First there is no need to declare the variable static since [UIApplication sharedAppliction] delegate] will always be the same instance. So just declare a property in the AppDelegate.h file and use that.
in AppDelegat.h
#property(nonatomic, strong) NSArray *message;
in AppDelegate.m use it like this:
self.message
And in your view controller import the .h and do:
AppDelegate *appDelegate =(AppDelegate *)[[UIApplication sharedApplication] delegate];
NSArray *arr = appDelegate.message;
You have to put public variables into your header file.
Your getMessage method uses an async call to get the messages. If you can't retrieve it in a sync way maybe you should call getMessage as soon as possible.
Better yet you could also use blocks to return the messages async:
+ (void)asyncMessage:(void(^)(NSArray * message))callbackBlock
{
if (_message)
{
callbackBlock(_message);
return;
}
[PubNub requestFullHistoryForChannel:self.myChannel withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {
_message = contentArray;
callbackBlock(_message);
NSLog(#"test log %#", _message);
}];
}
never import .m class in xcode because this throws cling: error.
if u want to NSArray defined in appdelegate to use later in your any view controller,there may be many approaches.some of them are-
initilise your array in appdelegate.h like this
#property(nonatmoic,retain)nsarray *message;
then in your appdelegate.m class in didfinishlaunchingwithOptions method allocate memory to this array-
message=[[nsarray alloc]initwithobjects:#"abc"];
then in your view controller make object of app delegate and access this property like this-
NSLog(#"array is %#",appdelegateobject.message);
In your first question you trying to return this array by class method,but in appdelegate you returning nil,so how will u get this message array,
Take the message variable and paste it into the .h then delete it from the .m
You can not import a implement file in your implement file like this.
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.m" // This is the reason causes error.
I made this errors before....
Modify like this easily fix this problem.
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"
you need to properties the message array to make public
AppDelegate.h
#property (strong, nonatomic) NSArray *message;
Hope it helps you..
Im new to Objective-C and CoreData and want to learn it and im trying in Xcode 5, im trying to make this tutorial.
I have followed it with some other CoreData table name, but i get some errors with my "ViewController.m" and dont know what to changes, i can see it recomment to changes "NSEntityDescription" to "kSetAttrDescription" but dont know if thats right or wrong to do, hope someone can tell mewhat to do - so i know it next time.
Error issues
Error Descriptions
My ViewController.m code.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//Save data as CoreData, to CoreData Table "Kunder" field "navn", "adresse", "alder" from textfield _name.text, _adress.text, _age.text.
- (IBAction)saveData:(id)sender {
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *newContact;
newContact = [NSEntityDescription insertNewObjectForEntityForName:#"Kunder" inManagedObjectContext:context];
[newContact setValue: _name.text forKey:#"navn"];
[newContact setValue: _adress.text forKey:#"adresse"];
[newContact setValue: _age.text forKey:#"alder"];
//if textfield empty, then error else save and show label message "Kunde Gemt".
_name.text = #"";
_adress.text = #"";
_age.text = #"";
NSError *error;
[context save:&error];
_status.text = #"Kunde Gemt";
}
//Find-search for user by name.
- (IBAction)findKunde:(id)sender {
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"Kunder" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *pred =
[NSPredicate predicateWithFormat:#"(navn = %#)", _name.text];
[request setPredicate:pred];
NSManagedObject *matches = nil;
//if no user then error, else take name match and get "adresse" and "alder" from CoreData and show it in the text fields _adress.text and _age.text and show matche count in status label.
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if ([objects count] == 0) {
_status.text = #"Ingen fundet";
} else {
matches = objects[0];
_adress.text = [matches valueForKey:#"adresse"];
_age.text = [matches valueForKey:#"alder"];
_status.text = [NSString stringWithFormat: #"%lu antal fundet", (unsigned long)[objects count]];
}
}
#end
My ViewController.h page (no error)
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UITextField *name;
#property (strong, nonatomic) IBOutlet UITextField *adress;
#property (strong, nonatomic) IBOutlet UITextField *age;
#property (strong, nonatomic) IBOutlet UILabel *status;
- (IBAction)saveData:(id)sender;
- (IBAction)findKunde:(id)sender;
#end
My AppDelegate.m file
#import "AppDelegate.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
return YES;
}
....
#end
UPDATE
When adding text to the fields and hit save, i don get a "Save ok" message it jump to xcode and show me this.
Is seems that you forgot to import <CoreData/CoreData.h>.
You can add the import to your precompiled header (...-Prefix.pch) file
which would look similar to this:
#import <Availability.h>
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h> // <-- Add this !!
#endif
You might also have to add the "CoreData.framework" to the "Link Binary With Libraries"
section of the targets "Build Phases".
Pls help me with this:
The AppDelegate has an argument called "user":
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
User *user;
}
#property (nonatomic, retain) User *user;
and I init the user instance in the frist viewController:
User *userInfo = [[User alloc] initWithRealName:realName UserId:userId];
and set the user to AppDelegate's:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.user = userInfo;
In the second viewController, I can get the use's realName,there is no problem:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *realName = appDelegate.user.realName;
But when I push to another viewController,and I want to get the user's realName like just now,
but there is an error:EXC_BAD_ACCESS:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
User *user = appDelegate.user;
NSLog(#"I am in noticeDetailViewController:%#",user.realName);***//ERROR***
And I want to know why? and how to fix this error.
Thanks!
User.h & User.m
#interface User : NSObject
{
NSString *realName;
NSString *userId;
}
#property (nonatomic, retain)NSString *realName;
#property (nonatomic, retain)NSString *userId;
- (id)initWithRealName :(NSString *)realNameArgument UserId :(NSString *)userIdArgument;
#end
#implementation User
#synthesize realName,userId;
- (id)initWithRealName :(NSString *)realNameArgument UserId :(NSString *)userIdArgument
{
self = [super init];
if (self)
{
realName = realNameArgument;
userId = userIdArgument;
}
return self;
}
- (void)dealloc
{
[super dealloc];
[realName release];
[userId release];
}
#end
AppDelegate does not retain user, so it gets deallocated before you try to access it in:
NSLog(#"I am in noticeDetailViewController:%#",user.realName);***//ERROR***
So Change AppDelegate by creating a retained property:
#interface AppDelegate : UIResponder <UIApplicationDelegate> {
// ...
#property (retain, nonatomic) User*user;
// ..
And don't forget to synthesize it.
Also change the init method of user to:
- (id)initWithRealName:(NSString *)realNameArgument UserId:(NSString *)userIdArgument
{
self = [super init];
if (self) {
self.realName = realNameArgument;
self.userId = userIdArgument;
}
return self;
}