I have an application developed in iOS4 using XiBs. I got it working all good with iOS6.1 and earlier. But for some buttons, IBAction is not getting called if it is iPhone and iOS 7.0. Also it is working fine with iPad and iOS 7.0. Of course, I am using different Xibs for iPhone and iPad.
Here is the code. It is pretty basic. But just not getting into it.
- (IBAction) didReceiveMapButtonPress {
NSLog(#"IN DID RECEIVE MAP BUTTON PRESS");
if ([self wasReferredFromMap]) {
[[self navigationController] popViewControllerAnimated:YES];
} else {
[self pushMapViewController];
}
}
Many of the developer used custom view to show custom cell on Table view for older version of iOS. If you are one of them, then you will have to face a problem that your button click action will no longer work with iOS7.
How to resolve this:
You have three options:
Option 1: Create the new lay out with new table cell instead of taking view. and put all layouts again in table cell.
I know, this will require a lot of effort.If you don't want to do this, we have a very small hack for it:option 2
Option 2: Create a IBOutlet for your button and add this button as a subview of your cell's content view.
[self.myCell.contentView addSubview:self.btn_click];
The above line of code will add btn_click as a subview of you content view. Now button click action should work.
Option 3:
The best way :
i) Take An outlet UITableViewCell.
ii) Make existing view as subview of new table cell.
iii) Disconnect the connection of custom cell to existing view and connect it to new UITableViewCell.
thats it, Your IBAction will work now.
May be you got the crash with error message that "class is not key value coding - compliant.". Check your old view connection and remove all connection having yellow mark.
When I faced with this problem, I had tons of cells from xibs. That's way I've create the category for UITableViewCell
#implementation UITableViewCell (customs)
- (void)awakeFromNib {
[super awakeFromNib];
[self reAddSubviews];
}
- (void)reAddSubviews {
for (UIView * o_vw in [[[self subviews] objectAtIndex:0] subviews]) {
if (o_vw != self.contentView) {
[o_vw removeFromSuperview];
[self.contentView addSubview:o_vw];
}
}
}
#end
Please make sure the TCell.xib for your UITableViewCell is correct.
Double check if this xib file has "Content view". If you can not see this item, that means your view is not a UITableViewCell, it probably is a UIView.
The correct method is to recreate this XIB file. you can do it like this:
NewFile(User Interface)--->Empty--->Device Family(iphone)--->Save as TCell.xib.
add UITableViewCell
copy your subview from your previous xib file to this view and connect the outlets. http://i.stack.imgur.com/WB4j3.png
Related
I'm having a problem handling rotation in a view controller.
When the view is topmost and the phone is rotated, it adapts correctly.
When there's a view controller being presented modally over it and the device is rotated, the view controller under is not fully updated for the rotation when the user returns. The biggest problem I appear to be having is that the separator lines don't expand to fill the whole width.
Example:
I've uploaded my test project to GitHub; you can clone it from https://github.com/tewha/ResizeOnRotate.git.
I have no code handling rotation at all. My understanding was that this was supposed to be fully automatic. What am I missing to make this work correctly?
Edit:
Inspired by the answer below, a simple workaround:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UITableViewCellSeparatorStyle separatorStyle = self.tableView.separatorStyle;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.separatorStyle = separatorStyle;
}
I think this may be an Apple bug. You can reproduce it in their own app "Mail".
Steps to reproduce in "Mail" app -
Open Inbox of messages in "Mail" app. (say, in Portrait orientation)
Tap compose message icon (bottom right) and rotate the device (in landscape).
Close the compose message and see the inbox messages view now.
Result: The separator lines are broken.
Workaround for user: Scroll down and up in message inbox (leads to display refresh).
Reproducible up to iOS 7.0.2.
Edit
(Code workaround - 1)
If possible, you could reloadData to refresh the tableview when it appears.
- (void)viewWillAppear:(BOOL)animated
{
[self.tableView reloadData];
}
Code workaround - 2 (reload only the visible cells)
- (void)viewWillAppear:(BOOL)animated
{
NSArray *refreshCells = [self.tableView indexPathsForVisibleRows];
[self.tableView reloadRowsAtIndexPaths:refreshCells withRowAnimation:UITableViewRowAnimationNone];
}
I'm using XCode 4.2 and have built my UI using Storyboards. I need to create a view that has content above and below a UITableView and I can achieve this by using a UIViewController. A UITableViewController does not let you add content above or below the table. You can use the table header/footer but that doesn't work for what I would like to achieve.
I now have a UIViewController with a UITableView embedded in it. I can adjust the height and width of the UITableView accordingly which provides me the UI layout that I am looking for.
I can customize the static cells in the UITableView but when I try to build I get the following error:
Illegal Configuration: Static table views are only valid when embedded in UITableViewController instances
My question is how are others getting around this? Creating a tableview with static cells and laying them out visually is very nice but apparently that is not allowed for some reason that I cannot understand. I can't switch to a UITableViewController because of my visual layout requirements.
Any assistance would be greatly appreciated.
You can achieve this in Xcode 4.5 and later versions, assuming your app is targeted at iOS 6+.
In the Storyboard simply create a UIViewController with a View Container inside it's main view. Then hook up that View Container to a UITableViewController that contains static cells.
Just like this:
You don't need a single line of code. Just control click, drag and select embed. The view controller containment is handled for you.
You are right. In storyboard, you cannot have a tableView with static cells embedded in a viewController. One way around it (I have not tried it myself, though, so I am not sure if it works) can be that you create an instance of UITableViewController in storyboard with static cells. Add an instance of UIView to your viewController, and then programmatically load the tableView of the UITableViewController into the UIView of your viewController.
pmd's answer works but in the event that backward compatibility with iOS 5 is required as well, you can do the embedding programatically using the View Containment API.
In the viewDidLoad method of your parent UIViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
MyTableViewController* vc =[storyboard instantiateViewControllerWithIdentifier:#"MyTableVC"];
[self addChildViewController:vc];
[self.view addSubview:vc.view];
// ensure embedded view is aligned to top
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
vc.view.frame = frame;
[vc didMoveToParentViewController:self];
}
Don't forget to specify a storyboard ID for your UITableViewController with the static cells.
I know this is an old question but I have a scrappy solution to this issue.
I needed 3 static cells on a UIViewController so this is what I did:
Drag in some Table View Cells into your interface (not into UITableView) - add text and whatever else you need.
Make IBOutlet properties for your cells and synthesise them.
Drag a button and make it cover the entire cell. Set the button to type 'Custom' so it appears invisible - repeat for all cells
Add numeric tags to your buttons
Implement the following functions. buttonDown is connected to the buttons 'Touch Down' event. buttonUp is connected to 'Touch Up Inside' AND 'Touch Up Outside'
-(IBAction)buttonDown:(id)sender {
if ([sender tag] == 1) {
myFirstCell.selected = YES;
}
else if ([sender tag] == 2) {
mySecondCell.selected = YES;
}
else if ([sender tag] == 3) {
myThirdCell.selected = YES;
}
}
-(IBAction)buttonUp:(id)sender {
myFirstCell.selected = NO;
mySecondCell.selected = NO;
myThirdCell.selected = NO;
}
You can do whatever else you like in the buttonDown event and use the button to go directly to a new view. I find this pretty useful.
I am not sure what you mean by static cells, but if you are trying to build the cells in IB, and then want to use it in your tableView, what you could do is in your cellForRowAtIndex you can call loadNibNamed passing the name of the .nib file you created for the cells as the parameter. Make sure that you have an outlet in your viewController which maps to the cell's .nib. Try exploring in these directions if that's what you are trying to achieve
You can make it dynamic and then switch of scrolling:
[yourTableName setScrollEnabled:NO];
For some reason I can't drag and drop from my storyboard button into my View Controller class.
All of the classes are named correctly, and I've tried logging out of my computer, shutting it down, and killing the XCode process. Nothing seems to work. Can anyone who's faced this kind of thing before give me any advice?
I think the problem in your case is that you have not set the UIViewController Class in Identity Inspecter . Please refer to the screenshots
Screenhot1:
Screenshot2:
In the first screenshot I am setting the Class of the UIViewController as the name of the Class of my View Controller (in my case the name is 'viewController').
Hope it will help you.
Delete and recreate your View Controller class. That how I fixed it (only got this problem 1 time).
Hope this helps.
If this is your situation, you can do one thing. Just tag your button in xib to identify that specific button. In ViewDidload , you can retrieve your button by below code..
#define YOURBTNTAG 44
for (UIView *subBtn in self.view.subviews)
{
if ([subBtn isKindOfClass:[UIButton class]])
{
if ( subBtn.tag == YOURBTNTAG)
{
self.btn = subBtn;
break;
}
}
}
[self.btn addTarget:self action:#selector(test:) forControlEvents:UIControlEventTouchUpInside];
Note : 1) If your class is correctly defined in Xib, It'll work otherwise cann't.
2) If self.view is nil, You have to delete your xib and create new one to do your work. Because It may have naming(class name or xib name) mistake or other mistake.
I'm preparing a UITableView with a custom prototype cell having a UISwitch widget on the right side, and I'd like to let my users be able to delete rows.
Everything is fine with that, except the fact that when the delete button shows up it overlaps to the UISwitch, this way:
Is it possible to have the UISwitch shifting left when the delete button appears?
Epilogue
I've decided for brevity to not shift my UISwitch position when "delete" button appears, but to make it disappear, bringing it back when the "delete" button is gone.
So, according to #geo suggestion (thank you), I've managed it out (quite simply) this way:
In my UITableViewCell' subclass .m file:
- (void)willTransitionToState:(UITableViewCellStateMask)state
{
[super willTransitionToState:state];
if (state & UITableViewCellStateShowingDeleteConfirmationMask) {
activationSwitch.hidden = YES;
}
else {
activationSwitch.hidden = NO;
}
}
I hit a very similar problem and fixed it. You need the right autoresizing mask (assuming not doing auto layout here) for your UI elements in your custom tableview cell in Interface Builder.
In my case, I needed to add the Left constraint (see that little autoresizing picture/animation in the Size Inspector, View section) for each of my UI elements.
Add a Left "bar", and you should be good.
Override the Methode
-(void)willTransitionToState:(UITableViewCellStateMask)state
-> UITableViewCellStateShowingDeleteConfirmationMask
of your custom Cell and do there your customizing :)
I'd like to place an ADBannerView object onto my UITableView screen statically, what means that I want it to always stay above my toolbar (self.navigationController.toolbar), even when the user is scrolling the tableview. I've solved this by adding by ADBannerView as a subview to my toolbar and given it negative values for the frames origin:
[self setBannerViewSize];
[self.navigationController.toolbar addSubview:bannerView];
The only problem is: I can't click and open the iAd this way - I can see the banner but nothing happens when I tap on it.
Since I'm also using a refreshControl, the option to use a UIViewController instead of UITableViewController and add a tableView manually wouldn't work for me. Is there any other way I can get my ADBannerView statically showing in my table view controller AND still being tappable?
Thank you in advice!
Yay!! After all I succeeded in solving this (really annoying) problem by myself (and a lot of reading around)!
First, I found this really world-changing post. Basically this post handles with the topic that a UITableViewController uses self.view for its tableView property, so overriding the tableView property (or synthesizing it manually) plus giving self.view a new view (from application) and adding tableView as its subview would make it possible to reach the real superview of tableView.
But this still didn't solve my problem, although I was sure it would, because it all made sense. My bannerView appeared in the right place (and was fixed) but it still didn't do anything when clicked. But there was a second minor thing I didn't know about:
As I read in this post the superview of a subview doesn't only have to be userInteractionEnabled but also have a non-transparent backgroundColor. Because my superviews background color was set to [UIColor clearColor] it all didn't work - but setting its backGroundColor to e.g. blackColor solved the whole problem: the bannerView got finally tappable! :)
So, my code is now looking like this:
#synthesize tableView;
- (void)viewDidLoad
{
[super viewDidLoad];
if (!tableView && [self.view isKindOfClass:[UITableView class]]) {
tableView = (UITableView *)self.view;
}
self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
self.tableView.frame = self.view.bounds;
[self.view addSubview:self.tableView];
[self resizeTableToFitBanner];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:bannerView];
// some other code
}
BannerViewController in Apple's iAdSuite sample code solves this problem very elegantly:
https://developer.apple.com/library/ios/samplecode/iAdSuite/Introduction/Intro.html
I think you should use a container view, and set things up in IB. You can add a tool bar and ADBannerView to the bottom of the view of your navigation controller's root view controller. Fill the rest of the space with a container view - this will give you an embedded view controller automatically. You should delete this one and then drag in a tableViewController and control drag from the container view to the tableViewController to hook up the embed segue.