prepareForInterfaceBuilder doesn't update my storyboard - ios

I've created a simple day calendar view and I'd like to see it rendering live on my storyboard, but I've managed to show only the code in -drawRect:.
Running on the simulator I get this image, that represents the correct final result, but in storyboard I get this.
On storyboard I get this
The CalendarDayView is a subclass of a another view whose purpose is to load a nib with a specific name and add it a as a subview. CalendarDayView is tagged as IB_DESIGNABLE.
It is added as a subview directly on the storyboard.
To show also the label inside the CalendarDayView in the -prepareForInterfaceBuilder method I've written some placeholder text.
- (void) prepareForInterfaceBuilder {
[super prepareForInterfaceBuilder];
self.yearLabel.text = #"2015";
self.monthLabel.text = #"FEBRUARY";
self.dayLabel.text = #"28";
}
Draw rect is shown fine
- (void) drawRect:(CGRect)rect {
self.backgroundColor = [UIColor clearColor];
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:20];
[APP_CALENDAR_VIEW_COLOR setFill];
[path fill];
}
How can I achieve to show labels while editing my storyboard? even if I show the preview nothing is shown.

Related

Add gradient background for only last 2 section on UITableView

I'm creating a UITableView have 3 sections with custom cells. At 1st section I set it to white background color. Now I wanna set a gradient background like image below for only section 2nd and 3rd (this background will start from section 2 and end at last row of section 3):
How can I do that? Can someone give me a solution? Thanks.
This is actually pretty easy.
First, make sure each cell has a transparent background color. The default is opaque white. You can set this in your storyboard, or you can do it in your tableView:cellForRowAtIndexPath: method like this:
cell.backgroundColor = [UIColor clearColor];
Next, make a subclass of UITableView and override layoutSubviews. Be sure to call [super layoutSubviews].
In your override of layoutSubviews, the first time it's called, make a CAGradientLayer with your chosen gradient and add it as a sublayer of the table view's layer at index 0 (so it's behind all of the table view's other sublayers). On every call, update the frame of the gradient layer to be the union of [self rectForSection:1] and [self rectForSection:2].
Also, remember to set the custom class of the table view in your storyboard.
Here's the table view subclass I used to make the demo.
GradientTableView.h
#import <UIKit/UIKit.h>
#interface GradientTableView : UITableView
#end
GradientTableView.m
#import "GradientTableView.h"
#implementation GradientTableView {
CAGradientLayer *gradientLayer;
}
- (void)layoutSubviews {
[super layoutSubviews];
[self layoutGradient];
}
- (void)layoutGradient {
[self createGradientLayerIfNeeded];
[self updateGradientLayerFrame];
}
- (void)createGradientLayerIfNeeded {
if (gradientLayer != nil) {
return;
}
gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = #[
(__bridge id)[UIColor redColor].CGColor,
(__bridge id)[UIColor orangeColor].CGColor
];
gradientLayer.locations = #[ #0, #1 ];
gradientLayer.startPoint = CGPointZero;
gradientLayer.endPoint = CGPointMake(0, 1);
gradientLayer.type = kCAGradientLayerAxial;
[self.layer insertSublayer:gradientLayer atIndex:0];
}
- (void)updateGradientLayerFrame {
CGRect frame = [self rectForSection:1];
frame = CGRectUnion(frame, [self rectForSection:2]);
gradientLayer.frame = frame;
}
#end
Edit:
This answer contains some general information on table views and an easy solution to your question if a coarse gradient as shown in the screenshot below suffices. If you need a more fine-grained solution please refer to Rob's answer.
Apart from the fact that it's really hard to recognize that your background image has a gradient at all (it looks like a plain red image to me and you should consider just using a red background color instead) there is no way to just set an image as the background of a whole section using the standard UIKit API. And there's a reason for that:
A UITableView doesn't load all its cells when it appears on screen. Instead it only loads those cells that are visible at the moment plus a couple of buffer cells below (and above) in order to enable smooth scrolling. A table view section is rather an abstract concept that's intended to help you present your data in a structured fashion as it gives you headers and footers for each section and the ability to give your cells a different format (e.g. a different background color) depending on the section index. However, a table view section is not a view that is placed behind your cells. And thus you cannot apply a background image or a color to it.
You can see that when you look at an arbitrary table view in Xcode's view debugger:
The selected light blue view is the table view's wrapper view. The upper next view layer is already the table view cells. So there's no "section view" or something in between.
As you can see from the screenshot it's possible and quite easy to get a rough gradient effect by simply setting the cell's background color depending on its index path. I achieved this effect with the following two lines of code in the cellForRowAtIndexPath method:
Swift:
let redColorValue = CGFloat(indexPath.row)/CGFloat(tableView.numberOfRowsInSection(indexPath.section))
cell.backgroundColor = UIColor.init(red: redColorValue, green: 0.5, blue: 0.8, alpha: 1)
Objective-C:
CGFloat redColorValue = (CGFloat)(indexPath.row) / aSection;
cell.backgroundColor = [UIColor colorWithRed:redColorValue green:0.5 blue:0.8 alpha:1];
This way the first and the last cell in the section will always have the same color so the gradient will dynamically change its height depending on the number of cells in your section.
I think you need to set the background to the cell, so it moves with scrolling. You need to know where your sections begins (0, 5, 10):
if (indexPath.row < 5)
{
[cell setBackgroundColor:[UIColor whiteColor]];
}
if (indexPath.row > 5 && < 10)
{
[cell setBackgroundColor:[UIColor gradientColor]];
}
if (indexPath.row > 10)
{
[cell setBackgroundColor:[UIColor gradientColor2]];
}

