I have a TextField in my settingsController that i can modify selecting a name from a pickerView, the problem is this : when i change the text of my textField i also change the text of a label in another controller, it work but when i close and reopen my app the label is empty, i can't find a way to save the text that i give it with the pickerView.
My code in the settingsController
override func viewDidLoad() {
super.viewDidLoad()
var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
if let firstNameIsNotNill = defaults.objectForKey("firstName") as? String {
self.currencyLabel.text = defaults.objectForKey("firstName") as String
}
currencyLabel.delegate = self
}
func currencyDoneClicked(sender: UIBarButtonItem) {
var myRow = picker.selectedRowInComponent(0)
currencyLabel.text = pickerData.objectAtIndex(myRow) as NSString
DataManager.sharedInstance.contenitore = currencyLabel.text
var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(self.currencyLabel.text, forKey: "firstName")
defaults.synchronize()
}
DataManager :
import UIKit
class DataManager: NSObject {
class var sharedInstance:DataManager {
get {
struct Static {
static var instance : DataManager? = nil
static var token : dispatch_once_t = 0
}
dispatch_once(&Static.token) { Static.instance = DataManager() }
return Static.instance!
}
}
var contenitore : String!
}
And in the other controller :
override func viewDidLoad() {
super.viewDidLoad()
labelCurrency.text = DataManager.sharedInstance.contenitore
}
Just use NSUserDefaults.
NSUserDefaults.standardUserDefaults().setValue(textField.text, forKey: "savedTextField")
Then, when you start up again, populate the field in viewDidLoad or viewWillAppear.
if let text = NSUserDefaults.standardUserDefaults().stringForKey("savedTextField") {
textField.text = text
}
Related
I have this ScreenSecurityWorker
final class ScreenSecurityWorker {
weak var delegate: ScreenSecurityWorkerDelegate?
private var isPassPhraseOn: Bool { return SettingsManager.shared.load(.passPhrase) }
private var isPassPhraseForced: Bool { return environment.forcePassPhraseEnabled }
var screenSecurityEnabled = false
inside my Mainrouter I am changing screenSecurityEnabled bool value to true at activateScreenSecurity
func activateScreenSecurity() {
guard !screenSecurityWorker.passwordSecurityInProgress else { return }
screenSecurityVC = ScreenSecurityBuiler.make()
app.dismissKeyboardOnTopVC()
app.window.rootViewController = screenSecurityVC
screenSecurityWorker.passPhareSuccess = false
screenSecurityWorker.screenSecurityEnabled = true
}
I am trying to reach to screenSecurityEnabled from ChatVC
but if I init it as
let screenSecurityWorker = ScreenSecurityWorker()
it has no values inside at all.
if I try like this it gives error
let screenSecurityWorker : ScreenSecurityWorker?
init(screenSecurityWorker: ScreenSecurityWorker){
self.screenSecurityWorker = screenSecurityWorker
}
I need this screenSecurityWorker.screenSecurityEnabled to change subviews in this function inside ChatVC
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if screenSecurityWorker!.screenSecurityEnabled {
let place = chatTextAreaContainerView.bounds.height + CGFloat(lastContentOffset ?? collectionView.contentOffset.y - chatTextAreaContainerView.bounds.height)
self.collectionView.contentOffset.y = place
screenSecurityWorker!.screenSecurityEnabled = false
}
}
I try to implement search behavior like in Xcode: if you enter something in search field, icon changes color.
I delegate both searchFieldDidStartSearching and searchFieldDidEndSearching to controller and change the image.
The problem is icon's image changes only when window lose it's focus.
class ViewController: NSViewController {
#IBOutlet weak var searchField: NSSearchField!
func searchFieldDidStartSearching(_ sender: NSSearchField) {
print("\(#function)")
(searchField.cell as! NSSearchFieldCell).searchButtonCell?.image = NSImage.init(named: "NSActionTemplate")
}
func searchFieldDidEndSearching(_ sender: NSSearchField) {
print("\(#function)")
(searchField.cell as! NSSearchFieldCell).searchButtonCell?.image = NSImage.init(named: "NSHomeTemplate")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
Thanks in advance for any ideas/suggestions.
Although I don't know the reason, it works:
NSApp.mainWindow?.resignMain()
NSApp.mainWindow?.becomeMain()
Here is the whole code:
class MyViewController: NSViewController {
private lazy var searchField: NSSearchField = {
let searchField = NSSearchField(string: "")
if let searchButtonCell = searchField.searchButtonCell {
searchButtonCell.setButtonType(.toggle)
let filterImage = #imageLiteral(resourceName: "filter")
searchButtonCell.image = filterImage.tinted(with: .systemGray)
searchButtonCell.alternateImage = filterImage.tinted(with: .systemBlue)
}
searchField.focusRingType = .none
searchField.bezelStyle = .roundedBezel
searchField.delegate = self
return searchField
}()
...
}
extension MyViewController: NSSearchFieldDelegate {
func searchFieldDidStartSearching(_ sender: NSSearchField) {
sender.searchable = true
}
func searchFieldDidEndSearching(_ sender: NSSearchField) {
sender.searchable = false
}
}
extension NSSearchField {
var searchButtonCell: NSButtonCell? {
(self.cell as? NSSearchFieldCell)?.searchButtonCell
}
var searchable: Bool {
get {
self.searchButtonCell?.state == .on
}
set {
self.searchButtonCell?.state = newValue ? .on : .off
self.refreshSearchIcon()
}
}
private func refreshSearchIcon() {
NSApp.mainWindow?.resignMain()
NSApp.mainWindow?.becomeMain()
}
}
extension NSImage {
func tinted(with color: NSColor) -> NSImage? {
guard let image = self.copy() as? NSImage else { return nil }
image.lockFocus()
color.set()
NSRect(origin: NSZeroPoint, size: self.size).fill(using: .sourceAtop)
image.unlockFocus()
image.isTemplate = false
return image
}
}
I was having the same issue. A simple override fixed this issue for me
extension NSSearchField{
open override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
}
}
As you can see when you click inside the view it's still focussed on the search text field(as you can still type in it after you clicked underneath it). Since the change image is on when it loses focus, you should check if you clicked outside of the text field.
Solve problem by subclassing NSSearchFieldCell and assign this class to field's cell.
You don't even need to subclass NSSearchFieldCell.
When you create your NSSearchField from code, you can do something like this:
if let searchFieldCell = searchField.cell as? NSSearchFieldCell {
let image = NSImage(named: "YourImageName")
searchFieldCell.searchButtonCell?.image = image
searchFieldCell.searchButtonCell?.alternateImage = image // Optionally
}
If you're using storyboards, you can do the same in didSet of your #IBOutlet.
//Patient class
import Foundation
struct Patients {
var family: NSArray
var given: NSArray
var id: String
var birthdate:String
var gender: String
}
struct Address {
var city: String
var country: String
var line: NSArray
}
class Patient {
var flag = 0
var address = Address(city: "", country: "", line: [""])
var patient_info = Patients(family: [""], given: [""], id: "", birthdate: "", gender: "")
var response : AnyObject?
init(response: AnyObject) {
self.response = response
if let entry = response.objectForKey("entry") {
//MARK: Address
if let resource = entry[0].objectForKey("resource") {
if let add = resource.objectForKey("address") {
address.city = add[0].objectForKey("city")! as! String
address.country = add[0].objectForKey("country")! as! String
address.line = add[0].objectForKey("line")! as! NSArray
//MARK: patient
patient_info.birthdate = resource.objectForKey("birthDate")! as! String
patient_info.gender = resource.objectForKey("gender")! as! String
if let name = resource.objectForKey("name") {
patient_info.family = name[0].objectForKey("family")! as! NSArray
patient_info.given = name[0].objectForKey("given")! as! NSArray
}
}
}
//MARK: id
if let link = entry[0].objectForKey("link") {
if let url = link[0].objectForKey("url") {
let id = url.componentsSeparatedByString("/")
patient_info.id = id[id.count-1]
}
}
}
print(patient_info)
}
}
//ViewController class
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
var viewModel = ViewModel()
#IBOutlet weak var family_name: UITextField!
#IBOutlet weak var given_name: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
family_name.delegate = self
given_name.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
switch textField {
case family_name:
family_name.resignFirstResponder()
given_name.becomeFirstResponder()
case given_name:
given_name .resignFirstResponder()
default:
print("")
}
return true
}
#IBAction func search(sender: UIButton) {
let family_name1 = family_name.text!
let given_name1 = given_name.text!
viewModel .searchForPatient(family_name1, given_name: given_name1)
//When the name property from my patient class changed I can call the //below method. How to implement the observer?
performSegueWithIdentifier("showSegue", sender:sender)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender:AnyObject?){
if segue.identifier == "showPatientSegue" {
if let displayViewController = segue.destinationViewController as? DisplayViewController {
displayViewController.viewModelDisplay.patient = viewModel.patient
}
}
}
}
// ViewModel where I make the request.
import Foundation
import Alamofire
import SystemConfiguration
class ViewModel {
var patient = Patient!()
func searchForPatient(family_name: String, given_name : String) {
let header = ["Accept" : "application/json"]
Alamofire.request(.GET, "https://open-ic.epic.com/FHIR/api/FHIR/DSTU2/Patient?family=\(family_name)&given=\(given_name)", headers: header).responseJSON { response in
self.patient = Patient(response: response.result.value!)
}
}
func checkInternetConnection() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
}
var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
return false
}
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
return (isReachable && !needsConnection)
}
}
The problem is that the view loads fester than the request and I need to observe when a property has been changed in my Patient class, so the view can be loaded. If the view loads faster than the request I can't display the Patient information which I need.
You have lots options:
Store a delegate (weak!) object to the ViewController so that when your patient finishes, you can load the view. In the meantime, display something sensible in the view instead.
Send an NSNotification out, which the ViewController is a listener for.
KVO (Explanation of it here, just search for 'key-value observing'), which would require your Patient object to extend NSObject so that you can leverage objc's KVO.
Hope that helps!
You can add an observer on your variable this way :
var yourVariable:String!{
didSet{
refreshView()
}
}
I would like to call functions residing in other files. In my given example I received no syntax errors, and the app runs. When I click the IBAction, the App crashes. I have no idea why. I am using Xcode 6.4 and coding for OS X
please advise.
// FileUtilties.swift
import Foundation
import Cocoa
class FileUtilities: NSObject, NSAlertDelegate {
var fileList : String!
func listFilesFromDocumentsFolder() -> [String]
{
var theError = NSErrorPointer()
let dirs = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
if dirs != nil {
let dir = dirs![0]
let fileList = NSFileManager.defaultManager().contentsOfDirectoryAtPath(dir, error: theError)
return fileList as! [String] // edit: added ! for Swift 1.2 compatibitily
}
else{
let fileList : String!
}
return [fileList]
}
// Alert popup Window
func IdialogOKCancel(myQuestion: String, myText: String) -> Bool {
let myPopup: NSAlert = NSAlert()
myPopup.messageText = myQuestion
myPopup.informativeText = myText
myPopup.alertStyle = NSAlertStyle.WarningAlertStyle
myPopup.addButtonWithTitle("OK")
myPopup.addButtonWithTitle("Cancel")
let res = myPopup.runModal()
if res == NSAlertFirstButtonReturn {
return true
}
return false
}
}
// ViewController.swift
import Cocoa
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
// setsup outlet to add data to ListViewer
#IBOutlet weak var ListViewer: NSScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
#IBAction func AddButtonClicked(sender: AnyObject) {
var rtnText: String = "this is the text "
var rtn: Bool = false
let instance = FileUtilities()
rtn = instance.IdialogOKCancel("Ok?", myText: rtnText)
}
}
Why my data is lost in singleton? Please take a look:
class YtDataManager {
static var shared_instance = YtDataManager()
let apiKey = /*...*/
let /*...*/
var channelData = [NSObject:AnyObject]()
var videosArray = [[NSObject:AnyObject]]()
var playlistId: String { return self.channelData["playlistId"] as! String}
var urlStringForRequestChannelDetails: String { return String("https://www.googleapis.com/youtube/v3/channels?part=contentDetails,snippet&forUsername=\(self./*ChannelName*/)&key=\(self.apiKey)") }
var urlStringForRequestChannelVideos: String { return String("https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=\(self.playlistId)&key=\(self.apiKey)") }
func fn1() { /*...*/ }
func fn2() { /*...*/ }
// class definition continue...
Look, from one function(fn1) I'm writing data to channelData:
//...
self.channelData["title"] = snippetDict["title"]
self.channelData["playlistId"] = ((firstItemDict["contentDetails"] as! [NSObject:AnyObject])["relatedPlaylists"] as! [NSObject:AnyObject])["uploads"]
//...
and so on... From second function(fn2), I'm reading data:
//...
let targetURL = NSURL(fileURLWithPath: self.urlStringForRequestChannelVideos)
//...
Hence urlStringForRequestChannelVideos is computational property it uses playlistId (look code above).
Here I was surprised about emptiness of channedData from second function(I saw it in Debug mode, also I printed it's count to stdout outside of function). Why????
class YtFeedViewController: UIViewController {
#IBOutlet weak var menuButton:UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
YtDataManager.shared_instance.fn1()
print(YtDataManager.shared_instance.channelData.count) //0
YtDataManager.shared_instance.fn2() //errorness
}
self.navigationItem.title = "YouTube feed"
// Do any additional setup after loading the view.
}