In some of my screens in my program the localized strings work and in some it doesn't.
(Xcode 4.2)
What I've done:
Added a Localizable.strings in the folder "Resources"
in my .h file, inside the #interface ClassViewController : UIViewController {} I added:
IBOutlet UILable *labelName;
Also in the .h file, I added
property (nonatomic, assign) IBOutlet UILabel *labelName;
In the .m file, I added :
#synthetize labelName;
Still in the .m file, I added inside "-(foid)dealloc" :
[labelName release];
In -(void)viewDidLoad I added :
self.labelName.text = [NSString stringWithFormat:#"KEY"];
Finally, in the xib file (with the Interface manager), I linked the label object with the variable.
So, as I said, this method works in some screen and not in others. Any idea?
Solution:
That what a stupid mistake. the line to enter the text should be:
NSLocalizedString(#"KEY", nil);
Use instead:
self.labelName.text = NSLocalizedString(#"KEY", "");
From the Documentation:
Name: NSLocalizedString
Description: NSString *NSLocalizedString(NSString *key, NSString *comment)
Availability: iOS (2.0 and later)
Abstract: Returns a localized version of a string.
As Vince pointed out, you need to use NSLocalizedString function. So in this case the code in 6 would be:
self.labelName.text = NSLocalizedString(#"The key for this label",#"Some comment");
That should work for you.
In XCode-4.2 you can do the following:
Click on "target"
Then select "Build Phase"
Select "Add Build Phase" & choose "Add Copy files".
After select "copy files(int item)".( where 'int' may be 1or 2 or 3 etc. depending upon how many items previously have been created).Set "Destination" to "Resources".
Now click on '+' & choose your created '.string' file(eg. localization.string).
It works, hope it will help you.
What do you imagine this line does?
self.labelName.text = [NSString stringWithFormat:#"KEY"];
Because it's functionally equivalent to writing this:
self.labelName.text = #"KEY";
But I suspect that what you meant to write was this instead:
self.labelName.text = NSLocalizedString(#"KEY", #"description");
Related
I am trying making a simple iphone app that copies text from one field to another when you press a button (text1 values into text2), but I am getting my some warnings "Attributes on method implementation and its declaration must match" and "Incompatible pointer types sending 'UITextField *' to parameter of type 'NSString *". Both text1 and 2 and declared as UITextField. The warnings are in the setText line.
#import "APPViewController.h"
#interface APPViewController ()
#end
#implementation APPViewController
-(IBAction)copy:(id)sender
{
[text2 setText:text1];
}
#end
text1 is a UITextField *, not an NSString *. You need to ask text1 for its contents by sending it the text message.
[text2 setText:[text1 text]];
You can also use “dot notation”, like this:
text2.text = text1.text;
The second form compiles into exactly the same executable code as the first form.
I'm trying to use this project which is a synthesizer for Objective-C for an iPhone application I'm building. However, I'm having trouble with the MHAudioBufferPlayer class.
In the MHAudioBufferPlayer.m class, I'm getting a bunch of Use of undeclared identifier errors for _gain, _playing, and _audioFormat. This makes sense, as those identifiers are never declared with an underscore in front of them. However, they are declared in the MHAudioBufferPlayer.h class without the underscores.
I'm sort of confused by this as I'm new to Objective-C. Does an underscore denote a special action to be taken? Is it supposed to be translated into self.gain, self.playing, etc.? How can I fix this? Or is this code just buggy?
- (id)initWithSampleRate:(Float64)sampleRate channels:(UInt32)channels bitsPerChannel:(UInt32)bitsPerChannel packetsPerBuffer:(UInt32)packetsPerBuffer
{
if ((self = [super init]))
{
_playing = NO;
_playQueue = NULL;
_gain = 1.0;
_audioFormat.mFormatID = kAudioFormatLinearPCM;
_audioFormat.mSampleRate = sampleRate;
_audioFormat.mChannelsPerFrame = channels;
_audioFormat.mBitsPerChannel = bitsPerChannel;
_audioFormat.mFramesPerPacket = 1; // uncompressed audio
_audioFormat.mBytesPerFrame = _audioFormat.mChannelsPerFrame * _audioFormat.mBitsPerChannel/8;
_audioFormat.mBytesPerPacket = _audioFormat.mBytesPerFrame * _audioFormat.mFramesPerPacket;
_audioFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
_packetsPerBuffer = packetsPerBuffer;
_bytesPerBuffer = _packetsPerBuffer * _audioFormat.mBytesPerPacket;
[self setUpAudio];
}
return self;
}
If you are using new compiler that comes with Xcode4.4 onwards, then for each of your property it creates an automatic synthesize with _(underscore) as prefix.
Like, if you have created #property.... playing;
then the compiler creates #synthesize playing=_playing;
If you are in older versions of Xcode, this need to be done manually.
#synthesize generated by Xcode => 4.4 as the default. The generated private instance variable, ivar, created for you by Xcode has a leading underscore '' if you don't explicitly create your own #synthesize statement. You MUST include the leading '' when sending messages to this
property (typically UI element as an outlet from your controller.m file).
That is
#property textField;
[_textField setStringValue: #"foo"]; if you DON'T write the '#synthesize'.
The compiler's done this for you, and has made a private instance variable by synthesizing the getter/setters. The convention is to make the private ivar the name of the property prepended by the leading underscore.
OR
#synthesize textField;
#property textField;
[textField setStringValue: #"foo"]; if you DO write your own '#synthesize' or are < Xcode 4.4.
Here, the complier has NOT done it for you, your ivar name/property name are the same and can be used w/o the leading '_'.
Good luck.
Depending on what version of XCode you are using, and compiler there are different ways of doing it. I don't know how familiar you are with OOP, if you are not I suggest you read up a bit on setters and getters and objects as it is the basis of almost everything you will do from now on.
Some examples, Old school style, will create an ivar. In your .h:
#interface TheViewController : UIViewController{
NSString *theString;
}
A bit new style, will create setter and getter In your .h.
#interface TheViewController : UIViewController
#property (nonatomic, weak) NSString *theString;
In your .m file:
#implementation TheViewController
#synthesize theString = _theString;
Can be accessed by _theString or self.theString
The new way of doing it. In your .h file:
#property (nonatomic, weak) NSString *theString;
The compiler Will create everything the above way did.
Hope that helps you a bit.
my app make a simple file called log.txt
the URL of this file (viewed in xcode) is file://localhost/var/mobile/Applications/NUMBER OF THE APPLICATION/Documents/log.txt
So I can see this file in the finder ...
I wanted to add the "open in" feature to my app to provide the user to share this file (via mail or imessage) or open this file in another compatible app.
Here is what I do :
-(void) openDocumentIn {
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:docFile]; //docFile is the path
//NSLog(#"%#",fileURL); // -> shows the URL in the xcode log window
UIDocumentInteractionController *documentController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
documentController.delegate = self;
documentController.UTI = #"public.text";
[documentController presentOpenInMenuFromRect:CGRectZero
inView:self.view
animated:YES];
}
Then the call to this function :
-(IBAction)share:(id)sender {
[self openDocumentIn];
}
When I run the app, I click on this "share" button, but nothing appends except showing me the path of the URL in the log window ...
I missed something ...
Thanks
EDIT : finally, it works on my real iphone ... there was no text viewer in the simulator !!! --'
EDIT 2 : it shows the apps that are available (pages, bump ...) but crashes finally :((( ! see here for the crash picture
Its a memory management issue. The main reason it crashes is because the object is not retained. Thats why if you declare it in the .h file and write an #property for retain when you do assign it the object gets retained.
So in your interface file (.h) you should have
#property (retain)UIDocumentInteractionController *documentController;
Then in your .m (implementation file) you can do
#synthesize documentController;
- (void)openDocumentIn{
// Some code here
self.documentController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
documentController.delegate = self;
documentController.UTI = #"public.text";
[documentController presentOpenInMenuFromRect:CGRectZero
inView:self.view
animated:YES];
// Some more stuff
}
Here is how it works for me :
I just put the declaration "UIDocumentInteractionController *documentController" in the .h file and it works !
I really don't know why, but ....
I am setting the value for the string in the viewdidload method and getting the string value in the button action method the app gets crashed. can I know the reason for crashing and how to pass the values to the method.
in .h file
NSString *test;
in .m file
-(void)viewDidLoad
{
test = [NSString stringWithFormat:#"sample"];
}
-(IBAction) buttonPressed:(id)sender
{
NSLog(#"%#", test);
}
When I pressed the button the app crashes.
Please try using this solution, I think this will help you,
Create Property of test in .h file like this,,
#property(nonatomic,retain) NSString *test;
and synthesize it in .m file like this,
#synthesize test;
now use test as self.test in .m file like this,
-(void)viewDidLoad
{
self.test = [NSString stringWithFormat:#"sample"];
}
-(IBAction) buttonPressed:(id)sender
{
NSLog(#"%#", self.test);
}
Another solution for this is just retain that test string in ViewDidLoad also, I think this will also help you..
Hope this will help you..
Let me try to explain it in more detail:
You have a string variable in .h file. In view did load you are assigning it as:
test = [NSString stringWithFormat:#"sample"];
What actually happning in this code is your test is a autoreleased object. When you use this and object without alloc and init this is autoreleased object and will release memory after the method you occupied it.
For avoiding this situation you can use #Mehul's solution by creating property. This is against encapsulation concept. Sometimes you have objects you don't want to access outside of the class or don't want to show with objects. Use following in those conditions:
test = [[NSString stringWithFormat:#"sample"] retain]; // or
test = [[NSString alloc] initWithFormat:#"sample"];
this will keep your string alive till you release it.
There is another way that is not good to use but want to tell you so you can understand it better. Using
test = #"sample";
If you don't want to append string or use it with format you can assign simple string to you NSString object.
using this will have a infinite retainCount of your test variable. You can use this to avoid crash but this is not preferable because as I told this have a infinite retaiCount you can't release it and free your memory after use. So earlier methods are more correct.
This is true with all of your autorelease objects which are created with class methods and not with init.
Hope this will clear you more.
I think simple allocation will solve the problem. Just replace this code in the viewDidLoad method
-(void)viewDidLoad {
test=[[NSString alloc]initWithString:#"Sample"];
}
What is the best way to keep my UI constants in seperate class accesible from all controllers?
UIView, UIImage and UIColour all these images and colours create a such mess of allocations and releases in my controllers and most of them are even same. Instead of alloc/relase the same images and views, CAlayers over and over again in different classes, I want to create them once, cache them (or something like that) and easily access when needed.
I want to keep memory and my code clean.
yes , its possible
create a class like gconstants , then store all your string here in h/m files
extern NSString *const APP_TITLE;
#interface UIColor (APP)
+(UIColor *) APP_NAV_COLOR;
#end
in .m file
NSString *const APP_TITLE = #"APP Name";
#implementation UIColor (APP)
+(UIColor *) APP_NAV_COLOR { return [UIColor colorWithRed:00/256.0 green:111/256.0
blue:59/256.0 alpha:1.0]; }
#end
and in any controller declare the header file
self.title = APP_TITLE;
You could use some macro's defined in a header file which you can then include in all the appropriate implementation files, or even in your prefix.pch if you want to make them available to every file in your project.
As an example, imagine a header file called Config.h
For a shared UIColor you could add the following ...
#define SOME_CONSTANT_COLOR [UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:0.5f]
And then you can access it the same way as you would use any other macro ...
#import "Config.h" // at the top of you implmentation file, or prefix header
someView.backgroundColor = SOME_CONSTANT_COLOR;
The same also goes for images as well ..
#define SOME_IMAGE [UIImage imageNamed:#"someImage.png"]; // In config.h
myImageView.image = SOME_IMAGE; // In implementation file