Error Message NSData - ios

I need to display an RTF file in a UITextView. My code looks like below:
My .h file:
#property (strong, nonatomic) IBOutlet UITextView *creditsTextView;
My .m file
#synthesize creditsTextView;
- (void)viewDidLoad {
[super viewDidLoad];
NSData *creditsData = [[NSBundle mainBundle] pathForResource:#"Credits" ofType:#"rtf"];
NSAttributedString *attrString;
NSDictionary *docAttributes;
attrString = [[NSAttributedString alloc]
initWithRTF: creditsData documentAttributes: &docAttributes];
}
This code gives me the following Error messages:
at
*creditsData : Incompatible pointer types 'NSData *' with expression of type 'NSString *'
and at
initWithRTF : No visible #interface for 'NSAttributedString' declares the selector 'initWithRTF:documentAttributes:'
How can I fix these two errors?

This method:
NSString *path = [[NSBundle mainBundle] pathForResource:#"Credits" ofType:#"rtf"];
Returns the path were your file is.
If, after you have the path, you want to read the file, use this:
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:path]];
Find the documentation here:
NSBundle Class Reference
NSData Class Reference
Also, there's no method called InitWithRTF in NSMutableAttributedString.

[[NSBundle mainBundle] pathForResource: returns type NSString, see NSBundle Class Reference, so you cannot directly assign NSData with NSString, so you can pass the returned URL to NSData with a different initialiser.
And NSAttributedString does not have an init method called initWithRTF. These are why you are seeing the errors.

Related

No visible #interface for NSURL declares the selector componentsseparatedbystring

The NSArray declaration brings up an error because "no visible #interface for NSURL declares the selector componentsseparatedbytring".
NSURL *MyURL = [[NSBundle mainBundle]
URLForResource: #"artList" withExtension:#"txt"];
NSArray *lines = [MyURL componentsSeparatedByString:#"\n"]; // each line, adjust character for line endings
for (int i = 0; i < 10; i++) {
NSString *line;
//in lines;
NSLog(#"%#", [NSString stringWithFormat:#"line: %#", line]);
_wordDefBox.text = [NSString stringWithFormat:#"%#%#",_wordDefBox.text, lines];
}
You missed a step. Once you have the URL, you need to load the file into an NSString. Then call componentsSeparatedByString on the NSString.
NSURL *myURL = [[NSBundle mainBundle]
URLForResource: #"artList" withExtension:#"txt"];
NSError *error = nil;
// Use the appropriate encoding for your file
NSString *string = [NSString stringWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:&error];
if (string) {
NSArray *lines = [string componentsSeparatedByString:#"\n"];
// and the rest
} else {
NSLog(#"Unable to load string from %#: %#", myURL, error);
}
In general when you see such an error it means class X( here NSURL) doesn't have any method named Y ( e.g. componentsseparatedbystring) or at least it doesn't have it in its interface ie it's not it's public method, it may be it's private method and available to its implementation. Always try to make sense of what the compiler is telling you. To find out more you can 'Cmmd + click' on any class and it will take you to it's interface and you can see what public methods it has. Try that on NSString and NSURL
Here specifically : NSURL doesn't have that method. It doesn't belong to NSURL, it belongs NSString.

How to read .m file as NSString in iOS

I am trying to display an implementation file(Code inside the .m file) in UITextView. Below is the code snippet i used. But it returns nil.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"TextCheck.m" ofType:#"m"];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"TextCheck.m" ofType:#"m"];
Replace the code as below line :
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"TextCheck" ofType:#"m"];
I really doubt you can do this. The source code is not a 'resource'..When you execute the app they are in binary form.. there is no code in there..
If you need to do display something that you know already - try storing the text/code you intend to display in a plain file and display..

NSAttributedString to NSData No visible #interface for 'NSAttributedString' declares the selector 'RTFDFromRange:documentAttributes:

I am trying to convert NSAttributedString to NSData using RTFDFromRange method. Getting this:
No visible #interface for 'NSAttributedString' declares the selector 'RTFDFromRange:documentAttributes:
What is wrong with my code?
NSAttributedString *val=self.textview.attributedText;
NSData *data = [val RTFDFromRange:NSMakeRange(0, self.textview.text.length) documentAttributes:nil];
NSAttributedString does not have a method called RTFDFromRange for iOS, but only for Mac OS X.
To convert NSAttributedString to NSData in iOS, you can try these two approaches:
1. Using initWithData:
NSMutableAttributedString *val = [[NSMutableAttributedString alloc] initWithData:data options:nil documentAttributes:nil error:nil];
2. Using NSKeyedArchiver:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject: val];
And to convert the NSData back to a string:
NSAttributedString *val = [NSKeyedUnarchiver unarchiveObjectWithData: data];
This code works on both Mac and iOS.
See the Apple docs here.
That method is only available under Cocoa (OSX) as it's part of the AppKit Additions to NSAttributedString.
Here's an open source category that might do what you want under iOS (not personally tested, however).

How to access dictionaries within other methods?

Below is the code I am using to try and access the initialised dictionary with another method:
#import "UserFoodData.h"
#implementation UserFoodData
-(void)loadUserFoodData{
NSString *appDataPath = [[NSBundle mainBundle] pathForResource:#"UserFoodData" ofType:#"plist"];
NSMutableDictionary *userFoodDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:appDataPath];
for (userFoodDictionary in userFoodDictionary){
NSLog(#"%#", userFoodDictionary);
}
}
-(void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount{
[userFoodDictionary setObject:foodName forKey:foodName];
}
#end
The error messages I seem to be getting is:
Use of undeclared identifier 'userFoodDictionary'
Now what I believe is wrong is that the compiler believes that there is a possibility that the setName:andCarbs method could but executed before the loadUserFoodData Which is called when the apps main screen has been initialised. Could someone please help me with a work around?
The error messages I seem to be getting is:
Use of undeclared identifier 'userFoodDictionary'
Compiler says:
1. I didn't see any variable like userFoodDictionary locally or instance variable in -(void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount.
2. But you are trying to access it.
and also your for loop has mistakes. please verify my answer
Compiler is trying to look for userFoodDictionary in "UserFoodData" class. Because you are accessing userFoodDictionary outside of loadUserFoodData method. So in order to access outside of local method you must keep that reference in header file then you can access it any where in class.
#interface UserFoodData : NSObject
#property(nonatomic,retain)NSMutableDictionary *userFoodDictionary;
#end
#import "UserFoodData.h"
#implementation UserFoodData
//#synthesize userFoodDictionary; synthesise is automatically entered by compiler
-(void)loadUserFoodData{
NSString *appDataPath = [[NSBundle mainBundle] pathForResource:#"UserFoodData" ofType:#"plist"];
self.userFoodDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:appDataPath];
//Please not down this
for (id aFood in userFoodDictionary){
NSLog(#"%#", aFood);
}
}
-(void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount{
[self.userFoodDictionary setObject:foodName forKey:foodName];
}
#end
I'm assuming you get the error in the second method that you posted.
- (void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount{
[userFoodDictionary setObject:foodName forKey:foodName];
}
userFoodDicitionary is not defined in that method. If you want the dictionary to persist between method calls, store it in a #property.
You should really read some introductory material to Objective-C, you could start with this Apple document
There are multiple issues here...
For one, your for loop has a syntax error...not only that, but you're trying to iterate through a dictionary named userFoodDictionary with an iterator variable also named userFoodDictionary. Change that to something like:
for (id dictKey in userFoodDictionary) {
NSLog(#"%#", dictKey);
}
You're also trying to access a variable out of scope. userFoodDictionary is declared within the scope of loadUserFoodData. After that method completes, the variable is deallocated, so of course you can't access it in setName:andCarbs:. To do that, you need to define it in a wider scope -- make a property, a static variable, an iVar, etc.
There are many lacking OOP concepts here...if you are new to programming, Objective-C is a difficult place to start, and it may throw you for many loops (pun intended).
Try this...
#import "UserFoodData.h"
#implementation UserFoodData
-(void)loadUserFoodData{
NSString *appDataPath = [[NSBundle mainBundle] pathForResource:#"UserFoodData" ofType:#"plist"];
NSMutableDictionary *userFoodDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:appDataPath];
for (userFoodDictionary in userFoodDictionary){
NSLog(#"%#", userFoodDictionary);
}
}
-(void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount{
NSString *appDataPath = [[NSBundle mainBundle] pathForResource:#"UserFoodData" ofType:#"plist"];
NSMutableDictionary *userFoodDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:appDataPath];
[userFoodDictionary setObject:foodName forKey:foodName];
}
#end
Let me know if that helps... :)
I think the issue is your NSMutableDictionary should be ivar that is declare NSMutableDictionary in .h as follow
NSMutableDictionary *userFoodDictionary
in .m
-(void)loadUserFoodData{
NSString *appDataPath = [[NSBundle mainBundle] pathForResource:#"UserFoodData" ofType:#"plist"];
userFoodDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:appDataPath];
for (userFoodDictionary in userFoodDictionary){
NSLog(#"%#", userFoodDictionary);
}
}
-(void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount{
[userFoodDictionary setObject:foodName forKey:foodName];
}
So the issue is in the below line
for (userFoodDictionary in userFoodDictionary){
NSLog(#"%#", userFoodDictionary);
}
replace it with
for (NSMutableDictionary *userFoodDic in userFoodDictionary){
NSLog(#"%#", userFoodDic);
}
May this will solve your issue
ok Got the other issue too
Please declare the userFoodDictionary as one of the property too
as described by #Sebastian in his answer :)

TableViewController crashes when calling a retained property?

I have a Table View Controller and during its initialisation I set an NSArray property which is then used in the cellForRowAtIndexPath method to display the data on the table.
But, when I touch a row, once I call this retained NSArray property it says EXC_BAD_ACCESS!
FYI the property is defined as shown below, and uses a custom getter function:
#property (nonatomic,retain) NSArray *dataList;
and in the .m file:
#synthesize dataList;
- (NSArray *)dataList
{
if (!dataList)
{
NSString *p = [kind lowercaseString];
NSString *s = [[NSBundle mainBundle] pathForResource:p ofType:#"txt"];
NSLog(#"%#",s);
NSData *dataRep = [NSData dataWithContentsOfFile:s];
NSPropertyListFormat format;
dataList = [NSPropertyListSerialization propertyListFromData: dataRep
mutabilityOption: NSPropertyListImmutable
format: &format
errorDescription: nil];
if (dataList.count == 0)
NSLog(#"Fetch failed!");
}
return dataList;
}
Any suggestions?
This is the problem:
dataList = [NSPropertyListSerialization propertyListFromData ...
This function does not begin with alloc, copy, or retain, therefore it returns an autoreleased object. However, you need it to be retained so that it stays around.
You have two options:
self.dataList = [NSPropertyListSerialization propertyListFromData ...
or,
dataList = [[NSPropertyListSerialization propertyListFromData ...] retain];

Resources