uiImageView showing borders between images in UICollectionViewCell - iphone

We have a row of 139x127 images that are displaying with borders in our collection view cell. we tried UIViewContentModeScaleAspectFill (and Fit) but it is still showing the borders.
The code is below:
// uicollectionviewcell
(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self = [super initWithFrame:frame];
if (self) {
// Initialization code
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:#"ProfilePhotoCell" owner:self options:nil];
if ([arrayOfViews count] < 1) {
return nil;
}
if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) {
return nil;
}
self = [arrayOfViews objectAtIndex:0];
}
[self.imageView setContentMode:UIViewContentModeScaleAspectFill];
return self;
}
return self;
}
// uicollectionview/viewcontroller
// 1
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
// 2
CGSize retval = CGSizeMake(100, 66);
return retval;
}
// 3
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(20, 0, 0, 0);
}
Here is a screenshot: ! http://m.mirror.co/collection.png

What is going on with your collectionViewLayout property of the UICollectionView? I am guessing that the UICollectionView is padding the cells it is displaying.

For debugging purposes i have found it priceless to use LLDB by pausing the app and running...
po [[UIWindow keyWindow] _autolayoutTrace]
This will give you the pointers to each view object. Then i will run...
po [0xabcd123 constraints]
...to see if any auto constraints were added at runtime you didn't know about. Also, you can get the frame size of your cell and your view and see if they match. You may need to programmatically delete auto constraints and apply new constraints pinning your view to your cell. I ran into some of this while making a view cell "flip" from view to view.
Don't forget to turn off the auto constraints in your init or IB...
[self.imageview setTranslatesAutoresizingMaskIntoConstraints:NO];
Good luck!

Related

Calling setCollectionViewLayout:animated does not reload UICollectionView

