I have this code :
_width.text = NSStringFromCGRect(_screen.frame);
and it gives me on my iPod 5:
{{0,20}, {320,548}}
how to get only height value = 548 so that I can use it to calculate another components.
thank you.
I guess you want a CGFloat, not a NSString if you want to calculate other components.
CGFloat height = _screen.frame.size.height;
Or if you want a string after all:
_width.text = [NSString stringWithFormat:#"%f", _screen.frame.size.height];
The frame property of UIView is a CGRect struct. To learn about CGRect go take a look at the documentation.
I would encourage you to use CGGeometry check the documentation, in your case use CGRectGetHeight().
CGFloat height = CGRectGetHeight(_screen.frame);
Try to use like this...
You can get Height Like this...
CGFloat height = _screen.frame.size.height;
_width.text = [NSString stringWithFormat:#"%f",height];
You can get Width Like this...
CGFloat width = _screen.frame.size.width;
_width.text = [NSString stringWithFormat:#"%f",width];
You can get x coordinate Like this Like this...
CGFloat x = _screen.frame.origin.x;
You can get y coordinate Like this Like this...
CGFloat y = _screen.frame.origin.y;
_screen.frame is a struct with a CGSize and a CGPoint.
CGPoint origin = _screen.frame.origin;
CGSize size = _screen.frame.size;
The struct CGPoint has the members x and y
CGFloat x = origin.x; // float on 32bit and double on 64bit
CGFloat y = origin.y;
The struct CGSize has the members width and height
CGFloat width = size.width;
CGFloat height = size.height;
You can print a message with a formatted NSString or C-String with the format specifier %
NSString *output = [NSString stringWithFormat:#"My screen height is: %f", height];
If you want to show the height as 543 not as 543.0, then use the float string specifier in the NSString creation method
NSString *string = [NSString stringWithFormat:#"Integer height is: %.0f", height];
// even with values like 0.9999 the output would be "Integer height is: 0"
If the property _width.text is a NSString.
_width.text = output;
Related
I'm learning Swift. As a test, I'm translating some of my old Objective-C programs to swift. But I have a crazy error: In Objective-C I have the following code:
- (CGSize)makeSizeFromCentimetersWidth: (CGFloat)width andY: (CGFloat)height {
NSScreen *screen = [NSScreen mainScreen];
NSDictionary *description = [screen deviceDescription];
NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue];
CGSize displayPhysicalSize = CGDisplayScreenSize([[description objectForKey:#"NSScreenNumber"] unsignedIntValue]);
CGFloat resolution = (displayPixelSize.width / displayPhysicalSize.width) * 25.4f;
CGFloat pixelsWidth = 0.394 * width * resolution;
CGFloat pixelsHeight = 0.394 * height * resolution;
return CGSizeMake(pixelsWidth, pixelsHeight);
}
In swift I have translated to this:
func makeSizeFromCentimeters(width: CGFloat, height: CGFloat) -> CGSize {
var screen: NSScreen = NSScreen.mainScreen()!
var description: NSDictionary = screen.deviceDescription
var displayPixelSize: NSSize = description.objectForKey(NSDeviceSize)!.sizeValue
var displayPhysicalSize: CGSize = CGDisplayScreenSize(description.objectForKey("NSScreenNumber")!.unsignedIntValue)
var resolution = (displayPixelSize.width / displayPhysicalSize.width) * 25.4
var pixelsWidth: CGFloat = 0.394 * width * resolution
var pixelsHeight: CGFloat = 0.394 * height * resolution
return CGSizeMake(pixelsWidth, pixelsHeight)
}
In Objective-C the code does what it should: Calculate a size from centimeters to pixels, to give out (in my case) an NSImageView with exactly the size of the given centimeters. But in Swift, the returned size, is always 0:
NSLog("%f", makeSizeFromCentimeters(2, height: 2).width)
NSLog("%f", makeSizeFromCentimeters(2, height: 2).height)
Is there an translating error? Which variable is 0? (No idea why it should be 0 if it's not caused by a variable).
Thank you for your help!
I am using drawRect for a text display, calling NSString. I am trying to implement using sizeWithFont to auto resizing font (shrinking) with default font size of 17 and using a loop to reduce the font size by 1 if it does not fit the size of width. Can anyone help me how to implement this? Example would be nice right now I just have the font size set to 17.0
[[self.string displayName] drawAtPoint:CGPointMake(xcoord, ycoord) withFont:[UIFont boldSystemFontOfSize:17.0]];
CGSize size = [[self.patient displayName] sizeWithFont:[UIFont boldSystemFontOfSize:17.0]];
max_current_y = size.height > max_current_y ? size.height : max_current_y;
xcoord = xcoord + 3.0f + size.width;
OK never mind. Here's modified version of the same method that takes NSString for which to return a font:
-(UIFont*)getFontForString:(NSString*)string
toFitInRect:(CGRect)rect
seedFont:(UIFont*)seedFont{
UIFont* returnFont = seedFont;
CGSize stringSize = [string sizeWithAttributes:#{NSFontAttributeName : seedFont}];
while(stringSize.width > rect.size.width){
returnFont = [UIFont systemFontOfSize:returnFont.pointSize -1];
stringSize = [string sizeWithAttributes:#{NSFontAttributeName : returnFont}];
}
return returnFont;
}
Here's how to call it:
NSString* stringToDraw = #"Test 123";
CGRect rect = CGRectMake(100., 100., 100., 200.);
UIFont* font = [self getFontForString:stringToDraw toFitInRect:rect seedFont:[UIFont systemFontOfSize:20]];
[stringToDraw drawInRect:rect withFont:font];
Code is for iOS7+
Trying font sizes with step 1.0 may be very slow. You can tremendously improve the algorithm by making two measures for two different sizes, then using linear approximation to guess the size that will be very close to the right one.
If it turns out not close enough, repeat the calculation using the guessed size instead of one of the previous two until it is good enough or stops changing:
// any values will do, prefer those near expected min and max
CGFloat size1 = 12.0, size2 = 56.0;
CGFloat width1 = measure_for_size(size1);
CGFloat width2 = measure_for_size(size2);
while (1) {
CGFloat guessed_size = size1 + (required_width - width1) * (size2 - size1) / (width2 - width1);
width2 = measure_for_size(guessed_size);
if ( fabs(guessed_size-size2) < some_epsilon || !is_close_enough(width2, required_width) ) {
size2 = guessed_size;
continue;
}
// round down to integer and clamp guessed_size as appropriate for your design
return floor(clamp(guessed_size, 6.0, 24.0));
}
is_close_enough() implementation is completely up to you. Given that text width grows almost linearly of font size, you can simply drop it and just do 2-4 iterations which should be enough.
I wanted to try to make a version that didn't have to repeatedly check font sizes using a do...while loop. Instead, I assumed that font point sizes were a linear scale, then worked out the size difference between the required frame width and the actual frame width, then adjusted the font size accordingly. Therefore, I ended up with this function:
+ (CGFloat)fontSizeToFitString:(NSString *)string inWidth:(float)width withFont:(UIFont *)font
{
UILabel *label = [UILabel new];
label.font = font;
label.text = string;
[label sizeToFit];
float ratio = width / label.frame.size.width;
return font.pointSize * ratio;
}
Pass in a font of any size, as well as the string and the required width, and it will return you the point size for that font.
I also wanted to take it a bit further and find out the font size for a multi-line string, so that the longest line would fit without a line break:
+ (CGFloat)fontSizeToFitLongestLineOfString:(NSString *)string inWidth:(float)width withFont:(UIFont *)font
{
NSArray *stringLines = [string componentsSeparatedByString:#"\n"];
UILabel *label = [UILabel new];
label.font = font;
float maxWidth = 0;
for(NSString *line in stringLines)
{
label.text = line;
[label sizeToFit];
maxWidth = MAX(maxWidth, label.frame.size.width);
}
float ratio = width / maxWidth;
return font.pointSize * ratio;
}
Seems to work perfectly fine for me. Hope it helps someone else.
Original poster didn't specify what platform he was working on, but for OSX developers on Mavericks, sizeWithFont: doesn't exist and one should use sizeWithAttributes :
NSSize newSize = [aString sizeWithAttributes:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSFont fontWithName:#"Arial Rounded MT Bold" size:53.0],NSFontAttributeName,nil
]];
Here's a method which can return you font that will fit in a rect:
-(UIFont*)getFontToFitInRect:(CGRect)rect seedFont:(UIFont*)seedFont{
UIFont* returnFont = seedFont;
CGSize stringSize = [self sizeWithFont:returnFont];
while(stringSize.width > rect.size.width){
returnFont = [UIFont systemFontOfSize:returnFont.pointSize -1];
stringSize = [self sizeWithFont:returnFont];
}
return returnFont;
}
You can add this method to a NSString category. You can find more about how to add a category here: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html#//apple_ref/doc/uid/TP40011210-CH6-SW2
If you don't want to create a category, you can add this method to one of your utility classes and pass in the string for which you want the font to be returned.
Here is another method, inspired by #puru020 & #jowie answers. Hope it helps someone
-(UIFont *) adjustedFontSizeForString:(NSString *)string forWidth:(float)originalWidth forFont:(UIFont *)font
{
CGSize stringSize = [string sizeWithFont:font];
if(stringSize.width <= originalWidth)
{
return font;
}
float ratio = originalWidth / stringSize.width;
float fontSize = font.pointSize * ratio;
return [font fontWithSize:fontSize];
}
I modified a bit the solution of #puru020 , added the support for attributes, and improved a bit:
Note: The method should be wrapped in a NSString Category
- (UIFont*)requiredFontToFitInSize:(CGSize)size seedFont:(UIFont*)seedFont attributes:(NSDictionary*)attributes{
UIFont *returnFont = [UIFont systemFontOfSize:seedFont.pointSize +1];
NSMutableDictionary *mutableAttributes = attributes.mutableCopy;
CGSize stringSize;
do {
returnFont = [UIFont systemFontOfSize:returnFont.pointSize -1];
[mutableAttributes setObject:returnFont forKey:NSFontAttributeName];
stringSize = [self sizeWithAttributes:mutableAttributes];
} while (stringSize.width > size.width);
return returnFont;
}
i want to show image height and width in a format a*b.for that i am using following code.problem is that label not show proper value where as height and ImagesizeWidth variable show correct value.
UIImage *newImage = image;
NSString *c= #"*";
int height = image.size.height;
int ImageSizeWidth = image.size.width;
//int size = image.size.height * image.size.width;
pixelInformation.text = [NSString stringWithFormat:#"%d%a%d",ImageSizeWidth,c,height];
can anyone help me. thanks in advance.
You should use the %# format specifier of Objective-C objects. They need to have description implemented.
So the last line should be,
pixelInformation.text = [NSString stringWithFormat:#"%d%#%d",ImageSizeWidth,c,height];
It's not %a. And you can directly put a * in the string though.
pixelInformation.text = [NSString stringWithFormat:#"%d*%d",ImageSizeWidth,height];
Im new to objective C so I need some help, is there any fast way of converting this string:
{{2, 2}, {103, 166}} to an NSArray, or just getting out the values to four NSInteger?
This is the storage format of a CGRect/NSRect. You can easily read it using CGRectFromString/NSRectFromString and then get the values like this:
NSString *string = #"{{2, 2}, {103, 166}}";
CGRect rect = CGRectFromString(string);
CGFloat x = rect.origin.x; // 2
CGFloat y = rect.origin.y; // 2
CGFloat width = rect.size.width; // 103
CGFloat height = rect.size.height; // 166
// CStroke.h
#import
#interface CStroke : NSObject {
CGFloat *startX;
CGFloat *startY;
CGFloat *endX;
CGFloat *endY;
BOOL *state;
}
#property CGFloat *startX;
#property CGFloat *startY;
#property CGFloat *endX;
#property CGFloat *endY;
#property BOOL *state;
-(void)setStroke: (CGFloat *)newStartX andStartY:(CGFloat *)newStartY andEndX:(CGFloat *)newEndX andEndY:(CGFloat *)newEndY;
#end
After set up CStroke class, I am going to use it in ViewController to draw something out using CGFloat
CGFloat *startX = (CGFloat *)[[self retrieveStartCoordinateOfStroke:k whichKindOfCoorXOrY:#"X"] integerValue];
CGFloat *startY = (CGFloat *)[[self retrieveStartCoordinateOfStroke:k whichKindOfCoorXOrY:#"Y"] integerValue];
CGFloat *endX = (CGFloat *)[[self retrieveEndCoordinateOfStroke:k whichKindOfCoordXOrY:#"X"] integerValue];
CGFloat *endY = (CGFloat *)[[self retrieveEndCoordinateOfStroke:k whichKindOfCoordXOrY:#"Y"] integerValue];
CStroke *stroke = [[CStroke alloc] init];
[stroke setStroke:startX andStartY:startY andEndX:endX andEndY:endY];
This is where I got error...I can't figure out what happened...are they both CGFloat type...Any answer for this?
The error is incompatible type for argument 2 of 'CGContextAddLineToPoint' and incompatible type for argument 2 of 'CGContextMoveToPoint'
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), myStroke.startX, myStroke.startY);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), [myStroke endX], [myStroke endY]);
Your problem is you're making your coordinates, pointers to CGFloat and not CGFloat types. They are not object types. CGfloat is currently, do not rely on this in the future just a type alias to float, and the functions you're passing to eventually, expect the scalar values, not pointers.
On a secondary note, getting the current graphics context is not a cheap operation. Do it once. That is, change your code to look something like this:
CGContextRef context = UIGraphicsGetCurrentContext();
// Now pass in context where you would normally pass in UIGraphicsGetCurrentContext()
I'm not sure I really understand what you are trying to do, but I don't really think you really meant to use pointers to floats...
try using just float and not pointers:
//CGFloat *startX; no need for it to be a pointer
CGFloat startX; // just a regular CGFloat is enough
//change all your variables to be CGFloats and not pointers to CGFloats