Is it possible to use custom view for SKCalloutView?

Is it possible to make a custom UIView, with elements such as Label and Button, and use it as a CalloutView?
What I read through the documentation so far doesn't implicates that it is possible.
Changing left and right button is possible, together with adding custom UIImageView for an arrow, but couldn't figure out if customising entire view is actually possible.
Yes - you just have to override the calloutViewForAnnotation callback. There is an example in the demo project (see inside AnnotationsViewController.m) where you can create a user defined UIView and return that
- (UIView*)mapView:(SKMapView *)mapView calloutViewForAnnotation:(SKAnnotation *)annotation
{
//Custom callouts.
if (annotation.identifier == self.annotation1.identifier)
{
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0.0f, 0.0f, 200.0f, 50.0f)];
view.backgroundColor = [UIColor purpleColor];
view.alpha = 0.5f;
return view;
}
return nil;// Default callout view will be used.
}

iOS creating PDF from UIViews

I am currently creating PDF documents from a UIView in iOS by using CALayer and the renderInContext method.
The problem I am facing is the sharpness of labels. I have created a UILabel subclass that overrides drawLayer like so:
/** Overriding this CALayer delegate method is the magic that allows us to draw a vector version of the label into the layer instead of the default unscalable ugly bitmap */
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
BOOL isPDF = !CGRectIsEmpty(UIGraphicsGetPDFContextBounds());
if (!layer.shouldRasterize && isPDF)
[self drawRect:self.bounds]; // draw unrasterized
else
[super drawLayer:layer inContext:ctx];
}
This method lets me draw nice crisp text, however, the problem is with other views that I don't have control over. Is there any method that would allow me to do something similar for labels embedded in UITableView or UIButton. I guess I'm looking for a way to iterate through the view stack and do something to let me draw sharper text.
Here is an example:
This text renders nicely (my custom UILabel subclass)
The text in a standard segmented control isn't as sharp:
Edit: I am getting the context to draw into my PDF as follows:
UIGraphicsBeginPDFContextToData(self.pdfData, CGRectZero, nil);
pdfContext = UIGraphicsGetCurrentContext();
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 612, 792), nil);
[view.layer renderInContext:pdfContext];
I ended up traversing the view hierarchy and setting every UILabel to my custom subclass that overrides drawLayer.
Here is how I traverse the views:
+(void) dumpView:(UIView*) aView indent:(NSString*) indent {
if (aView) {
NSLog(#"%#%#", indent, aView); // dump this view
if ([aView isKindOfClass:[UILabel class]])
[AFGPDFDocument setClassForLabel:aView];
if (aView.subviews.count > 0) {
NSString* subIndent = [[NSString alloc] initWithFormat:#"%#%#",
indent, ([indent length]/2)%2==0 ? #"| " : #": "];
for (UIView* aSubview in aView.subviews)
[AFGPDFDocument dumpView:aSubview indent:subIndent];
}
}
}
And how I change the class:
+(void) setClassForLabel: (UIView*) label {
static Class myFancyObjectClass;
myFancyObjectClass = objc_getClass("UIPDFLabel");
object_setClass(label, myFancyObjectClass);
}
The comparison:
Old:
New:
Not sure if there is a better way to do this, but it seems to work for my purposes.
EDIT: Found a more generic way to do this that doesn't involve changing the class or traversing through the whole view hierarchy. I am using method swizzling. This method also lets you do cool things like surrounding every view with a border if you want. First I created a category UIView+PDF with my custom implementation of the drawLayer method, then in the load method I use the following:
// The "+ load" method is called once, very early in the application life-cycle.
// It's called even before the "main" function is called. Beware: there's no
// autorelease pool at this point, so avoid Objective-C calls.
Method original, swizzle;
// Get the "- (void) drawLayer:inContext:" method.
original = class_getInstanceMethod(self, #selector(drawLayer:inContext:));
// Get the "- (void)swizzled_drawLayer:inContext:" method.
swizzle = class_getInstanceMethod(self, #selector(swizzled_drawLayer:inContext:));
// Swap their implementations.
method_exchangeImplementations(original, swizzle);
Worked from the example here: http://darkdust.net/writings/objective-c/method-swizzling

Shadow in separate view from UIImage for dynamic adjustments

I would like to obtain this effect (http://stackoverflow.com/questions/7023271/how-to-adjust-drop-shadow-dynamically-during-an-uiimageview-rotation) but from a more complex image than just a red square ! If the link ever gets broken, it's a about how to adjust drop shadow dynamically during an UIImageView rotation.
So I tried implementing something but I just can't get the shadow in a separate layer... Here is my code, very simple, but doesn't work:
// here is my code
- (void)viewDidLoad {
[super viewDidLoad];
testView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:#"handNoShadow.png"]];
testViewShadow = [[UIView alloc] initWithFrame:testView.frame];
testViewShadow.layer.shadowPath = [[testView layer] shadowPath];
testViewShadow.layer.shadowOpacity = 1.0;
testViewShadow.layer.shadowOffset = CGSizeMake(10, 10);
testViewShadow.layer.shadowRadius = 5.0;
[self.view addSubview:testViewShadow];
[self.view addSubview:testView];
}
PS: i did #import
I do get an image but no shadow... =(
Any lead, help, code, link... is welcome !
Thanks
possible cause:
your testViewShadow.clipToBounds property is set to YES (should be NO)
your testViewShadow do the drawing of the shadow correctly but another UIView is on top and mask it. Check your Z order. Either the order in Storyboard/Nib file (or the order you added the subviews programmatically). Last in the list (or last one added) is on top. For my app I had to put the UIView that need a shadow last so that no other view mask it.

How to make Drawing on Fully Transparent View Visible

I am using Quartz for drawing as in custom UIView say "Paint"
I have controller view "viewC"
I did
[self.view addSubView:somePaintInstance]; in my viewC at some event
Now when i am drawing or painting , the default background is "black" for Paint.
I want to do a Full Transparent Painting/Drawing on top of my "viewC" view
So i did
somePaintInstance.alpha=0.5; (before adding it as subview)
But that also make my drawing/painting transparent with the Paint's Background , so if i make it fully transparent (alpha = 0.0) , i couldn't see the drawing itself with the paint's view
What i tried and not working:
somePaintInstance.setbackgroundcolor
somePaintInstance.opaque
Other answers on web are also NOT concrete for this kind of implementation
I looked the answer by rob here:
How to add a transparent gradient mask to a context
But Still not clear how do i implement exactly what i want?
Let me know other details if required
Regards,
I tried to set a background with alpha value 0 or to work with StartTransparentLayer. None of that worked.
What worked for me was to set the views opaque property to NO.
In my view's initializer i put the following code:
-(id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// set default values
self.colorNormal = [UIHelper ricolaYellow];
self.colorActice = [UIColor colorWithHexString:CIRCLE_COLOR_ACTIVE];
self.capacities = nil;
self.opaque = NO;
}
return self;
}
This line should work,
somePaintInstance.backGroundColor = [UIColor clearColor];

Resources