It's been awhile since I've used Xcode and I resumed an old project I was working on awhile ago. I created a new UITableViewCell subclass. In my storyboard, I dragged a UITableViewCell onto my UITableView of my UIViewController. I changed the type of the UITableViewCell to my subclass, but when I control + drag from the UITableViewCell subclass to the UITextField, it doesn't allow me to make the connection.
.h of my UITableViewCell custom subclass
#property (nonatomic, weak) IBOutlet UITextField *titleTextField;
I must be going crazy because I thought this was something that just worked. I saw in another UIViewController that there is a custom subclass for the UITableView when I worked on this project last. I changed the subclass that was having the problem to that type of UITableViewCell subclass and I'm still not able to ctrl+drag to make the IBOutlet connection. Am I missing something here? Wasn't this something that always worked this way? Is there something new I'm not aware of? I tried using the assistant editor as well to drag it to the code, but that doesn't work either. I went back to the UITableViewCell subclass that DOES have a connection already made from when I last worked on this, and I tried ctrl+dragging to the label again, and it doesn't bring up the menu on which outlet I want to connect to either.
Another thing that is weird, is when I'm trying to type the custom class of my UITableViewCell that is already created, even though I built my project, it doesn't autocomplete it in the Class field. I'm not sure if my Xcode is having problems. Also, I don't know if this matters, but in my UITableViewCell, I Have some standard UITableViewCells as well. Any thoughts? Thanks.
It looks like all I had to do for my class name to appear in the drop down was to quit Xcode and come back in. I thought things like that would have been fixed in the IDE.
I found that I could still add the connections in the connections inspector. I don't know why they removed the very easy ctrl+drag from the left hand side of the storyboard unless I'm missing something.
Related
Prior to Xcode 11 I could easily attach a view (label, switch, e.t.c) to an IBOutlet defined on a superclass, if I had the inspector window open and command clicked to my view (In this case a subclass of a UITableViewCell subclass it would open the superclass in the inspector window and I could attach to the IBOutlet. In Xcode 11 however it seems that when command clicking through to the "definition" this opens in the LHS panel, which replaces my storyboard or xib file with the views superclass.
Is there any way to open the superclass alongside the xib/storyboard any more in Xcode 11? My framework is a pre-compiled framework so I can't access the source files to open them in a new panel in Xcode.
Thought it might be wise to include a class hierarchy
LargeHeaderTableViewCell -> TableViewCell -> UITableViewCell
TableViewCell is within a pre-compiled framework (Installed using Carthage)
Edit:
To frustrate matters further... I can get the class definition of TableViewCell open next to my xib file (In a panel), however it seems you can only attach to IBOutlets in the assistant editor, not in a standard Xcode panel/tab/whatever you call it.
Found an answer (eventually) in here
I realize that this question was posted a while ago, but since I just
struggled with the same issue and finally came up with a solution, I
figured I would still post my findings...
I understand the problem to be as follows (at least that's the one I
solved):
How to have class A inherit from class B, with each class having its
own XIB file with the some common IBOutlet properties? The goal being
to be able to have the super class handle the actions related to the
IBOutlets that are common to its subclass(es), while still being able
to use Interface Builder to design the interface for the
subclass(es).*
In order to do so:
Make the IBOutlet connections in the superclass from the superclass'
XIB files Make the IBOutlet connections in the subclass from the
subclass' XIB files, with the same IBOutlet property names as in the
superclass for the ones you need to inherit. Delete the declaration of
the IBOutlet variables in the subclass
Before you tell me that all I need to do is import UIKit, I know all about importing, and NO, that's not what I need to do in this case. Intrigued? Confused? Read on...
I have two different, but similar, custom UITableViewCells. Both have a UILabel and a UISwitch. Version one, DisplayCell, has a second UILabel, while version two, EditCell, has a UIPickerView. How I use them is like this, in a static UITableView that I'm using as a fill-in-the-data form, DisplayCell is the standard view which displays the selected value. The user can tap on DisplayCell to replace it with EditCell, then use the UIPickerView to pick a new value and hit done (button in the nav bar at the top). DisplayCell is then brought back, displaying the newly selected value. In either version the user can tap the switch to toggle whether or not the value from the UIPickerView should be used elsewhere in the form.
When it came time to write the code for the tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> (UITableViewCell) function I decided to rewrite my code so that I have a single class, SwitchCell that inherits from UITableViewCell and contains the IBOutlet and IBAction for the switch, then have DisplayCell and EditCell inherit from SwitchCell.
This works fine, however DisplayCell is now nothing more than a IBOutlet for a UILabel, and UITableViewCell, which DisplayCell inherits from via SwitchCell already has two UILabel IBOutlets, textLabel and detailTextLabel. The whole purpose in creating SwitchCell was to try and minimize code by only ever write any block of code once, something that I'm a bit of a fanatic about. Thus I would very much rather have the UILabel in DisplayCell use the detailTextLabel IBOutlet from UITabelViewCell, rather than having to create a 'redundant' UILabel IBOutlet for it.
In order to link to an IBOutlet in a superclass you must be able to bring up the code for that superclass in the assistant editor. Then you can just control+drag and link like normal. Which means, in theory, I believe it should be possible to link my UILabel to UITableViewCell's detailTextLabel, if I can access the appropriate line from the source code for UITableViewCell in the assistant editor. Is this possible, and if so, how?
Oh, and I'm working exclusively in Swift in this project, FYI.
tl;dr: It's really not anymore efficient to use UITableViewCell's default UILabels than it is to just add your own.
In order to link to an IBOutlet in a superclass you must be able to bring up the code for that superclass in the assistant editor.
Well, that's not correct. The assistant editor is not required to link to an IBOutlet defined in a superclass. But that's not important here anyway.
You can't link to detailTextLabel in Interface Builder because it's not defined with the #IBOutlet attribute. And although it is possible to override properties in Swift (so you can add #IBOutlet to it), that won't work in this case because an IBOutlet has to be mutable, and the superclass has defined the variable as immutable.
Now you could overcome this by adding your own setter method in the subclass to make the property mutable. I was able to do this with the following code:
var _detailTextLabel: UILabel?
#IBOutlet override var detailTextLabel: UILabel? {
get {
return super.detailTextLabel
}
set {
_detailTextLabel = newValue
}
}
I could wire this up in Interface Builder just fine. So perhaps I could tweak this code to actually get an set what I want (I don't think it would work as shown here). We're so far outside the realm of common-sense coding that we just need to stop and give up on this idea.
Thus I would very much rather have the UILabel in DisplayCell use the detailTextLabel IBOutlet from UITabelViewCell, rather than having to create a 'redundant' UILabel IBOutlet for it.
I can relate. I'm just as anal. :-)
However, if you do a little testing (or read the UITableViewCell header file) you'll see that UITableView is smart enough (optimized enough?) to not actually add a UILabel to the content view unless you try to use it. So at worst you have an unused property.
So it's really not inefficient to just add your own UILabel and property.
I am following a tutorial HERE on creating a table-view controller in Xcode. I am using the latest version of Xcode (Xcode 5). At the top of the tutorial it says its for iOS 5.
In the tutorial a cell is created and an UIImage and a few labels are dragged onto the cell. It goes on to say to Ctrl-Click the white space of the cell and then drag to the labels and image to establish the outlet connection. See screen grab from tutorial.
When I do this, I dont get the same options as per the tutorial. The only options I get are shown below in this screen grab (note I chose to only add one label and leave out image for the purpose of my application).
Can anyone please let me know what Im doing wrong or how else I can create this connection? I have Googled it for the last hour and all I could see was how to create IBOutlets.
Alternatively, does anyone know of any tutorials similar to this one? This one suits my needs perfect as I will be creating a view similar to the second part of this tutorial. Like I mentioned Im working with Xcode 5.
Although this might be a little late, I recently just stumbled upon this problem myself and figure out the answer. I used the same tutorial as you, and could not seem to generate the proper options when I did the control + drag.
Instead of dragging the labels to the whitespace of the custom cell, you will be dragging from the Connections tab of the custom cell. To do this:
First, make sure your labels are properly declared in CarTableViewCell.h and synthesize them in CarTableViewCell.m.
Second, change the custom class in the storyboard for the prototype cell from UITableViewCell to CarTableViewCell.
Next, click on the cell prototype in storyboard. Using Utilities, go to the connections tab (the last one with the arrow). If everything is linked properly in your header files, you should see "makeLabel", "modelLabel", and "carImage" under the Outlets section.
Finally, click the little circle next makeLabel and drag it over to the proper label in your custom cell. Do this for modelLabel as well as carImage, just using the associated outlet and label or imageView for each.
This solved my connection problem, and after following the rest of the tutorial, everything worked!
Is your cell a custom cell. If not click on your cell and go to the attribute inspector then under table view cell choose the style as custom
Is your TableViewCell connected to the "CarTableViewCell"?
Click on the cell and make sure the custom class is set to CarTableViewCell.
And your .h file matches the one in the tutorial
#import <UIKit/UIKit.h>
#interface CarTableViewCell : UITableViewCell
#property (nonatomic, strong) IBOutlet UIImageView *carImage;
#property (nonatomic, strong) IBOutlet UILabel *makeLabel;
#property (nonatomic, strong) IBOutlet UILabel *modelLabel;
#end
Try again, and it should be like the tutorial.
-Cong
I'm using XCode 4.6 and I'm trying to replace one of my UITextView's by a SSTextView from SSToolKit in order to add a placeholder to it. The SSToolkit library is correctly integrated in my project thanks to CocoaPods. So I just changed the type of the property in my view controller to be SSTextView instead of UITextView:
#property (strong, nonatomic) IBOutlet SSTextView *commentTextView;
And of course I also changed the class of the control in interface builder's inspector:
And yet, in my controller's viewWillAppear: the property is still a UITextView and when I set the placeholder:
self.commentTextView.placeholder = NSLocalizedString(#"Comment", #"");
I get an "unrecognizable selector setPlaceholder: sent to instance".
It seems to me like I've done that sort of things a thousand times and yet here, I can't figure out what I'm forgetting.
I figured it out. It turns out some parts of the compiled application seem not to be overwritten when redeploying to the simulator. So after I deleted the app from the simulator and ran it from scratch, it worked normally. I had other bugs like missing segues and so on so I looked that up and found out about the "delete app" technique. Weird...
I'm currently refactoring a couple of view controllers that share a few IBOutlets and IBAction methods. I moved the outlet declarations and the IBAction method into a superclass, cutting these out of the subclasses.
Now, when I open up Interface Builder, I find that I can't see the outlets or actions declared in the superclass. The connections still exist, as I'd wired them up before the refactoring, but they're grayed out. (It's important to note that the connections also WORK, as my action fires on a button press, and my outlets are modified properly.)
The question is, how can I get interface builder to recognize outlets from a superclass? Is this possible, and, if not, what do you all recommend?
(Just for fun, here's my superclass header file:)
#interface TFMainViewController : UIViewController {
UIImageView *logoImage, *thinkfunImage;
UIButton *buyFullButton;
}
#property (nonatomic, retain) IBOutlet UIImageView *logoImage, *thinkfunImage;
#property (nonatomic, retain) IBOutlet UIButton *buyFullButton;
-(IBAction) buyFullVersion;
#end
EDIT: in case anyone's wondering, I'm using Xcode and IB 3.2.5, with the iOS 4.2 SDK.
I didn't realize it was even possible to connect to superclasses in interface builder until about an hour ago. Since this was the only question I could find regarding how to do this, I'll add my answer, even though this question is old. My answer is with regard to Xcode 4, not Xcode 3.
As far as I can tell, you can't connect to outlets in a superclass using the assistant editor, but you can do it by clicking on "File's Owner" in IB. That should show all the outlets in Utilities->Connections Inspector. You can then Ctrl+Click on the outlet in the inspector (click on the '+' sign), and drag it over to your view in IB.
The solution for the problem with the IBOutlet .. is to change the class type to the Base Class in the identity inspector
connect using Control + drag and drop and
change it back to the child class
This works for me
BTW: i used Xcode 6
IB should be able to see outlets from superclasses, I have done this a number of times with no issues. Are you sure you are importing the superclass correctly (using #import instead of #class)? IB needs some way to track back to the superclass.
Switching between the super and subclass in the identity inspector allows you to connect your outlets across the classes. The only issue I found is when you attempt to do this with a UITableViewCell and its subclass. I wanted to re-assign the default textLabel and detailTextLabel instances to labels I create in Interface Builder. The workaround is to create substitute labels and then override the getters to point to these instead.
I'm pretty sure that IB only looks at the actual class you're using to find outlets, and not at superclasses. I think that the easiest solution would be to leave the instance variable declarations in the superclass, but duplicate the #property lines in each subclass.
I'm doing this in XCode 3.2.6. I started with outlets connected to a class, and then made a subclass with additional outlets. When I changed the File's Owner class to the subclass, IB showed the superclass outlets as greyed out. I switched File's Owner to the superclass, then back to the subclass and now all outlets are showing not greyed out.
The simplest way: create interface and implementation files for your subclass(es)!
Perfect example: Juggleware's awesome ShadowButton Subclass of UIButton.
Make sure to create the .h & .m files in your project.
NOTE: There is no need to #import the header files at all since this is simply a class instance of UIButton.
In Interface Builder:
Select the element you which to connect.
Go to Utilities -> Identity Inspector
Change the Class to your subclass (or superclass). NOTE: You might have to type in your subclass name and hit ENTER.
You're done!
Even if you have declared a basic class (UIButton) as IBOutlet in your header file like so...
// YourViewController.h
#interface YourViewController : UIViewController {
IBOutlet UIButton *mybutton;
}
...the class you've set in Interface Builder (ShadowButton) will overwrite it since it's in the view layer.
The best part about this approach is that your code doesn't have any messy dependency issues.
On the project I am currently working, we have a BaseViewController with a UIScrollView as IBOutlet and handles keyboard appearance/disappearance events and slides the content accordingly. At first, I could not connect to that IBOutlet, than solved the problem like this, which is similar to Sosily's answer:
BaseViewController has an IBOutlet, called contentScrollView. I can see 5 previously connected outlets, which are UIScrollViews on other UIViewControllers, created by people who previously worked on the project
I tried to connect my UIScrollView as the contentScrollView. Although my UIViewController is a subclass of BaseViewController, I cannot connect it.
I tried to connect already connected UIScrollViews as the contentScrollView. Although all UIViewControllers are subclasses of BaseViewController, I cannot connect them again, as well. So, I started to look for a trick.
I have created the same contentScrollView IBOutlet on my own UIViewController, connected the scrollView to my own contentScrollView outlet and removed the one that I have just created.
Now the scrollView is connected as contentScrollView to File's Owner, but the only contentScrollView belongs to the BaseViewController. Tested and verified that keyboard events are handled correctly.
I ran into a similar problem with a superclass, but it was due to a bug in Xcode (8.2) where Interface Builder doesn't show outlets in the Connection Inspector if those outlets have been declared with a _Nullable type annotation for Swift compatibility.
Using nullable inside #property's parentheses appears to work around the problem.
This Xcode bug seems to affect outlets in any class (ie. not just superclasses).
I had the same problem, and it turns out it was because in the superclass I had the IBOutlets declared as "_Nullable".
Example:
#property (nonatomic, strong) IBOutlet UITableView *_Nullable mySuperTableView;
When I removed the _Nullable, suddenly the IBOutlets reappeared in IB and all was good again.
(I had only set them to _Nullable because Xcode was complaining "pointer is missing a nullability type specifier"... (don't know why). )