I have a MKMapView in one of my static cells. Instead of being able move the map around, I would like the user to be able to tap the map and have it expand full screen. Then within the full screen the user can move around and zoom in and out. They will eventually be able to see where I have pins placed based on other users' city where they are located.
I am getting an error when the map is tapped.
Thread 1: "-[HomeTableViewController triggerTouchAction:]: unrecognized selector sent to instance 0x115e2f8a0"
Here is the important code for the map and touch gesture for the controller:
import UIKit
import CoreLocation
import MapKit
class HomeTableViewController: UITableViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
// Always adopt a light interface style.
overrideUserInterfaceStyle = .light
let gestureRecognizer = UITapGestureRecognizer(target: self, action:"triggerTouchAction:")
mapView.addGestureRecognizer(gestureRecognizer)
}
override func numberOfSections(in 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 7
}
func triggerTouchAction(gestureReconizer: UITapGestureRecognizer) {
//Add alert to show it works
print("Map Tapped")
}
}
I would love to be able to move forward with this part of my app. Thank you in advance for helping me out. I am very new to coding and wish I had gotten my degree in it.
Related
I am unable to populate a swift cell-based tableview in macOS 10.14.6 using an Xcode 11.2 xib. The app is Document based and the tableView is created with a separate WindowController xib. A similar project created programmatically in Xcode works ok, including drag and drop; I am relatively new to using xibs and likely have not set things correctly. A column identifier has been set in the xib and NSTableViewDataSource and NSTableViewDelegate have been added to the Window Controller. Pertinent source code follows and the complete Xcode project may be downloaded here: https://www.dropbox.com/s/6tsb98b7iihhfxl/tableView.zip?dl=0
Any help in getting the tableView populated with a String array would be appreciated. I would also like to get drag and drop working but can get by for now just getting the array items to show up in the table view. It correctly creates four rows, corresponding to the number of elements in the array, but there is no visible text. The tableView is cell-based, but I could use view-based if that would work better. Thank you in advance.
class WindowController: NSWindowController, NSTableViewDataSource, NSTableViewDelegate {
#IBOutlet var tableView: NSTableView!
var sports : [String] = ["Basketball","Baseball","Football","Tennis"]
override func windowDidLoad() {
super.windowDidLoad()
tableView.registerForDraggedTypes([NSPasteboard.PasteboardType.fileURL])
tableView.dataSource = self
tableView.delegate = self
}
func numberOfRows(in tableView: NSTableView) -> Int {
return (sports.count)
}
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
var value : Any? = 0
let columnIdentifier : String = (tableColumn?.identifier.rawValue)!
if (columnIdentifier == "Col1"){
value = sports[row]
}
return value
}
In Document.swift windowController is released at the end of showTableView() and the table view looses its data source. Add windowController to the window controllers of the document or hold a strong reference to windowController.
#IBAction func showTableView(_ sender: Any) {
let windowController = WindowController.init(windowNibName:NSNib.Name("WindowController"))
addWindowController(windowController)
windowController.showWindow(nil)
}
I am extremely new to Swift so I am guessing this is a rookie mistake but here's my situation:
I am trying to create an application that allows you to add things to a list. I have a NSTextField where users input there data and a NSButton to add that data to the myTeam array. The tableView is binded (I think that's what you call it) to the myTeam array.
When I run the application a table containing the preset values of myTeam populate the table view correctly, but when I add to this array nothing happens. After research, I found this question.
Unfortunately, like most swift tutorials and Q&A, it was for iOS. But I thought I would give it a try. I added
self.tableView.reloadData()
self.refresher.endRefreshing()
to my code, and received two errors: Value of type '(NSTableView, NSTableColumn?, Int) -> Any?' has no member 'reloadData' and Value of type 'ViewController' has no member 'refresher', respectively.
Heres my code below:
import Cocoa
import Darwin
class ViewController: NSViewController, NSTableViewDataSource {
var myTeam = ["Test", "Test2"]
#IBOutlet weak var myText: NSTextField!
#IBOutlet weak var AddMember: NSButton!
#IBAction func addmem(_ sender: Any) {
myTeam.append(myText.stringValue);
self.tableView.reloadData()
self.refresher.endRefreshing()
}
override func viewDidLoad() {
super.viewDidLoad()
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
// MARK: DataSource
func numberOfRows(in tableView: NSTableView) -> Int {
return myTeam.count
}
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
return myTeam[row]
}
}
P.S. I used this tutorial to get as far as I did.
Simplest solution, we are going to use (full) Cocoa Bindings:
Replace the entire code with
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var myText: NSTextField!
#objc dynamic var myTeam = ["Test", "Test2"]
#IBAction func addmem(_ sender: NSButton) {
myTeam.append(myText.stringValue)
}
}
In Interface Builder select the table view (not the enclosing scroll view) and press ⌥⌘6 (Connections Inspector)
Disconnect dataSource
Press ⌥⌘7 (Bindings Inspector)
Bind Content to ViewController > Model Key Path myTeam
Since you are still using objectValueFor I assume that the value of the table cell view is already bound to objectValue.
macOS doesn't know a refresher.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I working with swift 4 for osx and I would like to realize a address autocomplete function like apple maps does:
How can I do something like the image shows?
I guess the structure will be:
a simple NSTextfield
but what is the popup menu? is it a simple popover?
UPDATE
Now my app works like this:
Thats brilliant.
But one little problem:
I write my first character into the textfield, the popover will be shown and the textfield lost the focus. Now I have to click again in my textfield to go on. Is there a way to keep the focus of this textfield?
I ported the Apple "CustomMenus" example from Objective-C to Swift. The example includes a search completions dropdown menu for NSSearchField:
https://github.com/dougzilla32/CustomMenus
Original example on the Apple site in Objective-C:
https://developer.apple.com/library/content/samplecode/CustomMenus
i solve the situation like this:
use the controlTextDidChange and present a popover
override func controlTextDidChange(_ obj: Notification) {
vcAddress.searchString = txtSourceAddress.stringValue
self.presentViewController(vcAddress, asPopoverRelativeTo: txtSourceAddress.bounds, of: txtSourceAddress, preferredEdge: .maxX, behavior: .semitransient)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "AutoComplete"), object: nil)
}
the popover has a tableview, which gets the suggestions with the SearchCompleter (MapKit)
import Cocoa
import MapKit
class AcAddress: NSViewController, NSTableViewDelegate, NSTableViewDataSource, MKLocalSearchCompleterDelegate {
var searchString:String?
var searchCompleter = MKLocalSearchCompleter()
var searchResults = [MKLocalSearchCompletion]()
#IBOutlet weak var tblAutoComplete: NSTableView!
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(AutoComplete), name: NSNotification.Name(rawValue: "AutoComplete"), object: nil)
searchCompleter.delegate = self
tblAutoComplete.refusesFirstResponder = true
}
#objc func notificationAutoComplete() {
searchCompleter.queryFragment = searchString ?? ""
}
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
searchResults = completer.results
tblAutoComplete.reloadData()
}
func numberOfRows(in tableView: NSTableView) -> Int {
return searchResults.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
// FILL IT
}
}
When I want to make an UITableView inside of an ViewController.
I have made all exactly as in a tutorial in which it worked, but I got this Error "Thread one signal SIGABRT" on class AppDelegate: UIResponder, UIApplicationDelegate { in AppDelegate.swift.
I have recently asked this question with all codes before, but every answer said, they need more information.
So i have made the whole Xcode Project new and I have filmed it with Screenium.
Here is the video (10 minutes; 53 Megabyte) https://workupload.com/file/24NNW68.
You must give in the Password
ThePassword
Then there is the information of the "video.mov". Click on the below (blue) download, the abowe is advertising.
For people who don't want to see the video (I've made it when I was 14, so my voice is a bit high: Here is the complete code:
AppDelegate.swift:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var Label1multi = ["TableView","Alarm Clock","Green","Book"]
var Label2multi = ["Pen", "1 Euro","Red","Mobile Phone"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! THISTableViewCell
cell.Label1.text = Label1multi[indexPath.row]
cell.Label2.text = Label2multi[indexPath.row]
return cell
}
}
THISTableViewCell.swift:
import UIKit
class THISTableViewCell: UITableViewCell {
#IBOutlet weak var Label1: UILabel!
#IBOutlet weak var Label2: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
But I've found the failure: When I remove The Outlet TableView - DataSource I don't get the error, but I only get empty cells in the TableView.
I have watched your video. I think the mistake is a small one. You need to set the reuse identifier for your custom cell to be "cell" in the attributes inspector. You use it correctly in this method:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! THISTableViewCell
cell.Label1.text = Label1multi[indexPath.row]
cell.Label2.text = Label2multi[indexPath.row]
return cell
}
Select the cell in main.storyboard and select the attributes inspector. Enter "cell" in the "identifier" box.
I am trying to link to another view controller by pressing a button which i have named 'find'. The issue is with the pickerView. i want the 'service' selected from the pickerView to determine which page you end up on. For example, you select 'bars' in the pickerView, you click the 'find' button and it takes you to the bars view controller page.
Here is my code which controls the picker and the find button.
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate {
#IBOutlet weak var SelectedService: UILabel!
#IBAction func Find(sender: AnyObject) {
}
#IBOutlet weak var ItemLabel: UILabel!
var services = ["Cafe","Coffee Shops","Bar","Takeaway","Sunday Roast","Shoe Mender","Craft Shops","Electrical"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return services.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String!{
return services[row]
}
}
I am new to coding with swift so please could you explain your answer in a simple way.
Thank you very much
Shaun
In #IBAction func Find() you could have switch statement where you check which item from UIPickerView was selected, and based on that you can present desired view controller like this:
let cafeViewController: CafeViewController = CafeViewController()
self.presentViewController(cafeViewController, animated: true, completion: nil)
But are you sure you need it's own view controller for every item? They'll probably look exactly the same, only presented data will be different... so you could use just one view controller, send picked item in func prepareForSegue() and according on that prepare data in viewDidLoad() in that view controller.
Or at least try to reuse as much as you can creating some base class for your view controller and then create subclass for each service.