Hi I am brand new to swift and need some help
Every time I run my code my app crashes and spits out a " the above error
Can anyone please tell me what I need to do or what I need to replace in my code?
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource{
#IBOutlet weak var picker: UIPickerView!
var employeeNames = ["John","Jane","Jack","James"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.picker.delegate = self
self.picker.dataSource = self
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return employeeNames.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return employeeNames [row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
print(employeeNames[row])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Your code is absolutely fine, so the only alternative is that you haven't hooked up your pickerView outlet. Ctrl click on your picker view in the storyboard and see if your outlet 'picker' shows up. If it doesn't then ctrl drag from the pickerView to your outlet to hook it up.
Related
I'm taking an iPhone app and making it available for Mac.
When I run the app on the Mac, the UIPicker displays nothing.
It places the cursor inside of the button and allows me to type, which is not the behavior I want (want to allow selecting from a list of options). Video in action.
I've tried putting Print statements in each of those functions (since removed) and they won't print so for whatever reason it seems like the functions themselves don't even run.
What approach(es) should I take to make a picker work on the Mac?
What am I screwing up?
What other information should I provide?
UI Picker (using UIKit):
// Mortgage Length Picker
#IBOutlet weak var mortgageLengthButton: UITextField!
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return mortgageLengthData.count
}
func pickerView( _ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return mortgageLengthData[row]
}
func pickerView( _ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
mortgageLengthButton.text = mortgageLengthData[row]
let mortgageArray = mortgageLengthData[row].components(separatedBy: " ")
mortgageLengthYears = Int(mortgageArray[0]) ?? 30
calculateMortgage()
calculateCashFlow()
}
OS 10.15.6
xCode 12.0.1
I am trying to download an image from my web server, using Xcode 8 and Swift 3. It looks like this. The request returns nil. Any suggestions why?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var view1: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func load(_ sender: UIButton) {
let url = URL(string:"http://www.example.com/folder2/pic3-1.jpg")
let task = URLSession.shared.dataTask(with: url!) { data, response,
error in
guard let data = data, error == nil else { return }
DispatchQueue.main.sync() {
self.view1.image = UIImage(data: data)
}
}
task.resume()
}
#IBAction func reset(_ sender: UIButton) {
self.view1.image="blankU.png"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
Any idea why the image is returning nil from the server?
The Xcode8, Swift3 coding is okay. The server is blocked.
I have a swift project with a custom cell from a tableview, ans inside it I have a label to display the value of a UIPicker. The UiPicker appear in the keyboard when you press the label, I wan't to be able to set default values to my UIPicker, I tried a lot of differents technics with the 2 methods :
selectRow(), without success, here is my CustomCell code :
import UIKit
class CustomCell: UITableViewCell, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet weak var answer: UITextField!
var delegate: QuestionSelectorCellDelegate?
var pickOption: [String] = []
var pickerView:UIPickerView = UIPickerView()
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#IBAction func editBeginQuestionSelectorCell(sender: UITextField) {
pickerView = UIPickerView()
pickerView.delegate = self
sender.inputView = pickerView
}
func displayBlock(block: Block){
if block.answers != nil {
pickOption = block.answers! // block.answers! = ["blue","red","green"] for example
}
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickOption.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickOption[row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if row < pickOption.count {
answer.text = pickOption[row]
delegate?.updateQuestionSelectorCell(self, rep: pickOption[row])
}
}
}
Updated your code.
You didn't set the pickerView.dataSource!
If i understood your question, you want an element to be selected by default, other than element at index 0.
I also added that.
import UIKit
class CustomCell: UITableViewCell, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet weak var answer: UITextField!
var delegate: QuestionSelectorCellDelegate?
var pickOption: [String] = []
var pickerView:UIPickerView = UIPickerView()
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#IBAction func editBeginQuestionSelectorCell(sender: UITextField) {
pickerView = UIPickerView()
pickerView.delegate = self
// --- Thats what I added ---
pickerView.dataSource = self
let indexOfDefaultElement = 1 // Make sure that an element at this index exists
pickerView.selectRow(indexOfDefaultElement, inComponent: 0, animated: false)
sender.inputView = pickerView
}
func displayBlock(block: Block){
if block.answers != nil {
pickOption = block.answers! // block.answers! = ["blue","red","green"] for example
}
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickOption.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickOption[row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if row < pickOption.count {
answer.text = pickOption[row]
delegate?.updateQuestionSelectorCell(self, rep: pickOption[row])
}
}
}
The func yesBtSetTextTo prints not nil when called from the grey button in the pink area, but the same func print nil when is called from the yellow button. I am lost on this one.
My main veiwController.swift does not have a prepareForSegue since I did not thing it is needed here.
The func in question is at the end of this code block,
MainBtVC.swift
protocol MainBtDelegate {
func yesBtSetTextTo(name: String)
}
class MainBtVC: UIViewController, MainBtDelegate {
#IBOutlet weak var yesBt: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func yesBtSetTextTo(name: String) {
print("called")
if yesBt == nil {
print("button is nil")
} else {
print("button not nil")
}
// yesBt.setTitle("Exit", forState: UIControlState.Normal)
}
#IBAction func yesBtTapped(sender: AnyObject) {
yesBtSetTextTo("dummy")
}
TopVC.swift
class TopVC: UIViewController {
var delegate: MainBtDelegate?
override func viewDidLoad() {
super.viewDidLoad()
delegate = MainBtVC()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func buttonTapped(sender: AnyObject) {
delegate?.yesBtSetTextTo("Exit")
}
I have the following code that loads a video and loops it. However, when pressing home and returning to the application the video freezes and will not play again. I feel like the answer is in the AppDelegate functions but can not seem to get them to work.
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController, UIApplicationDelegate {
var videoPlayer: AVPlayer!
var playerLayer: AVPlayerLayer?
override func viewDidLoad() {
super.viewDidLoad()
let path = NSBundle.mainBundle().pathForResource("video", ofType:"mp4")
let url = NSURL(fileURLWithPath: path!)
let playerItem = AVPlayerItem(URL: url)
self.videoPlayer = AVPlayer(playerItem: playerItem)
self.playerLayer = AVPlayerLayer(player: self.videoPlayer)
self.playerLayer!.frame = self.view.frame
self.videoPlayer!.play()
self.view.layer.addSublayer(self.playerLayer!)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("playerDidReachEnd:"), name: AVPlayerItemDidPlayToEndTimeNotification, object:nil)
}
func playerDidReachEnd(notification: NSNotification) {
self.videoPlayer.seekToTime(kCMTimeZero)
self.videoPlayer.play()
}
func applicationWillResignActive(application: UIApplication) {
videoPlayer.pause()
}
func applicationDidBecomeActive(application: UIApplication) {
videoPlayer.play()
}
func applicationDidEnterBackground(application: UIApplication) {
videoPlayer.pause()
}
func applicationWillEnterForeground(application: UIApplication) {
videoPlayer.play()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Here is what I used to fix it.
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController, UIApplicationDelegate {
var videoPlayer: AVPlayer!
var playerLayer: AVPlayerLayer?
override func viewDidLoad() {
super.viewDidLoad()
let path = NSBundle.mainBundle().pathForResource("video", ofType:"mp4")
let url = NSURL(fileURLWithPath: path!)
let playerItem = AVPlayerItem(URL: url)
self.videoPlayer = AVPlayer(playerItem: playerItem)
self.playerLayer = AVPlayerLayer(player: self.videoPlayer)
self.playerLayer!.frame = self.view.frame
self.videoPlayer!.play()
self.view.layer.addSublayer(self.playerLayer!)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("continueVideo:"), name: "continueVideo", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("playerDidReachEnd:"), name: AVPlayerItemDidPlayToEndTimeNotification, object:nil)
}
func playerDidReachEnd(notification: NSNotification) {
self.videoPlayer.seekToTime(kCMTimeZero)
self.videoPlayer.play()
}
func continueVideo(notification: NSNotification) {
self.videoPlayer.play()
}
func applicationWillResignActive(application: UIApplication) {
videoPlayer.pause()
}
func applicationDidBecomeActive(application: UIApplication) {
videoPlayer.play()
}
func applicationDidEnterBackground(application: UIApplication) {
videoPlayer.pause()
}
func applicationWillEnterForeground(application: UIApplication) {
videoPlayer.play()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
And the app delegate portion
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
return true
}
func applicationWillResignActive(application: UIApplication) {
}
func applicationDidEnterBackground(application: UIApplication) {
}
func applicationWillEnterForeground(application: UIApplication) {
NSNotificationCenter.defaultCenter().postNotificationName ("continueVideo", object:nil)
}
func applicationDidBecomeActive(application: UIApplication) {
}
func applicationWillTerminate(application: UIApplication) {
}
}
This is a simple fix, you need to create a NSNotification and call it from your AppDelegate:
func applicationWillEnterForeground(application: UIApplication) {
NSNotificationCenter.defaultCenter().postNotificationName("continueVideo", object: nil)
}
SWIFT3 Update
func applicationWillEnterForeground(_ application: UIApplication) {
// NOTE: Notification.Name raw value should be global
NotificationCenter.default.post(name: Notification.Name(rawValue: "com.yourappname.continueVideo"), object:self)
}
And the receive that notification in the normal way:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "<funcName>:", name: "continueVideo", object: nil)
SWIFT3 Update
NotificationCenter.default.addObserver(self, selector: #selector(<funcName>), name: Notification.Name(rawValue: "com.yourappname.continueVideo"), object: nil)