I am using a UICollectionView with two custom layouts - which are subclassed from UICollectionViewFlowLayout
When my view first loads I set it to a default view using:
[self.collectionView setCollectionViewLayout:self.tableViewLayout];
This calls: cellForItemAtIndexPath - so no problem there. This is in viewWillAppear method.
Then I use a UIButton to change the layout from current view to the next layout like so:
-(void)changeViewLayoutButtonPressed
{
self.changeLayout = !self.changeLayout;
if (self.changeLayout){
[self.tradeFeedCollectionView setCollectionViewLayout:self.grideLayout animated:YES];
}
else {
[self.tradeFeedCollectionView setCollectionViewLayout:self.tableViewLayout animated:YES];
}
}
After this call - numberOfItemsInSection is called. I have checked in the debugger that the return account is not zero.
After that call, nothing else is called and my UICollectionView changes the layout but since cellForItemAtIndexPath is not called - the cells are not setup correctly.
if I put [self.collectionView roloadData] inside of numberOfItemsInSection - then cellForItemAtIndexPath is called and cells are setup.
I shouldn't need to do a manual call to reload the data in numberOfItemsInSection. Can someone tell me whats going on?
Edit
I forgot to mention I am using two different UINibs for the two different cells as they need slightly different layouts applied to them. Would this be an issue?
Thanks!
Edit 2
Right, so I have gotten it to work almost like I want it to. Here is all the code used for the collection view and how I change its layouts.
The Custom Layouts
These are subclassed from UICollectionViewFlowLayout - The reason I subclassed is simply due to the face my UICollectionView needs to look and behave very close to Apple's pre-made layout. Just different cell sizes, though.
TableViewLayout
- No code in the header file.
- BBTradeFeedTableViewLayout.m
#implementation BBTradeFeedTableViewLayout
-(id)init
{
self = [super init];
if (self){
self.itemSize = CGSizeMake(320, 80);
self.minimumLineSpacing = 0.1f;
}
return self;
}
#end
Gride Layout
- No code in the header file.
- BBTradeFeedGridViewLayout.m
#implementation BBTradeFeedGridViewLayout
-(id)init
{
self = [super init];
if (self){
self.itemSize = CGSizeMake(159, 200);
self.minimumInteritemSpacing = 0.1f;
self.minimumLineSpacing = 0.1f;
}
return self;
}
#end
Then in the ViewController that has my UICollectionView - I declare the two custom layouts like so:
#property (strong, nonatomic) BBTradeFeedTableViewLayout *tableViewLayout;
#property (strong, nonatomic) BBTradeFeedGridViewLayout *grideLayout;
I then register the two .xib files for the collectionView:
[self.tradeFeedCollectionView registerNib:[UINib nibWithNibName:#"BBItemTableViewCell" bundle:nil] forCellWithReuseIdentifier:#"TableItemCell"];
[self.tradeFeedCollectionView registerNib:[UINib nibWithNibName:#"BBItemGridViewCell" bundle:nil] forCellWithReuseIdentifier:#"GridItemCell"];
Then, I have a UIButton that changes the layout:
-(void)changeViewLayoutButtonPressed
{
if (!self.gridLayoutActive){
self.gridLayoutActive = YES;
[self.tradeFeedCollectionView setCollectionViewLayout:self.grideLayout animated:YES];
self.lastLayoutUsed = #"GridLayout";
}
else {
self.gridLayoutActive = NO;
[self.tradeFeedCollectionView setCollectionViewLayout:self.tableViewLayout animated:YES];
self.lastLayoutUsed = #"TableLayOut";
}
[self.tradeFeedCollectionView reloadItemsAtIndexPaths:[self.tradeFeedCollectionView indexPathsForVisibleItems]];
}
Finally - when a web service call is done - it calls [self.tradeFeedCollectionView reloadData];
So there my UICollectionView gets reloaded and the last method:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{ static NSString *tableCellIdentifier = #"TableItemCell";
static NSString *gridCellIdentifier = #"GridItemCell";
if (indexPath.item < [self.tradeSearchArray count]){
if (self.gridLayoutActive == NO){
BBItemTableViewCell *tableItemCell = [collectionView dequeueReusableCellWithReuseIdentifier:tableCellIdentifier forIndexPath:indexPath];
if ([self.tradeSearchArray count] > 0){
self.toolBarButtomItem.title = [NSString stringWithFormat:#"%d Results", self.searchResult.searchResults];
tableItemCell.gridView = NO;
tableItemCell.backgroundColor = [UIColor whiteColor];
tableItemCell.item = self.tradeSearchArray[indexPath.row];
}
return tableItemCell;
}else
{
BBItemTableViewCell *gridItemCell= [collectionView dequeueReusableCellWithReuseIdentifier:gridCellIdentifier forIndexPath:indexPath];
if ([self.tradeSearchArray count] > 0){
self.toolBarButtomItem.title = [NSString stringWithFormat:#"%d Results", self.searchResult.searchResults];
gridItemCell.gridView = YES;
gridItemCell.backgroundColor = [UIColor whiteColor];
gridItemCell.item = self.tradeSearchArray[indexPath.row];
}
return gridItemCell;
}
The problem with the above code
The above code does work. However, the cells don't animate nicely and it looks odd, almost as if a refreshed happened. Which is due to calling:
[self.tradeFeedCollectionView reloadItemsAtIndexPaths:[self.tradeFeedCollectionView indexPathsForVisibleItems]];
But that is the only way I could get it to be close to what I want.
-setCollectionViewLayout: or -setCollectionViewLayout:animated: won't cause your UICollectionView reload its data.
If you want to change your cell style or update the data, call [self.collectionView reloadData] and UICollectionViewDataSource protocol methods will be called.
If you want to change your UICollectionView layout to another, call -setCollectionViewLayout:. Or if you want to update your UICollectionView layout, just call [self.collectionView.collectionViewLayout invalidateLayout].
Cell layout and data are two different things in UICollectionView.
Update
you should discard all the stale data, probably by -reloadData. And calculate the new frames for every cell in your UICollectionViewLayout subclasses. Override - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath and - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect.
You decide the new contentOffset. For instance, you could keep the indexPath of some visible cell and decide to scroll to that indexPath or setContentOffset: to the frame.origin of the new cell at the same indexPath after your layout changed.
And I find this answer may give you help.
Also check the awesome video WWDC 2012 Advanced Collection Views and Building Custom Layouts
Simply call reloadData before you switch your layout (the performBatchUpdates call is not mandatory):
[self.collectionView reloadData];
[self.collectionView.collectionViewLayout invalidateLayout];
[self.collectionView setCollectionViewLayout:yourLayout animated:YES];
In Swift:
self.collectionView?.reloadData()
self.collectionView?.collectionViewLayout.invalidateLayout()
self.collectionView?.setCollectionViewLayout(yourLayout, animated: true)
You should call [self.tradeFeedCollectionView invalidateLayout]; before
if (self.changeLayout){
[self.tradeFeedCollectionView setCollectionViewLayout:self.grideLayout animated:YES];
}
else {
[self.tradeFeedCollectionView setCollectionViewLayout:self.tableViewLayout animated:YES];
}
(Posted solution on behalf of the question author).
I finally found a nice and simple solution.
The marked answer was correct, that I needed to call, -reloadData on my UICollectionView - However, this destroyed the animation when switching between the two cells.
After taking in suggestions from the marked answer - I just reworked my `UIButton' method, that changes the cells
I found that if I call:
[self.collectionview performBatchUpdates:^{ } completion:^(BOOL finished) {
}];
According to the WDDC video - this animates the changes works with -reloadData method:
Example:
[self.collectionView reloadData];
[self.collectionView performBatchUpdates:^{
[self.collectionView.collectionViewLayout invalidateLayout];
[self.collectionView setCollectionViewLayout:self.grideLayout animated:YES];
} completion:^(BOOL finished) {
}];
}
You should only have to call this method:
[self.collectionView setCollectionViewLayout:layout animated:YES];
I had a similar bug, but it ended up that my subviews of the cells were not setup with Auto Layout. The cell was resizing correctly, but my subviews were not, so it looked like the cell size never changed. Check this in your code quickly by setting clipsToBounds = YES on your cell.contentView.
Here is the simple trick if you want to update layouts Use it wherever you are updating the collectionView:
[self.collectionView removeFromSuperview]; //First remove the Collection View
//Relocate the view with layouts
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.minimumInteritemSpacing = 10;
layout.minimumLineSpacing = 10;
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.width,100) collectionViewLayout:layout];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[self.collectionView reloadData];
[self.view addSubview:self.collectionView];
I found that to easily and nicely animate both cells' kind and layout simultaneously it is best to reloadSections (instead of reloadData) followed by setting a new layout with animation:
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
[self.collectionView setCollectionViewLayout:newLayout animated:animated];

Set border in UICollectionView

It is my first time that I want to create a UICollectionView. This is how I want it to look like:
I read some tutorials and I know how it works exactly. The thing is as you see in the image, The UICollection cells have border from up, bottom, left and right. Do you know how can set these kind of border in Collection View?
As you see two of the items are selected by red color. is it possible in UICollectionView to have multiple selected items? if yes, could you please give send me some tutorials.
Small example project here: https://github.com/erikt/ETMultiSelect
First you have to make it possible to select more than one cell in the UICollectionView. This is done by setting the allowsMultipleSelectionproperty to YES on the collection view.
The view controller would look something like this:
#import "ETViewController.h"
#import "ETCellView.h"
#implementation ETViewController
static NSString *cellIdentifier = #"cvCell";
- (void)viewDidLoad {
[super viewDidLoad];
// Register our custom collection view cell
[self.collectionView registerClass:ETCellView.class forCellWithReuseIdentifier:cellIdentifier];
// Make it possible to select multiple cells
self.collectionView.allowsMultipleSelection = YES;
}
#pragma mark - UICollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 10;
}
#pragma mark - UICollectionViewDelegate
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ETCellView *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
return cell;
}
#end
The UICollectionViewCell is made up of several views. It has a content view, a background view and a selected background view.
There are many ways to achieve something similar to your picture, but I set the border on the selected background layer and add a subview to the content view that's inset so the background border is visible:
#import "ETCellView.h"
#import <QuartzCore/QuartzCore.h>
#implementation ETCellView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.restorationIdentifier = #"cvCell";
self.backgroundColor = [UIColor clearColor];
self.autoresizingMask = UIViewAutoresizingNone;
CGFloat borderWidth = 3.0f;
UIView *bgView = [[UIView alloc] initWithFrame:frame];
bgView.layer.borderColor = [UIColor redColor].CGColor;
bgView.layer.borderWidth = borderWidth;
self.selectedBackgroundView = bgView;
CGRect myContentRect = CGRectInset(self.contentView.bounds, borderWidth, borderWidth);
UIView *myContentView = [[UIView alloc] initWithFrame:myContentRect];
myContentView.backgroundColor = [UIColor whiteColor];
myContentView.layer.borderColor = [UIColor colorWithWhite:0.5f alpha:1.0f].CGColor;
myContentView.layer.borderWidth = borderWidth;
[self.contentView addSubview:myContentView];
}
return self;
}
#end
The result is something like this:
Clone and play with the sample project.
In a real project you would want to keep track of what the user has selected in the view controller, by adding the selected data model entities to some structure (like a NSMutableArray) in the – collectionView:didSelectItemAtIndexPath: method on the UICollectionViewDelegate protocol.

TableView wont display provided data

I am having a strange issue with TableView. Here is some code to clarify everything:
I am using tabbed panes and this right here is just one of my two ViewControllers:
As you can see, all I do is setting up an UIView and placing a tableView right ontop of it.
#import "SuchenCtrl.h"
#interface SuchenCtrl ()
#end
#implementation SuchenCtrl
#synthesize MainView;
#synthesize Standort;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view = self.MainView;
[self.Standort.tableView setDelegate:self.Standort];
[self.Standort.tableView setDataSource:self.Standort];
[self.MainView addSubview:self.Standort.tableView];
}
- (id)init {
self = [super init];
if(self) {
CGRect rect = [[UIScreen mainScreen] applicationFrame];
self.MainView = [[UIView alloc] initWithFrame:rect];
[self.MainView setBackgroundColor:[UIColor blackColor]];
//Alloc UITableViewController
self.Standort = [[UIStandort alloc] initWithStyle:UITableViewStylePlain];
[self.Standort release];
[self.MainView release];
}
return self;
}
#end
Now UIStandort is another class that simply inherits from UITableViewController. It implements all necessary functions to display data. All im trying to achieve is having the table display "Test" a couple of times but it wont. The table gets displayed nicely but just with empty cells. When I breakpoint one of the implemented functions in the class UIStandort nothing gets called, so my assumption is that the delegate and sourceData are pointing to wrong classes? Though, I explicitly assign those before putting the table on the view.
UIStandort* Standort is declared with properties retain and nonatomic if this helps.
#import "UIStandort.h"
#interface UIStandort ()
#end
#implementation UIStandort
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath(NSIndexPath *)indexPath
{
UITableViewCell* cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.textLabel.text = #"Test";
[cell autorelease];
return cell;
}
#end
Thanks.
You return 0 for the number of row in section. The documentation states:
The number of sections in tableView. The default value is 1.
Can you try:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}

Custom UITableViewCell redraw issues

I have a custom UITableView cell that I've added a textbox to for editing, that shows and hides based on the edit mode. I've also tried adding a vertical line that shows when editing, and it does that, but I'm running into some drawing issues. I just added a green checkmark rightView to start working on input validation feedback, and I'm seeing similar issues.
Here is the code for the cell, and part of my cellForRowAtIndexPath.
#import <UIKit/UIKit.h>
#interface EditableCellStyle2 : UITableViewCell {
CGRect editRect;
UITextField *editField;
UIView *lineView;
}
#property (nonatomic, readonly, retain) UITextField *editField;
#property (nonatomic, readonly, retain) UIView *lineView;
#end
#import "EditableCellStyle2.h"
#implementation EditableCellStyle2
#synthesize editField;
#synthesize lineView;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code.
editRect = CGRectMake(83, 12, self.contentView.bounds.size.width-83, 19);
editField = [[UITextField alloc] initWithFrame:editRect];
editField.font = [UIFont boldSystemFontOfSize:15];
editField.textAlignment = UITextAlignmentLeft;
editField.textColor = [UIColor blackColor];
editField.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:editField];
self.editField.enabled = NO;
self.editField.hidden = YES;
lineView = [[UIView alloc] initWithFrame:CGRectMake(80, 0, 1, self.contentView.bounds.size.height)];
self.lineView.backgroundColor = [UIColor lightGrayColor];
[self.contentView addSubview:lineView];
self.lineView.hidden = YES;
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state.
}
-(void)layoutSubviews
{
[super layoutSubviews]; // layouts the cell as UITableViewCellStyleValue2 would normally look like
editRect = CGRectMake(83, 12, self.contentView.frame.size.width-self.detailTextLabel.frame.origin.x-10, 19);
editField.frame = editRect;
}
- (void)willTransitionToState:(UITableViewCellStateMask)state {
[super willTransitionToState:state];
if (state & UITableViewCellStateEditingMask) {
self.detailTextLabel.hidden = YES;
self.editField.enabled = YES;
self.lineView.hidden = NO;
self.editField.hidden = NO;
}
}
- (void)didTransitionToState:(UITableViewCellStateMask)state {
[super didTransitionToState:state];
if (!(state & UITableViewCellStateEditingMask)) {
self.editField.enabled = NO;
self.editField.hidden = YES;
self.lineView.hidden = YES;
self.detailTextLabel.hidden = NO;
self.editField.text = self.detailTextLabel.text;
}
}
- (void)dealloc {
[editField release];
[lineView release];
[super dealloc];
}
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// handling every section by hand since this view is essentially static. Sections 0, 1, 2, and 4 use a generic editable cell.
// Section 3 uses the multiline address cell.
static NSString *CellIdentifier = #"Cell";
EditableCellStyle2 *cell = (EditableCellStyle2 *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (indexPath.section == 0 || indexPath.section == 1 || indexPath.section == 2 || indexPath.section == 4) {
if (cell == nil) {
cell = [[[EditableCellStyle2 alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
}
}
// Configure the Odometer
if (indexPath.section == 0) {
NSArray *array = [sectionsArray objectAtIndex:indexPath.section];
NSDictionary *dictionary = [array objectAtIndex:indexPath.row];
cell.textLabel.text = #"Odometer";
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", [dictionary objectForKey:#"Odometer"]];
cell.tag = kOdometer;
cell.editField.text = cell.detailTextLabel.text;
cell.editField.placeholder = #"Odometer";
cell.editField.tag = kOdometer;
cell.editField.keyboardType = UIKeyboardTypeNumberPad;
// Create a view for the green checkmark for odometer input validation and set it as the right view.
UIImage *checkImage = [UIImage imageNamed:#"tick.png"];
UIImageView *checkImageView = [[[UIImageView alloc] initWithImage:checkImage] autorelease];
cell.editField.rightView = checkImageView;
cell.editField.rightViewMode = UITextFieldViewModeAlways;
}
return cell;
}
There is more to it but all the cells are built the same way.
The problems are that, when in edit mode, the vertical lines will display properly. When I leave edit mode, any cells that were off screen when I go to normal mode still have the vertical line (it doesn't get hidden). Also, now that I've added the imageView for the checkmark indicator, any cells that are off screen when switching modes gain the checkmark. (only section 0 sets it up).
I've also noticed that if i do cell.setNeedsDisplay, the text label and detail text label won't update if the data source has been updated. I have to do [self.tableView reloadData] which skips any active animations.
I'm sure these issues are related to me using a custom cell + dequeueReusableCellWithIdentifier, but I can't find exactly what.
Any feedback or a push in the right direction would be appreciated.
Edit:
Not using reusable cells seems to have resolved the above issues. I'm still open to feedback on the cell code.
I forgot one other issue that may or may not be related. One of my cells has a "tap to view list" button. If I enter data into the cells while in edit mode, then hit that button to choose some info from a list (it displays a modal table view), when I dismiss the modal view, all of the cells' edited data has reverted to their original state. I'm not calling reload data when I dismiss the modal view controller. I thought this might be fixed by not using reusable cells but it isn't.
You need to prepare the cell for reuse. Try adding this to the EditableCellStyle2 implementation:
- (void)prepareForReuse {
[super prepareForReuse];
[self didTransitionToState:UITableViewCellStateDefaultMask];
}
Maybe you trimmed too much for your post, but in the posted code your reusable cell handling is all wrong.
First of all, each different type of cell needs its own CellIdentifier. In your case (judging from your code comment), that means at least a different identifier for section 3 versus sections 0, 1, 2, and 4. You may also want to do a separate identifier for section 0, so you don't have to keep removing and readding that checkmark. The different identifier needs to be used for both the dequeueReusableCellWithIdentifier: and initWithStyle:reuseIdentifier:` for the appropriate sections.
The second problem is that you are not resetting the cells correctly. There are two "kinds" of initialization that must be done to a UITableViewCell: initialization that is the same for every cell of its type, and initialization that depends on the specific row being displayed. The first kind can (and should) only be done once, when a new cell is allocated. The second kind must be done every time through tableView:cellForRowAtIndexPath:. You seem to be doing the first correctly for your EditableTableCell2 class in its init method, but I see nowhere in there where you do the per-row initialization: you never reset selected, or the cell state, or the contents of the edit field, or remove the checkImageView since you are using the same kind of cell for section 0 versus the other sections. If you want, the reset selected, state, and clearing out the checkbox image and field contents can be done in prepareForReuse on your EditableTableCell2 class.
The third problem, which is almost certainly due to over-trimming, is that you never create this "multiline address" cell for section 3. You'll end up maybe reusing a random EditableTableCell2, or maybe crashing on an exception from the framework when you return nil from tableView:cellForRowAtIndexPath:.

How to resize a UISwitch?

I have made a custom UISwitch (from this post). But the problem is, my custom texts are a bit long. Is there any way to resize the switch? [I tried setBounds, did not work]
Edit:
Here is the code I used:
#interface CustomUISwitch : UISwitch
- (void) setLeftLabelText: (NSString *) labelText;
- (void) setRightLabelText: (NSString *) labelText;
#end
#implementation CustomUISwitch
- (UIView *) slider
{
return [[self subviews] lastObject];
}
- (UIView *) textHolder
{
return [[[self slider] subviews] objectAtIndex:2];
}
- (UILabel *) leftLabel
{
return [[[self textHolder] subviews] objectAtIndex:0];
}
- (UILabel *) rightLabel
{
return [[[self textHolder] subviews] objectAtIndex:1];
}
- (void) setLeftLabelText: (NSString *) labelText
{
[[self leftLabel] setText:labelText];
}
- (void) setRightLabelText: (NSString *) labelText
{
[[self rightLabel] setText:labelText];
}
#end
mySwitch = [[CustomUISwitch alloc] initWithFrame:CGRectZero];
//Tried these, but did not work
//CGRect aFrame = mySwitch.frame;
//aFrame.size.width = 200;
//aFrame.size.height = 100;
//mySwitch.frame = aFrame;
[mySwitch setLeftLabelText: #"longValue1"];
[mySwitch setRightLabelText: #"longValue2"];
The simplest way is to resize it, as a view:
UISwitch *mySwitch = [[UISwitch alloc] init];
mySwitch.transform = CGAffineTransformMakeScale(0.75, 0.75);
and you don't have to care about anything else!
Here is the swift 3 version of mxg answer:
let mySwitch = UISwitch()
mySwitch.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
Many controls are meant to be a specific size. If you were implementing this yourself, you would override setFrame:, adjust the frame parameter to match your control's required size, and then pass that to [super setFrame:].
If you subclass a control that has this behavior, there's really no way to override it because your subclass will inherit the superclass's implementation of setFrame:, which modifies your frame rectangle. And there's no way to set the frame of your control without calling [super setFrame:].
You'll most likely have to inherit from UIControl and implement the properties/behaviors you want from UISwitch manually to work around this.
UISwitch is not designed to be customized.
I think the your best solution is to download one of the custom switch implementations mentioned in the other question that you referred to. Either UICustomSwitch or RCSwitch. They both should be able to handle wide labels.
There is no option for resizing uiswitch in xib, so need to create and resize it in controller class,
UISwitch *onoff = [[UISwitch alloc] initWithFrame: CGRectMake(0, 0, 10, 10)];
onoff.transform = CGAffineTransformMakeScale(0.50, 0.50);
[self.view addSubview:onoff];
If you want to resize switch put through the Storyboard or nib, You can subclass UISwitch and override awakeFromNib method:
- (void)awakeFromNib {
self.transform = CGAffineTransformMakeScale(0.75, 0.75);
}
Select the switch control and change it's class to your custom switch class.
Here is a solution in code:
UISwitch *mySwitchNewsletter = [[UISwitch alloc] initWithFrame: CGRectMake(varSettingsSwitchNewsletter_x,
varSettingsSwitchNewsletter_y,
varSettingsSwitchNewsletter_width,
varSettingsSwitchNewsletter_height)];
if (mySwitchNewsletter != nil) {
[varCommerceSettingsView addSubview:mySwitchNewsletter];
float mySwitchScaleFactor = (varSettingsSwitchNewsletter_scale / 100.0);
CGFloat dX=mySwitchNewsletter.bounds.size.width/2, dY=mySwitchNewsletter.bounds.size.height/2;
mySwitchNewsletter.transform = CGAffineTransformTranslate(CGAffineTransformScale(CGAffineTransformMakeTranslation(-dX, -dY), mySwitchScaleFactor, mySwitchScaleFactor), dX, dY);
mySwitchNewsletter release];
}
Where varSettingsSwitchNewsletter_scale is an int from 0 to 100 (%).
// Just in case someone trying to hard code UISwitch in Xcode 6.4 the following is working
// in .h
#property UISwitch * onoff;
// in .m
self.onoff = [[UISwitch alloc] initWithFrame:CGRectMake(160, 40, 0, 0)];
_onoff.transform = CGAffineTransformMakeScale(0.50, 0.50);
[self.view addSubview:self.onoff];