I have a parent view UIViewController (on storyboard), a TableViewController with .xib and TableViewCell with .xib. I am trying to connect DataSource to the TableView however it's giving me an error:
Redundant conformance of 'TableView1' to protocol 'UITableViewDataSource'
'TableView1' inherits conformance to protocol 'UITableViewDataSource' from superclass here.
Without adding dataSource near class and try it as class TableView1: UITableViewController {.. , it doesn't give me any error and in the simulator, I can see the table view illusion when I scroll down.
However, when I try to add dataSource, it gave me these errors.
The path I followed on setting it up...:
Ctrl + drag from xib to TableView1 and connected it as Globals
In xib file, I connected DataSource & Delegate
Finally, my TableView1:
class TableView1: UITableViewController, UITableViewDataSource { error here..
#IBOutlet var GlobalsTableView: UITableView!
var results: [AnyObject]? = []
override func viewDidLoad() {
super.viewDidLoad()
print("A")
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.results?.count ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! DogTableViewCell
return cell
}
}
Please note that in TableView1.xib, I can't select TableView1 as Custom Class -> Class (but i don't think it's necessary).
When a class inherits from UITableViewController, it by default conforms to UITableViewDataSource & UITableViewDelegate and you need not explicitly specify it.
You need to conform to UITableViewDataSource and UITableViewDelegate only when you embed a UITableView in a UIViewController.
There are at least 2 conformations in your class. You need to extend only once.
First Scenario:
You conform in the class description AND in the extension.
class MyViewController: MyDelegate{
//class functions here
}
extension MyViewController: MyDelegate{
func1()
}
Remove "My Delegate" in the class description.
class MyViewController{
//class functions here
}
extension MyViewController: MyDelegate{
func1()
}
Second Scenario:
You conform in two extensions.
extension MyViewController: MyDelegate{
func1()
}
extension MyViewController: MyDelegate{
func2()
}
Merge them into one extension like:
extension MyViewController: MyDelegate{
func1()
func2()
}
Related
Being a beginner with Xcode, I wanted to know if it was possible to create a list with our own components? I explain, it would be to make a list of favorites scrolling on an Xcode view, with an image, a button to delete it, and a text. It is obvious that I will have to create more components but how to put them in a list without limits?
The prototype design is as follows:
Here !
Thank you in advance, Sincerely.
Yes you can make your own list cells. For that you will need to,
create your own UITableViewCell and add your componenents (2x UIImageViews, 1x UILabel)
register your cell to the UITableView you want to display the cell in with the identifier
Conform to both UITableViewDelegate & UITableViewDataSource
Refer this blog to learn more as I barely scratched the surface with the explanation
You can add data to the table as follows
/// Conforming to the UITableViewDelegate, UITableViewDataSource protocols
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// Table view to display data
#IBOutlet weak var tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// setting the datasource and delegate
tableview.delegate = self
tableview.dataSource = self
}
/// 2d Array to store data
let data = [["Melon", "Glace"], ["Epinard"], ["one", "two", "three"] ]
func numberOfSections(in tableView: UITableView) -> Int {
return self.data.count
}
/// UITableViewDataSource protocol stubs
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.data[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell") as? CustomTableViewCell {
cell.name = data[indexPath.section][indexPath.row]
return cell
}
return UITableViewCell()
}
}
I am new to Mac OSX and with Apple promoting the fact that the bodies of code are becoming similar decided to tell the folk I am writing code for we should be able to do a Mac OSX version. iPhone and iPad versions are all good and about to release second version so no issues there.
So I am subclassing NSWindowController to get access to the Toolbar and worked out how to remove and add items on the toolbar, but for the life of me I can not get one NSViewController (firstViewController) to dismiss and bring up the second NSViewController (secondViewController) in the same NSWindowController.
So the 2 issues are that
1. I want to be able to performSegueWithIdentifier from the first NSViewController in code and
2. bring up the second NSViewController by replacing the first NSViewController in the same NSWindowController.
If I add a button to the firstViewController and put a segue to the secondViewController then when I select the button the secondViewController comes up just fine but in a seperate window not the same NSWindowController that I want it to and the firstViewController does not get replaced but stays in the NSWindowController.
So I know the segue idea will work but its not working in code and when I do insert the segue from a button it works but into a seperate NSViewController that is not part of the NSWindowController.
I am trying to find some programming guide from Apple on the issue but no luck so far.
Here is an overview from my Storyboard:
Here is my NSWindowController subclassed and the func loginToMe2Team is trigger from the NSToolBar and its working just find as the print statements show up on the console.
import Cocoa
class me2teamWindowsController: NSWindowController {
#IBOutlet var mySignUp : NSToolbarItem!
#IBOutlet var myToolbar : NSToolbar!
let controller = ViewController()
override func windowDidLoad() {
super.windowDidLoad()
print("window loaded")
}
override func windowWillLoad() {
print("window will load")
}
#IBAction func logInToMe2Team(sender: AnyObject){
controller.LogIn() //THIS IS THE FUNC I AM TESTING WITH
}
#IBAction func signUpToMe2Team(sender: AnyObject){
controller.signUp()
}
Here is my NSViewController subclassed with the func LogIn. Its getting selected just fine but the performSegueWithIdentifier is not. And I did cut and past the Identifier to make absolutely sure it was the same.
import Cocoa
import WebKit
class ViewController: NSViewController {
#IBOutlet weak var theWebPage: WebView!
#IBOutlet weak var progressIndicator: NSProgressIndicator!
override func viewDidLoad() {
super.viewDidLoad()
let urlString = "https://thewebpage.com.au"
self.theWebPage.mainFrame.loadRequest(NSURLRequest(URL: NSURL(string: urlString)!))
}
override func viewDidAppear() {
}
func LogIn() {
print("I logged in")
self.performSegueWithIdentifier("goToTeamPage", sender: self)
//THIS IS THE BIT THATS NOT WORKING
}
func signUp() {
print("I have to sign up now")
}
override var representedObject: AnyObject? {
didSet {
}
}
func webView(sender: WebView!, didStartProvisionalLoadForFrame frame: WebFrame!)
{
self.progressIndicator.startAnimation(self)
}
func webView(sender: WebView!, didFinishLoadForFrame frame: WebFrame!)
{
self.progressIndicator.stopAnimation(self)
}
}
You need to use a custom segue class (or possibly NSTabViewController if it’s enough for your needs). Set the segue’s type to Custom, with your class name specified:
…and implement it. With no animation, it’s simple:
class ReplaceSegue: NSStoryboardSegue {
override func perform() {
if let src = self.sourceController as? NSViewController,
let dest = self.destinationController as? NSViewController,
let window = src.view.window {
// this updates the content and adjusts window size
window.contentViewController = dest
}
}
}
In my case, I was using a sheet and wanted to transition to a different sheet with a different size, so I needed to do more:
class ReplaceSheetSegue: NSStoryboardSegue {
override func perform() {
if let src = self.sourceController as? NSViewController,
let dest = self.destinationController as? NSViewController,
let window = src.view.window {
// calculate new frame:
var rect = window.frameRectForContentRect(dest.view.frame)
rect.origin.x += (src.view.frame.width - dest.view.frame.width) / 2
rect.origin.y += src.view.frame.height - dest.view.frame.height
// don’t shrink visible content, prevent minsize from intervening:
window.contentViewController = nil
// animate resizing (TODO: crossover blending):
window.setFrame(window.convertRectToScreen(rect), display: true, animate: true)
// set new controller
window.contentViewController = dest
}
}
}
I'm working on a project that uses the JSQMessagesViewController library. Has anyone successfully animated the typing indicator, and if so could they share their approach?
Thanks!
I'm late for the party but because this also take me a lot of time and my post could help others so I will list my working solution.
I use an APNG (animated PNG, which could have transparent background) as typing indicator so I use APNGKit which provide an UIImageView subclass named APNGImageView
Copy JSQMessagesTypingIndicatorFooterView.xib from Pods/Pods/JSQMessagesViewController/Resources to your source folder, rename it to MyMessagesTypingIndicatorFooterView.xib (for example)
Create a class named MyMessagesTypingIndicatorFooterView like so:
class MyMessagesTypingIndicatorFooterView: JSQMessagesTypingIndicatorFooterView {
#IBOutlet weak var animatedImageView: APNGImageView!
override func draw(_ rect: CGRect) {
super.draw(rect)
}
override func awakeFromNib() {
super.awakeFromNib();
}
public override class func nib() -> UINib! {
return UINib(nibName: "MyMessagesTypingIndicatorFooterView", bundle: Bundle.main)
}
override class func footerReuseIdentifier()->String{
return "MyMessagesTypingIndicatorFooterView"
}
}
Add APNGImageView instance to MyMessagesTypingIndicatorFooterView.xib, reference custom class MyMessagesTypingIndicatorFooterView. Add reference outlet animatedImageView to MyMessagesTypingIndicatorFooterView class.
Register custom footer in subclass of JSQMessagesViewController and override viewForSupplementaryElementOfKind
class MyMessagesViewController: JSQMessagesViewController{
override func viewDidLoad() {
self.collectionView.register(MyMessagesTypingIndicatorFooterView.nib(),
forSupplementaryViewOfKind: UICollectionElementKindSectionFooter,
withReuseIdentifier: "MyMessagesTypingIndicatorFooterView")}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionElementKindSectionFooter{
let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "MyMessagesTypingIndicatorFooterView", for: indexPath) as! MyMessagesTypingIndicatorFooterView
//footerView
let image = APNGImage(named: "typing1.png")
footerView.animatedImageView.image = image
footerView.animatedImageView.startAnimating()
return footerView
}
return super.collectionView(collectionView, viewForSupplementaryElementOfKind: kind, at: indexPath)
}
}
You will want to look into the JSQTypingIndicatorFooterView here is the documentation. http://cocoadocs.org/docsets/JSQMessagesViewController/7.2.0/Classes/JSQMessagesTypingIndicatorFooterView.html
You can set the ellipsisColor
messageBubbleColor the color of the bubble it self.
shouldDisplayOnLeft to decide if it should be on the left or right.
collectionView the collection view it should show on.
I'm having a heck of a time setting up a simple split view. The first split view is collapsed. I need to set a minimum width for it. Everything I see online (scarce for NSSplitViewController/NSSplitView) is for Objective-C, puts everything in the app delegate, and uses XIBs.
Here's the scenario:
Window Controller with a segue to a SplitView Controller, which has two split views (2 view controllers).
Which object needs to have the NSSplitViewDelegate?
EDIT: Adding code snippet:
For example, I have this:
import Cocoa
class ViewController: NSSplitViewController, NSSplitViewDelegate {
#IBOutlet weak var pdlSplitView: NSSplitView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func splitView(splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
return proposedMinimumPosition + 200
}
}
Is there more that I'm missing?
Thanks
UPDATE
Based on comments below, I've made a change, but now I get a sigAbort on the class definition for the AppDelegate. Full code
ViewController:
import Cocoa
class ViewController: NSSplitViewController, NSSplitViewDelegate {
#IBOutlet weak var pdlSplitView: NSSplitView!
let publicDataListings : PDL = PDL()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.pdlSplitView.delegate = self
}
override func splitView(splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
return proposedMinimumPosition + 200
}
}
SidebarViewController:
import Cocoa
class SidebarViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
}
DatasetViewController:
import Cocoa
class DatasetViewController: NSViewController, NSSplitViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
}
Update
I took away my custom NSSplitViewController class and created two NSSplitView classes, one with the constraint method. Now, I see both subviews, but they're far smaller than they should be:
Is there anyone at all that has done this with Swift and Storyboards?
No coding is required to set a minimum width in a storyboard with auto layout for a NSSplitViewController/NSSplitView.
Select the CustomView that you require a minimum width for (e.g. 200), and add a width constraint set to the required value which will add a "Equal" constraint (e.g. Custom View.Width equals 200).
Next locate that new constraint and change the constraint relation to "Greater Than or Equal" (e.g. so you now have width ≥ 200).
You now have a minimum width in an NSSplitView. You can then use the Priority field to resolve any conflicts with any other auto layout constraints.
These values are not exposed in the storyboard, which is a great shame, but NSSplitViewItem has minimumThickness and maximumThickness properties which you can use. (This overrides the holding priority, so if you set minimumThickness for one splitViewItem, the other one(s) will now shrink into nothing if you make the window small enough.)
There is also automaticMaximumThickness (I cannot work out how this interacts with the other values) and preferredThicknessFraction which had no effect when I played with it under 10.13.
Set NSSplitViewController as delegate of NSSplitView (the split view you want to constrain). In your case it should be - in xib hook the delegate outlet of the NSSplitView to file owner (I guess the file owner is NSSplitViewController subclass)
Implement
- (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)dividerIndex { ... }
in NSSplitViewController
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSSplitViewDelegate_Protocol/index.html#//apple_ref/occ/intfm/NSSplitViewDelegate/splitView:constrainMinCoordinate:ofSubviewAt:
Trying to load contents of a directory into tableview.
Using: NSFileManager and NSTableView.
Getting Error Message in the last function:
'[AnyObject]?' does not have a member named 'subscript'
Do I miss something regarding Optionals?
Code:
import Cocoa
let fileManager = NSFileManager.defaultManager()
let folderURL = NSURL.fileURLWithPath("/Applications/")
var error : NSError? = nil
let folderContents: [AnyObject]? = fileManager.contentsOfDirectoryAtURL(folderURL!,
includingPropertiesForKeys:nil, options:NSDirectoryEnumerationOptions(),
error:&error)
class tonik: NSObject, NSTableViewDataSource {
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
folderContents?.count
}
func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int) -> AnyObject? {
folderContents[row]
}
}
Now it compiles.
I created object in xib file and table view, used the tonik class as datasource for the tableview, now I am getting message:
2015-01-10 07:21:18.420 ac3[6016:143038] *** Illegal NSTableView data source (). Must implement numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:
but both functions are implemented.