So i have a firebase structure like the pic below
Now i want to retrieve that image file that i've uploaded. to decode the base64String and show it. Every user can make a post and the information that will be sended to firebase has a description etc. and also have an image. now i tried to retrieve it whit this codes but nothing did work.
var REF_LIST = Firebase(url: "\(URL_BASE)/listItems")
REF_LIST.observeEventType(FEventType.Value, withBlock: { snapshot in
let image = snapshot.value.objectForKey("images") as! String
but this already gave me a nil error on that line, so i couldn't even decode. i think i understand why it's giving me a nil error, there is no images in listItems on firebase, you first have the unique ID and then the specs with images in. now i don't now how i can retrieve that information from that unique ID?
UPDATE:
the tableViewController what will receive the data from firebase:
import UIKit
import FBSDKLoginKit
import Alamofire
import Firebase
class ListVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var lists = [List]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
dispatch_async(backgroundQueue, {
self.initObservers()
})
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.tableView.reloadData()
}
func initObservers() {
LoadingOverlay.shared.showOverlay(self.view)
DataService.ds.REF_LISTS.observeEventType(.Value, withBlock: { snapshot in
print(snapshot.value)
self.lists = []
if let snapshots = snapshot.children.allObjects as? [FDataSnapshot] {
for snap in snapshots {
print("SNAP: \(snap)")
if let listDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let list = List(listKey: key, dictionary: listDict)
self.lists.insert(list, atIndex:0)
}
}
}
self.tableView.reloadData()
LoadingOverlay.shared.hideOverlayView()
})
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lists.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCellWithIdentifier("ListCell") as? ListCell {
let list = self.lists[indexPath.row]
cell.request?.cancel()
cell.configureCell(list)
return cell
} else {
return ListCell()
}
}
}
the addController which post the data to firebase:
import UIKit
import Firebase
import Alamofire
import FBSDKCoreKit
class AddVC: UIViewController, UITextFieldDelegate, UITextViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var addTitle: UITextField!
#IBOutlet weak var addDescription: UITextView!
#IBOutlet weak var addLocation: UITextField!
#IBOutlet weak var placeholderLbl: UILabel!
#IBOutlet weak var freeSwitch: UISwitch!
#IBOutlet weak var tradeSwitch: UISwitch!
#IBOutlet weak var imageSelectorImg: UIImageView!
#IBOutlet weak var overlayView: UIView!
var currentUsername = ""
var imageSelected = false
var imagePicker: UIImagePickerController!
var base64String: NSString = ""
override func viewDidLoad() {
super.viewDidLoad()
addTitle.delegate = self
addDescription.delegate = self
addLocation.delegate = self
imagePicker = UIImagePickerController()
imagePicker.delegate = self
getCurrentUser()
hideKeyboardWhenTappedAround()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
addTitle.text = ""
addDescription.text = ""
addLocation.text = ""
freeSwitch.setOn(false, animated: false)
tradeSwitch.setOn(false, animated: false)
placeholderLbl.hidden = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getCurrentUser() {
DataService.ds.REF_USER_CURRENT.observeEventType(FEventType.Value, withBlock: { snapshot in
let currentUser = snapshot.value.objectForKey("username") as! String
print("Username: \(currentUser)")
self.currentUsername = currentUser }, withCancelBlock: { error in
print(error.description)
})
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
imagePicker.dismissViewControllerAnimated(true, completion: nil)
imageSelectorImg.image = image
dispatch_async(backgroundQueue, {
let uploadImage = image
let imageData = UIImageJPEGRepresentation(uploadImage, 0.5)
self.base64String = imageData!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
})
imageSelected = true
}
#IBAction func selectImage(sender: UITapGestureRecognizer) {
presentViewController(imagePicker, animated: true, completion: nil)
}
func postToFirebase() {
// LoadingOverlay.shared.showOverlay(self.overlayView)
var post: Dictionary<String, AnyObject> = ["username": self.currentUsername, "description": self.addDescription.text!, "title": self.addTitle.text!, "location": self.addLocation.text!, "images": self.base64String]
if self.freeSwitch.on && self.tradeSwitch.on {
post["tradeOption"] = "Gratis/Te ruil"
} else if self.freeSwitch.on {
post["tradeOption"] = "Gratis"
} else if self.tradeSwitch.on {
post["tradeOption"] = "Te ruil"
}
let firebasePost = DataService.ds.REF_LISTS.childByAutoId()
firebasePost.setValue(post)
}
#IBAction func postListItem(sender: AnyObject) {
if let addTitle = addTitle.text where addTitle != "", let addDescription = addDescription.text where addDescription != "", let addLocation = addLocation.text where addLocation != "" {
dispatch_async(backgroundQueue, {
self.postToFirebase()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let listVC = storyboard.instantiateViewControllerWithIdentifier("TBC") as! UITabBarController
listVC.selectedIndex = 1
self.presentViewController(listVC, animated: false, completion: nil)
})
})
}
}
func textViewDidBeginEditing(textView: UITextView) {
placeholderLbl.hidden = true
}
func textViewDidEndEditing(textView: UITextView) {
if textView.text == "" {
placeholderLbl.hidden = false
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
and the swift file to configure the cell:
import UIKit
import Alamofire
import Firebase
class ListCell: UITableViewCell {
#IBOutlet weak var listImg: UIImageView!
#IBOutlet weak var listTitle: UILabel!
#IBOutlet weak var listTradeOption: UILabel!
#IBOutlet weak var listLocation: UILabel!
#IBOutlet weak var headImg: UIImageView!
var list: List!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func retrieveImages() {
DataService.ds.REF_LISTS.observeEventType(FEventType.Value, withBlock: { snapshot in
if let snapshots = snapshot.children.allObjects as? [FDataSnapshot] {
for snap in snapshots {
let image = snap.value.objectForKey("images") as! String
let decodedData = NSData(base64EncodedString: image, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
let decodedImage = UIImage(data: decodedData!)
self.headImg.image = decodedImage
}
}
})
}
func configureCell(list: List) {
self.list = list
self.listTitle.text = list.listTitle
self.listTradeOption.text = list.listTradeOption
self.listLocation.text = list.listLocation
retrieveImages()
}
}
also the list Model file:
import Foundation
import Firebase
class List {
private var _listTitle: String!
private var _listDescription: String!
private var _listTradeOption: String!
private var _listLocation: String!
private var _listImageURL: String?
private var _listKey: String!
private var _listRef: Firebase!
var listTitle: String? {
return _listTitle
}
var listDescription: String? {
return _listDescription
}
var listTradeOption: String? {
return _listTradeOption
}
var listLocation: String? {
return _listLocation
}
var listKey: String {
return _listKey
}
var listImageURL: String? {
return _listImageURL
}
init(title: String, description: String, tradeOption: String, location: String, listImageURL: String?) {
self._listTitle = title
self._listDescription = description
self._listTradeOption = tradeOption
self._listLocation = location
self._listImageURL = listImageURL
}
init(listKey: String, dictionary: Dictionary<String, AnyObject>) {
self._listKey = listKey
if let title = dictionary ["title"] as? String {
self._listTitle = title
}
if let desc = dictionary ["description"] as? String {
self._listDescription = desc
}
if let trade = dictionary ["tradeOption"] as? String {
self._listTradeOption = trade
}
if let loc = dictionary ["location"] as? String {
self._listLocation = loc
}
if let imgUrl = dictionary["images"] as? String {
self._listImageURL = imgUrl
}
self._listRef = DataService.ds.REF_LISTS.childByAppendingPath(self._listKey)
}
}
i've got also a DataServicefile, where i create a user by unique ID with this code:
var REF_USER_CURRENT: Firebase {
let uid = NSUserDefaults.standardUserDefaults().valueForKey(KEY_UID) as! String
let user = Firebase(url: "\(REF_BASE)").childByAppendingPath("users").childByAppendingPath(uid)
return user!
}
func createFirebaseUser(uid: String, user: Dictionary<String, String>) {
REF_USERS.childByAppendingPath(uid).setValue(user)
}
i know it's a lot but maybe the best way to help :)
Try editing this in List Cell
var imageURL = String()
func retrieveImages() {
let decodedData = NSData(base64EncodedString: imageURL, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
let decodedImage = UIImage(data: decodedData!)
self.headImg.image = decodedImage
}
func configureCell(list: List) {
self.list = list
self.listTitle.text = list.listTitle
self.listTradeOption.text = list.listTradeOption
self.listLocation.text = list.listLocation
self.imageURL = list.listImageURL //you already had the image url for that specific cell
retrieveImages()
}
Storing and accessing images using base64String in firebase is not an
efficient way, instead of that we can use FirebaseStorage (Google cloud storage
bucket) for uploading images to Firebase and it will provide us
download URL for a particular image. We can store that URL into our database simply in a string format and access it whenever we
required and then download the corresponding image from that URL by
using SDWebImage.
Refer below link for integrating FirebaseStorage into your project: https://firebase.google.com/docs/storage/ios/upload-files
Related
I'm trying to display the users username that stored in firebase. I'm not sure if Im saving the username correctly or if that's even the problem. I can't seem to access the data or display it at all. Any tips? I have a screenshot of the Cloud Firestore attached.
SignupViewController
import UIKit
import FirebaseAuth
import Firebase
import AVKit
import FirebaseFirestore
class SignUpViewController: UIViewController {
var videoPlayer:AVPlayer?
var videoPlayerLayer:AVPlayerLayer?
#IBOutlet weak var firstNameTextField: UITextField!
#IBOutlet weak var lastNameTextField: UITextField!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var BackButton: UIButton!
#IBOutlet weak var UserNameTextField: UITextField!
#IBOutlet weak var signUpButton: UIButton!
#IBOutlet weak var errorLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing))
view.addGestureRecognizer(tap)
// Do any additional setup after loading the view.
setupElements()
}
func setupElements(){
//hides the error label
errorLabel.alpha = 0
//styles the text and buttons
Utilities.styleTextField(UserNameTextField)
Utilities.styleTextField(firstNameTextField)
Utilities.styleTextField(lastNameTextField)
Utilities.styleTextField(passwordTextField)
Utilities.styleTextField(emailTextField)
Utilities.styleFilledButton(signUpButton)
}
/*
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
// this function makes sure all data is good
func validateFields() -> String?
{
//make sure fields are filled
if firstNameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" || lastNameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" || emailTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" || UserNameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == ""
{
return "Please fill all fields"
}
let cleanPassword = passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
if Utilities.isPasswordValid(cleanPassword) == false{
return "Needs 8 charaters, number, and special charater"
}
return nil
}
#IBAction func signUpTapped(_ sender: Any) {
//validate fields
let error = validateFields()
if error != nil{
showError(error!)
}
else{
let firstName = firstNameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let lastName = lastNameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let email = emailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let username = UserNameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
//create user
Auth.auth().createUser(withEmail: email, password: password) { result, err in
if err != nil{
self.showError("Error creating user")
}
else
{
//User is stored sucessfully, store the first and last name
let database = Firestore.firestore()
database.collection("UserInfo").addDocument(data: ["firstname": firstName,"email": email, "lastname": lastName, "username": username, "uid": result!.user.uid]) {(error) in
if error != nil
{
self.showError("First name and last name couldnt be saved.")
}
}
self.transitionToHome()
}
}
}
}
func showError(_ message:String){
errorLabel.text = message
errorLabel.alpha = 1
}
func transitionToHome(){
let homeViewController = storyboard?.instantiateViewController(identifier: Constants.StoryBoard.homeViewController) as?
HomeViewController
view.window?.rootViewController = homeViewController
view.window?.makeKeyAndVisible()
}
override func viewWillAppear(_ animated: Bool) {
//Set up video in background
setUpVideo()
}
func setUpVideo(){
//Get path to resource bundle
let bundlePath = Bundle.main.path(forResource: "IMG_7211 2", ofType: "mov")
guard bundlePath != nil else{
return
}
//create the url from it
let url = URL(fileURLWithPath: bundlePath!)
//Create The video Player item
let item = AVPlayerItem(url: url)
//create the player
videoPlayer = AVPlayer(playerItem: item)
//create the layer
videoPlayerLayer = AVPlayerLayer(player: videoPlayer!)
//adjust the size and frame
videoPlayerLayer?.frame = CGRect(x: -self.view.frame.size.width*1.5, y:0, width: self.view.frame.size.width*4, height: self.view.frame.size.height)
view.layer.insertSublayer(videoPlayerLayer!, at: 0)
//add and play
videoPlayer?.playImmediately(atRate: 0.8)
}
}
CurrentUser.swift
import Foundation
struct CurrentUser{
let uid: String
let name: String
let email: String
let profilepictureURL:String
init(uid: String, dictionary: [String: Any]){
self.uid = uid
self.name = dictionary["username"] as? String ?? ""
self.email = dictionary["email"] as? String ?? ""
self.profilepictureURL = dictionary["profilepictureURL"] as? String ?? ""
}
}
ProfileViewController
import UIKit
import Firebase
import FirebaseAuth
import FirebaseInstallations
import FirebaseFirestore
import FirebaseStorage
import FirebaseDatabase
class ProfileViewController: UIViewController {
#IBOutlet weak var SignOut: UIButton!
#IBOutlet weak var UserName: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
UserNameLabel()
// Do any additional setup after loading the view.
}
func UserNameLabel()
{
if Auth.auth().currentUser != nil
{
guard let uid = Auth.auth().currentUser?.uid else {return}
Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value) { (snapshot) in
guard let dict = snapshot.value as? [String: Any] else {return}
let user = CurrentUser(uid: uid, dictionary: dict)
self.UserName.text = user.username
}
}
}
#IBAction func SignOut(_ sender: Any) {
if Auth.auth().currentUser != nil {
do {
try Auth.auth().signOut()
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Vc")
vc.modalPresentationStyle = .fullScreen
present(vc, animated: true, completion: nil)
}
catch let error as NSError {
print(error.localizedDescription)
}
}
}
}
The problem is you are saving the data to Firebase Firestore, and then trying to access it from firebase real time database. Firebase Realtime Database and Firebase Firestore are 2 completely different backend servers and you are trying to use both at the same time. You need to pick only 1 and stick with it.
You are saving it to firebase firestore by using:
let database = Firestore.firestore()
database.collection("UserInfo").addDocument()
then after you save it to firestore you are trying to access it from real time database, not Firestore which is causing it to return nil:
Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value) { (snapshot) in
So instead what you need to do is get it back from firestore by using this:
Firestore.firestore().collection("s").getDocuments { query, error in
for doc in query!.documents {
// Successfully retrieved data from firestore.
}
}
Note: You could also instead save it to the real time database instead of firestore, but it just depends which one will work better for your app. You need to pick either Firestore or the Database, you can't use both. Here is more info to help you decide which one is better. More Info
I have a problem.
I've implemented the visionkit framework in order to detect a text when the camera is used.
The problem is that the colors of the buttons: "Keep Scan" and "Retake" are blue. I want them in black color. How can I fix this problem? I paste my code.
Thank you in advance!
import UIKit
import Vision
import VisionKit
class ScanText: UIViewController, VNDocumentCameraViewControllerDelegate {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var TextScan: UITextView!
#IBOutlet weak var buttonStartShape: UIButton!
#IBOutlet weak var infoScattaUnaFoto: UILabel!
#IBOutlet weak var copyButtonShape: UIButton!
var textRecognitionRequest = VNRecognizeTextRequest(completionHandler: nil)
private let textRecognitionWorkQueue = DispatchQueue(label: "MyVisionScannerQueue", qos: .userInitiated, attributes: [], autoreleaseFrequency: .workItem)
var classView = ViewController()
var arrayText = String()
override func viewDidLoad() {
super.viewDidLoad()
imageView.layer.cornerRadius = 15
imageView.clipsToBounds = true
TextScan.layer.cornerRadius = 15
TextScan.clipsToBounds = true
copyButtonShape.layer.cornerRadius = 25
copyButtonShape.clipsToBounds = true
buttonStartShape.layer.cornerRadius = 25
buttonStartShape.clipsToBounds = true
TextScan.isEditable = true
setupVision()
}
#IBAction func TakePicture(_ sender: Any) {
let scannerViewController = VNDocumentCameraViewController()
scannerViewController.delegate = self
present(scannerViewController, animated: true)
}
private func setupVision() {
textRecognitionRequest = VNRecognizeTextRequest { (request, error) in
guard let observations = request.results as? [VNRecognizedTextObservation] else { return }
var detectedText = ""
for observation in observations {
guard let topCandidate = observation.topCandidates(2).first else { return }
print("text \(topCandidate.string) has confidence \(topCandidate.confidence)")
detectedText += topCandidate.string
detectedText += "\n"
}
DispatchQueue.main.async {
self.TextScan.isHidden = false
self.infoScattaUnaFoto.isHidden = true
self.copyButtonShape.isHidden = false
self.buttonStartShape.setTitle("Ripeti", for: .normal)
self.TextScan.text += detectedText
self.TextScan.flashScrollIndicators()
}
}
textRecognitionRequest.recognitionLevel = .accurate
}
private func processImage(_ image: UIImage) {
imageView.image = image
recognizeTextInImage(image)
}
private func recognizeTextInImage(_ image: UIImage) {
guard let cgImage = image.cgImage else { return }
TextScan.text = ""
textRecognitionWorkQueue.async {
let requestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:])
do {
try requestHandler.perform([self.textRecognitionRequest])
} catch {
print(error)
}
}
}
func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
/* guard scan.pageCount >= 1 else {
controller.dismiss(animated: true)
return
}*/
for i in 0 ..< scan.pageCount {
let img = scan.imageOfPage(at: i)
processImage(img)
}
let originalImage = scan.imageOfPage(at: 0)
print(originalImage)
//let newImage = compressedImage(originalImage)
controller.dismiss(animated: true)
}
func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFailWithError error: Error) {
print(error)
controller.dismiss(animated: true)
}
func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController) {
controller.dismiss(animated: true)
}
func compressedImage(_ originalImage: UIImage) -> UIImage {
guard let imageData = originalImage.jpegData(compressionQuality: 1),
let reloadedImage = UIImage(data: imageData) else {
return originalImage
}
return reloadedImage
}
//MARK: By tapping on this button, I pass all the data.
#IBAction func CopyText(_ sender: Any) {
let vc = (storyboard?.instantiateViewController(identifier: "SpeakDetail") as? ViewController)!
vc.textscannerized = TextScan.text
self.navigationController?.pushViewController(vc, animated: true)
}
}
You can try something like this:
scannerViewController.view.tintColor = .red
I have been building my first firebase application and I have run into issues attempting to retrieve data and display it on the map as an annotation.
Currently my logic is as follows : Fetch data and put it into Note Class i then try to push the information into an array which is located in NoteBrain the information appears to be being placed inside the class when i debug with print statements the data shows up. The only issue is i am having trouble pushing the data to the view controller. For some reason my loadallcoordinates is not working, i even try to type print statements and it is not showing up.
My question
Is this the best way to structure my data? Is there any way I can make my current implementation work?
Thankyou
Note Class
import Foundation
import MapKit
class noteClass : NSObject, MKAnnotation{
var title : String?
var subtitle: String?
var coordinate: CLLocationCoordinate2D
var longitude : Double
var latitude : Double
init(dictionary: [String: Any]) {
self.title = dictionary["title"] as? String ?? ""
self.subtitle = dictionary["subtitle"] as? String ?? ""
self.longitude = dictionary["longitude"] as! Double
self.latitude = dictionary["latitude"] as! Double
self.coordinate = CLLocationCoordinate2DMake((dictionary["longitude"] as? Double)!, (dictionary["latitude"] as? Double)!)
}
}
noteBrain or model class
import Foundation
import UIKit
import MapKit
import CoreLocation
import Firebase
import FirebaseDatabase
class noteBrain: UIViewController, CLLocationManagerDelegate{
var noteArray = [noteClass]()
var newNote = false
var outsideToggle = true
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.0025, 0.0025)
var manager = CLLocationManager()
func getNotes() -> Array <noteClass>
{
return noteArray
}
func appendArray(newNote : noteClass){
noteArray.append(newNote)
}
func checkInside( s1 : Int ) -> noteClass{
return noteArray[0]
}
func checkToggle() -> Bool{
return outsideToggle
}
func fetchUser() {
FIRDatabase.database().reference().child("notes").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = noteClass(dictionary: dictionary)
self.appendArray(newNote: user)
}
}, withCancel: nil)
}
}
Viewcontroller
import UIKit
import MapKit
import CoreLocation
import Firebase
import FirebaseDatabase
struct PreferencesKeys{
static let savedItems = "savedItems"
}
class ViewController: UIViewController, CLLocationManagerDelegate{
let manager = CLLocationManager()
var coordinotes : [noteClass] = []
var latitude = Double()
var noteTime = noteBrain()
//Map
#IBOutlet weak var map: MKMapView!
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations[0]
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, noteTime.span)
map.setRegion(region, animated: true)
self.map.showsUserLocation = true
}
override func viewDidLoad()
{
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(handleLogout))
if FIRAuth.auth()?.currentUser?.uid == nil {
perform(#selector(handleLogout), with: nil, afterDelay: 0)
}
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
noteTime.fetchUser()
appendThisTest()
loadAllCoordinotes()
}
func handleLogout() {
do {
try FIRAuth.auth()?.signOut()
} catch let logoutError {
print(logoutError)
}
let loginController = LoginController()
present(loginController, animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func loadAllCoordinotes() {
for x in coordinotes
{
add(coordinote: x)
}
}
func add(coordinote: noteClass) {
map.addAnnotation(coordinote)
print(coordinote.coordinate)
print("test")
print(coordinote.title! as String)
}
func appendThisTest(){
coordinotes = noteTime.getNotes()
}
}
I'm a newbie in SWIFT and I do some examples application.
The only thing that I can not get worked is to get my Image displayed on Detail Scene (DetailViewController).
On my MasterViewController file I have this to get my multiData file:
...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showData" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = self.multiData[indexPath.section][indexPath.row]
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
// Here I get my multiData
func createData() {
var first: [Dictionary<String,String>] = []
var second: [Dictionary<String,String>] = []
dataSections = ["First Data", "Second Data"]
first.append(["name": "someName", "image": "somePngFile", "someData": "someText"])
second.append(["name": "someName", "image": "somePngFile", "someData": "someText"])
multiData = [first, second]
}
DetailViewController:
...
#IBOutlet weak var label: UILabel!
#IBOutlet weak var text: UITextView!
#IBOutlet weak var image: UIImageView!
...
func configureView() {
if let detail = self.detailItem {
if let labelTitle = label {
labelTitle.text = detail["name"] as! String!
}
if let textData = text {
textData.text = detail["someData"] as! String!
}
// This obvious doesn't work
if let imageFile = image {
imageFile.image = detail["image"] as! UIImage!
}
}
}
So, my question is how can I get the Image from detail["image"]?
I assume that the image contained in detail["image"] is in your application Bundle (i.e.: not an image from an HTTP URL). So, you should use the init(named:) constructor from UIImage to load your image. Something like that:
if let myImage = UIImage(named: detail["image"]) {
myImageView.image = myImage
}
Edit:
Here is, also, your code with a better management of optionals and casts in configureView:
func configureView() {
if let detail = self.detailItem {
if let labelTitle = detail["name"] as? String {
myLabel.text = labelTitle
}
if let textViewContent = detail["someData"] as? String {
myTextView.text = textViewContent
}
if let myImageName = detail["image"] as? String {
if let myImage = UIImage(named: myImageName) {
myImageView.image = myImage
}
}
}
}
I just update my code, but the alertWindow won't show up.
I add break point in Xcode, it shows that the viewDelegate is nil.
All delegates are nil.
This is my code:
class LoginViewController:UIViewController,AlertDelegate
{
override func viewDidLoad() {
super.viewDidLoad()
let BackGroundImage:UIImageView = UIImageView(frame: CGRectMake(0, 0, self.view.frame.width , self.view.frame.height))
let image: UIImage = UIImage(named: "backgroundLogin.jpg")!
BackGroundImage.image = image
self.view.addSubview(BackGroundImage)
//self.view.backgroundColor = UIColor(patternImage: UIImage(named: "backgroundLogin.jpg")!)
username.text = "User name"
password.text = "Password"
usernameWarning.text = ""
passwordWarning.text = ""
self.view.bringSubviewToFront(username)
self.view.bringSubviewToFront(password)
self.view.bringSubviewToFront(usernameText)
self.view.bringSubviewToFront(passwordText)
self.view.bringSubviewToFront(LoginButton)
self.view.bringSubviewToFront(RegisterButton)
self.view.bringSubviewToFront(usernameWarning)
self.view.bringSubviewToFront(passwordWarning)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
switch segue.identifier
{
case .Some("RegisterSegue"):
let registerViewController = segue.destinationViewController as! RegisterViewController
if let temp_register_username = usernameText!.text
{
registerViewController.register_name = temp_register_username
if let temp_register_pass = passwordText!.text
{
registerViewController.register_password = temp_register_pass
}
}
case .Some("loginSegue"):
let loginViewController = segue.destinationViewController as! FunctionsViewController
loginViewController.client = client
default:
super.prepareForSegue(segue, sender: sender)
}
}
override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
if identifier == "loginSegue"
{
if usernameText.text != ""
{
if passwordText.text != ""
{
let encrypt = encryptMsg(send: passwordText.text!)
let encrypt_pass = encrypt.encryptSendMsg()
let sendMsg = AppConfig.AddHead("login", body: usernameText.text!+"|"+encrypt_pass)
let (_,_) = client.connect(timeout: 1)
let (success,_) = client.send(str: sendMsg)
if success
{
let data = client.read(1024*10)
if let d = data
{
if let str = String(bytes: d, encoding: NSUTF8StringEncoding)
{
if str[0...2] == AppConfig.TransmissionAgreementConfiguration["successLogin"]
{
AppConfig.StoreUserID(str)
let defaults = NSUserDefaults()
defaults.setObject(usernameText.text!, forKey: "userName")
let acceptThread = AcceptThread()
acceptThread.start()
return true
}
else if str[0...2] == AppConfig.TransmissionAgreementConfiguration["errLoginUsernameNotExist"]
{
usernameWarning.text = "User name doesn't exist"
usernameWarning.reloadInputViews()
passwordWarning.text = ""
passwordWarning.reloadInputViews()
return false
}
else if str[0...2] == AppConfig.TransmissionAgreementConfiguration["errLoginUsernameAlreadyOnline"]
{
usernameWarning.text = "User account already be online"
usernameWarning.reloadInputViews()
passwordWarning.text = ""
passwordWarning.reloadInputViews()
return false
}
else if str[0...2] == AppConfig.TransmissionAgreementConfiguration["errLoginPassword"]
{
usernameWarning.text = ""
usernameWarning.reloadInputViews()
passwordWarning.text = "Password Incorrect"
passwordWarning.reloadInputViews()
return false
}
}
}
}
return false
}
else
{
usernameWarning.text = ""
usernameWarning.reloadInputViews()
passwordWarning.text = "password cannot be empty"
passwordWarning.reloadInputViews()
return false
}
}
else
{
usernameWarning.text = "username cannot be empty"
usernameWarning.reloadInputViews()
return false
}
}
else
{
return true
}
}
func presentWindow(title:String,msg:String)
{
let alertController = UIAlertController(title: "\(title):", message: "\(msg)", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addTextFieldWithConfigurationHandler{
(textField: UITextField!) -> Void in
textField.placeholder = "Message"
}
let cancelAction = UIAlertAction(title: "Ignore", style: UIAlertActionStyle.Cancel, handler: nil)
let okAction = UIAlertAction(title: "Reply", style: UIAlertActionStyle.Default,
handler: {
action in
let reply_msg = alertController.textFields!.first! as UITextField
print("I replies \(reply_msg)")
})
alertController.addAction(cancelAction)
alertController.addAction(okAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
#IBAction func logoutUnwindSegue(segue: UIStoryboardSegue) {
// Intentionally left blank
}
var client:TCPClient = TCPClient(addr:"localhost",port:8889)
var AppConfig=TransmissionAgreement(first:"test")
#IBOutlet weak var usernameWarning: UILabel!
#IBOutlet weak var passwordWarning: UILabel!
#IBOutlet weak var username: UILabel!
#IBOutlet weak var password: UILabel!
#IBOutlet weak var usernameText: UITextField!
#IBOutlet weak var passwordText: UITextField!
#IBOutlet weak var LoginButton: UIButton!
#IBOutlet weak var RegisterButton: UIButton!
}
class AcceptThread: NSThread {
override func main() {
let server:TCPServer = TCPServer(addr:"127.0.0.1",port: 7000)
let (success,_) = server.listen()
if success
{
while !cancelled
{
if let my_client = server.accept()
{
let clientReadThread = ClientReadThread(client: my_client)
clientReadThread.start()
clientThreads.append(clientReadThread)
}
}
for clientThread in clientThreads {
clientThread.cancel()
}
}
}
var clientThreads = Array<ClientReadThread>()
var AppConfig=TransmissionAgreement(first:"test")
}
#objc protocol AlertDelegate: class {
func presentWindow(title:String,msg:String)
}
#objc protocol ClientReadThreadDelegate: class {
func clientReadThread(clientReadThread: ClientReadThread, didReceiveMessage message: String)
}
class ClientReadThread:NSThread{
init(client: TCPClient) {
self.client = client
super.init()
}
override func main() {
while !cancelled, let readValue = client.read(1024*10) {
if let message = String(bytes: readValue, encoding: NSUTF8StringEncoding) {
let head = message[0...2]
// print("head is \(head)")
if head! == AppConfig.TransmissionAgreementConfiguration["add"]
{
let defaults = NSUserDefaults()
let myname = defaults.stringForKey("userName")
//store data
let context = CoreDataService.sharedCoreDataService.mainQueueContext
let friend = NSEntityDescription.insertNewObjectForNamedEntity(Friends.self, inManagedObjectContext: context)
friend.name = message.substringFromIndex(3)
try! context.save()
let sendMsg = AppConfig.AddClientHead("agreeAdd", body:myname)
let (_,_) = client.send(str:sendMsg)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.delegate?.clientReadThread(self, didReceiveMessage: message)
})
}
else if head! == AppConfig.TransmissionAgreementConfiguration["chat"]
{
let search = message.substringFromIndex(3)
let resultController = try? catFriend.sharedCatFriendsService.catBlack(search)
try! resultController!.performFetch()
let flag = resultController?.sections?.count
if flag <= 1//friend
{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let client_info = message.split("|")
let client_name = client_info[1]
//self.alertDelegate?.presentWindow(client_name, msg: client_info[2])
self.viewDelegate?.presentWindow(client_name, msg: client_info[2])
})
}
else//black, not show the meg
{
//do nothing
}
}
}
}
}
var AppConfig=TransmissionAgreement(first:"test")
let client: TCPClient
var viewDelegate:LoginViewController?
var delegate: ClientReadThreadDelegate?
var alertDelegate: AlertDelegate?
private var resultController: NSFetchedResultsController?
}
presentViewContoller is a method on UIViewController so you'll need an instance of a view controller to be able to present your alert view.
The way this would normally be done is to have the view controller you have start the ClientReadThread implement the AlertDelegate protocol. There's no reason for ClientReadThread to implement AlertDelegate itself. Would it ever be it's own delegate?
Also you delegate's should be marked weak or else you'll end up with a retain cycle.
class MyViewController : UIViewController, AlertDelegate {
private var clientReadThread: ClientReadThread?
override viewDidLoad() {
super.viewDidLoad();
clientReadThread = ClientReadThread(someTcpClient)
clientReadThread.viewDelegate = self
}
func presentWindow(title:String,msg:String) {
// Your code goes here.
}
}
Your other option would be to pass an instance of a UIViewController into your ClientReadThread and use that to present the alert view. Although that's not the way I would go. the ClientReadThread shouldn't need to know how it's alerts are handled, that should be delegated to another class.