How can I create multiple button by SwiftyJson and Almofire in swift 4? - ios

These are my effort:
var cats = [[String:AnyObject]]()
func getAllCats(){
_ = EZLoadingActivity.show("Loading...", disableUI: true)
let param: [String: AnyObject] = ["apiKey": "???" as AnyObject]
_ = Alamofire.request(APIRouters.GetAllCats(param)).responseJSON { (responseData) -> Void in
if((responseData.result.value) != nil) {
let getJson = JSON(responseData.result.value!)
if (getJson["status"].stringValue == "200"){
if let resData = getJson["data"].arrayObject {
self.cats = resData as! [[String:AnyObject]]
}
} else if (getJson["status"].stringValue == "404") {
} else {
}
}
_ = EZLoadingActivity.hide()
}
}
var buttonY: CGFloat = 20 // our Starting Offset, could be 0
for villain in cats {
print("ok",villain["pt_name_Fa"])
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart
villainButton.layer.cornerRadius = 10 // get some fancy pantsy rounding
villainButton.backgroundColor = UIColor.darkGray
villainButton.setTitle("Button for Villain: \(villain["pt_name_Fa"] ?? "" as AnyObject))", for: UIControlState.normal) // We are going to use the item name as the Button Title here.
villainButton.titleLabel?.text = "\(villain)"
villainButton.addTarget(self,action:#selector(villainButtonPressed),
for:.touchUpInside)
// villainButton.addTarget(self, action: Selector(("villainButtonPressed:")), for: UIControlEvents.touchUpInside)
self.view.addSubview(villainButton) // myView in this case is the view you want these buttons added
}
It did not work, but if i use an array such below it works!
var arrayOfVillains = ["santa", "bugs", "superman", "batman"]
Thanks for your helping in advance

I found the solution. Adding button should be run after Json load completely:
var cats = [[String:AnyObject]]()
_ = EZLoadingActivity.show("Loading...", disableUI: true)
let param: [String: AnyObject] = ["apiKey": "???" as AnyObject]
_ = Alamofire.request(APIRouters.GetAllCats(param)).responseJSON { (responseData) -> Void in
if((responseData.result.value) != nil) {
print(responseData.request!) // original URL request
print(responseData.response!) // URL response
let getJson = JSON(responseData.result.value!)
if (getJson["status"].stringValue == "200"){
if let resData = getJson["data"].arrayObject {
self.cats = resData as! [[String:AnyObject]]
}
if self.cats.count > 0 {
self.addButton()
}
} else if (getJson["status"].stringValue == "404") {
_ = SweetAlert().showAlert("Ok", subTitle: "Api Error!", style: AlertStyle.warning)
} else {
_ = SweetAlert().showAlert("Error", subTitle: getJson["message"].stringValue, style: AlertStyle.warning)
}
}
_ = EZLoadingActivity.hide()
}
func addButton(){
var buttonY: CGFloat = 20 // our Starting Offset, could be 0
for villain in self.cats {
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart
villainButton.layer.cornerRadius = 10 // get some fancy pantsy rounding
villainButton.backgroundColor = UIColor.darkGray
villainButton.setTitle("Button for Villain: \(villain["pt_name_Fa"] ?? "" as AnyObject))", for: UIControlState.normal) // We are going to use the item name as the Button Title here.
villainButton.titleLabel?.text = "\(villain)"
villainButton.addTarget(self,action:#selector(villainButtonPressed),
for:.touchUpInside)
self.view.addSubview(villainButton) // myView in this case is the view you want these buttons added
}
}
Please attention to this part of code :
if self.cats.count > 0 {
self.addButton()
}
Thanks for your attendance.

Related

Terminating app due to uncaught exception 'NSRangeException'. libc++abi.dylib: terminating with uncaught exception of type NSException

I get this crash error:
MXNet2CoreML[11383:1168377]
*** Terminating app due to uncaught exception 'NSRangeException', reason:
*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'
*** First throw call stack: (0x18333f164 0x182588528 0x18329a020 0x1007894bc 0x1011ef94c 0x1011b0420 0x1021412cc 0x10214128c
0x102145ea0 0x1832e7344 0x1832e4f20 0x183204c58 0x1850b0f84
0x18c95d5c4 0x1007d8894 0x182d2456c)
libc++abi.dylib: terminating with uncaught exception of type
NSException
Here is the Complete Code
//Owais: - Map setup
func resetRegion(){
let region = MKCoordinateRegionMakeWithDistance(annotation.coordinate, 5000, 5000)
mapKit.setRegion(region, animated: true)
}
var myLatitude = ""
var myLongitude = ""
// Array of annotations
let annotation = MKPointAnnotation()
var places = PredictionLocationList().place
var locationsArray = [String]()
var ie: Int = 0
#IBOutlet var mapKit: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let defaults = UserDefaults.standard
let data = defaults.data(forKey: "selectedimage")
let uiimage2 = UIImage(data: data!)
defaults.synchronize()
let image = uiimage2
// imageView.image = image
predictUsingVision(image: image!)
let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture))
swipeDown.direction = UISwipeGestureRecognizerDirection.down
self.view.addGestureRecognizer(swipeDown)
// Do any additional setup after loading the view.
}
#objc func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.right:
print("Swiped right")
case UISwipeGestureRecognizerDirection.down:
print("Swiped down")
self.dismiss(animated: true, completion: nil)
case UISwipeGestureRecognizerDirection.left:
print("Swiped left")
case UISwipeGestureRecognizerDirection.up:
print("Swiped up")
default:
break
}
}
}
func predictUsingVision(image: UIImage) {
guard let visionModel = try? VNCoreMLModel(for: model.model) else {
fatalError("Something went wrong")
}
let request = VNCoreMLRequest(model: visionModel) { request, error in
if let observations = request.results as? [VNClassificationObservation] {
let top3 = observations.prefix(through: 2)
.map { ($0.identifier, Double($0.confidence)) }
self.show(results: top3)
}
}
request.imageCropAndScaleOption = .centerCrop
let handler = VNImageRequestHandler(cgImage: image.cgImage!)
try? handler.perform([request])
}
typealias Prediction = (String, Double)
func show(results: [Prediction]) {
var s: [String] = []
for (i, pred) in results.enumerated() {
let latLongArr = pred.0.components(separatedBy: "\t")
print("lat long \(latLongArr)")
myLatitude = latLongArr[1]
myLongitude = latLongArr[2]
ie = i
s.append(String(format: "%d: %# %# (%.2f%%)", i + 1, myLatitude, myLongitude, pred.1 * 100))
LocationByCoordinates(latitude: myLatitude, longitude: myLongitude)
// let ew1 = (String(format: "%.2f%", pred.1 * 100))
// print(ew1)
// let double1 = Double(ew1)
// self.doubles.append(double1!)
// print("eueue \(self.doubles)")
// let maxDouble = max(max(double1, double2), double3)
print("first latidue \(myLatitude),,,, \(myLongitude)")
places[i].title = String(i+1)
places[i].coordinate = CLLocationCoordinate2D(latitude: CLLocationDegrees(myLatitude)!, longitude: CLLocationDegrees(myLongitude)!)
}
// predictionLabel.text = s.joined(separator: "\n")
// Map reset
resetRegion()
mapKit.centerCoordinate = places[0].coordinate
// Show annotations for the predictions on the map
mapKit.addAnnotations(places)
// Zoom map to fit all annotations
zoomMapFitAnnotations()
}
func zoomMapFitAnnotations() {
var zoomRect = MKMapRectNull
for annotation in mapKit.annotations {
let annotationPoint = MKMapPointForCoordinate(annotation.coordinate)
let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0)
if (MKMapRectIsNull(zoomRect)) {
zoomRect = pointRect
} else {
zoomRect = MKMapRectUnion(zoomRect, pointRect)
}
}
self.mapKit.setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(50, 50, 50, 50), animated: true)
}
func LocationByCoordinates (latitude: String,longitude:String) {
let mapsKey = UserDefaults.standard.string(forKey: "maps_key") ?? ""
Alamofire.request("https://maps.googleapis.com/maps/api/geocode/json?latlng=\(latitude),\(longitude)&key=\(mapsKey)").responseJSON { response in
if let json = response.result.value {
let request = json as? NSDictionary
if let id = request!["results"] {
// print(id)
let ide = id as? NSArray
let formatted_address = ide![0]
let fors = formatted_address as! NSDictionary
//print(fors.value(forKey: "formatted_address"))
let forss = fors.value(forKey: "formatted_address")
self.locationsArray.append(forss as? String ?? "")
if self.ie == 0 {
self.places[0].identifier = (forss as? String)!
} else if self.ie == 1 {
self.places[1].identifier = (forss as? String)!
} else if self.ie == 2 {
self.places[2].identifier = (forss as? String)!
}
}
}
}
}
}
extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
The problem is in this line let formatted_address = ide![0]
If an array is empty, you can't get it's first element with [0] because there is no element at all!
All you have to do is check if the array is not empty before unwrapping it:
if ide!.count > 0 {
//Your code
}
To avoid force-unwrapping ide, you may want to use optional binding like so:
if let id = request!["results"], let ide = id as? NSArray {
let formatted_address = ide[0]
let fors = formatted_address as! NSDictionary
//rest of your code
}

Swift 4 - How to update progressView in loop

I have created this progressView:
progress = UIProgressView(progressViewStyle: .default)
progress.center = view.center
progress.setProgress(0.5, animated: true)
view.addSubview(progress)
In my viewDidLoad method, I call getLandGradingImages and inside that I do a loop, inside that I call getLandGradingImage for each result in getLandGradingImages, what would be the best way to update the progressView I created during this entire process:
getLandGradingImages(jobNo: jobNo) { result in
//Define axis variables
var x = 25
var y = 80
//Define image counter variable
var counterImages = 0
var actualImageCounter = 0
//For each Lot Image
for item in result
{
self.getLandGradingImage(image: item["imageBytes"] as! String) { data in
//Create Image from Data
let image = UIImage(data: data)
//Add Image to Image View
let imageView = UIImageView(image: image!)
//Set Image View Frame
imageView.frame = CGRect(x: x, y: y, width: 100, height: 100)
//Define UITapGestureRecognizer
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.imageTapped(tapGestureRecognizer:)))
//Enable user interaction
imageView.isUserInteractionEnabled = true
//Assign tap gesture to image view
imageView.addGestureRecognizer(tapGestureRecognizer)
//Add Image to view
self.view.addSubview(imageView)
//Increase x axis
x = x + 115
//Increase image counter
counterImages = counterImages + 1
actualImageCounter = actualImageCounter + 1
//If image counter is equal to 3, create new line.
if(counterImages == 3)
{
//Increase y axis
y = y + 115
//Reset x axis
x = 25
//Reset image counter
counterImages = 0
}
if(actualImageCounter == result.count)
{
//self.stopIndicator()
}
}
}
}
Here are those two methods I am calling in this process:
func getLandGradingImages(jobNo:String, completionHandler:#escaping (_ result:Array<Dictionary<String, Any>>) -> Void) {
//Define array for returning data
var returnedResults = Array<Dictionary<String, Any>>()
//Call API
WebService().GetLandGradingImages(jobNo: jobNo)
{
(result: Array<Dictionary<String, Any>>) in
DispatchQueue.main.async {
//Return our results
returnedResults = result
completionHandler(returnedResults)
}
}
}
func getLandGradingImage(image:String, completionHandler:#escaping (_ result:Data) -> Void) {
//Define array for returning data
var returnedResults = Data()
//Call API
WebService().GetLandGradingImage(image: image)
{
(result: Data) in
DispatchQueue.main.async {
//Return our results
returnedResults = result
completionHandler(returnedResults)
}
}
}
For these calls, I am using Alamofire:
func GetLandGradingImage(image: String, completion: #escaping (_ result: Data) -> Void)
{
let imagePath : String = image
let url = URL(string: webserviceImages + imagePath)!
Alamofire.request(url).authenticate(user: self.appDelegate.username!, password: self.appDelegate.password!).responseData { response in
let noData = Data()
if(response.error == nil)
{
if let data = response.data {
completion(data)
}
}
else
{
completion(noData)
}
}
}
I have tried this:
var counter:Int = 0 {
didSet {
let fractionalProgress = Float(counter) / 100.0
let animated = counter != 0
progress.setProgress(fractionalProgress, animated: animated)
}
}
and inside the for loop:
DispatchQueue.global(qos: .background).async {
sleep(1)
DispatchQueue.main.async {
self.counter = self.counter + 1
}
}
Still nothing, my the progress view appears but does not get updated.

Getting duplicate tableview cells after first time

In my app, there is an add button, when clicked will add a new tableviewcell. However the problem is I am getting duplicate cells after the first time. Essentially, I am getting 2 duplicates when I click second time, 3 on third and so on.... Please see the images for the screenshot:
The above image is the first screen. Clicking '+' will add a new cell, which looks like the below images:
Now after saving,
Now if I go out of this view and come back, click add again and create a new cell, it gives me duplicates as mentioned in the above paragraphs (that is, 2 for second time, 3 for third time and so on...).
Here is the screenshot:
Here is the code I am using:
#IBAction func addBasket(_ sender: UIButton) {
let prefs = UserDefaults.standard
let status = prefs.string(forKey: "status")
if(status != nil){
if( status == "pending"){
if(BasketItemList.count < 5 ) {
self.addpost()
} else {
let alert = SCLAlertView()
alert.showWarning("Basket", subTitle: "Upgrade to add more")
}
} else {
if(BasketItemList.count < 50 ) {
self.addpost()
} else {
let alert = SCLAlertView()
alert.showWarning("Basket", subTitle: "Upgrade to add more")
}
}
}
}
func addpost() {
let appearance = SCLAlertView.SCLAppearance(
showCloseButton: false
)
let alert = SCLAlertView(appearance : appearance)
let txt = alert.addTextField("Enter name")
alert.addButton("Save") {
if txt.text?.characters.count != 0 {
let basketname : String = txt.text!
let userID = FIRAuth.auth()?.currentUser?.uid
let postitem : [String :AnyObject] = ["userid" : userID! as AnyObject , "basketname" : basketname as AnyObject ]
let dbref = FIRDatabase.database().reference()
dbref.child("BasketList").childByAutoId().setValue(postitem)
self.Basketdata2()
let appearance = SCLAlertView.SCLAppearance(
kDefaultShadowOpacity: 0,
showCloseButton: false
)
let alertView = SCLAlertView(appearance: appearance)
alertView.showTitle(
"Saved", // Title of view
subTitle: "", // String of view
duration: 2.0, // Duration to show before closing automatically, default: 0.0
completeText: "Done", // Optional button value, default: ""
style: .success, // Styles - see below.
colorStyle: 0xA429FF,
colorTextButton: 0xFFFFFF
)
} else {
let alert = SCLAlertView()
alert.showError("Oops!", subTitle: "Basket name should not be empty")
self.tableviewbasket.reloadData()
}
}
alert.addButton("Cancel"){
}
alert.showEdit("Add basket", subTitle: "Please enter your basket name")
}
func Basketdata2() {
HUD.show(.labeledProgress(title: "Loading...", subtitle: ""))
let databaseref = FIRDatabase.database().reference()
var userID = FIRAuth.auth()?.currentUser?.uid
if userID == nil {
userID = userfbid
}
databaseref.child("BasketList").queryOrdered(byChild: "userid").queryEqual(toValue: userID!).observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
self.tableviewbasket.backgroundView = nil;
HUD.hide()
} else {
HUD.hide()
self.tableviewbasket.setContentOffset(CGPoint(x : 0, y: -98), animated: true)
if (self.BasketItemList.count == 0) {
// tableView is empty. You can set a backgroundView for it.
let label = UILabel(frame: CGRect(x: 5, y: 0, width: self.tableviewbasket.bounds.size.width, height:self.tableviewbasket.bounds.size.height))
label.text = "The best preparation for tomorrow \n is doing your best today.\n Please create your first basket."
label.textColor = UIColor.black;
label.textAlignment = .center
label.numberOfLines = 4
label.sizeToFit()
label.font = UIFont(name: "AvenirNext-Regular", size: 16.0)
self.tableviewbasket.backgroundView = label;
self.tableviewbasket.separatorStyle = .none;
}
}
})
}
func Basketdata() {
HUD.show(.labeledProgress(title: "Please wait...", subtitle: ""))
self.BasketItemList.removeAll()
self.Basketid.removeAll()
let databaseref = FIRDatabase.database().reference()
let userID = FIRAuth.auth()?.currentUser?.uid
databaseref.child("BasketList").queryOrdered(byChild: "userid").queryEqual(toValue: userID!).observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
databaseref.child("BasketList").queryOrdered(byChild: "userid").queryEqual(toValue: userID!).observe(.childAdded, with: {
(snapshot) in
if let dictionary = snapshot.value as? [String : AnyObject] {
let basketitem = BasketList(text : "")
basketitem.setValuesForKeys(dictionary)
self.BasketItemList.append(basketitem)
self.Basketid.append(snapshot.key)
DispatchQueue.main.async {
if !self.BasketItemList.isEmpty {
HUD.hide()
self.tableviewbasket.reloadData()
}
}
} else {
self.tableviewbasket.reloadData()
HUD.hide()
}
})
} else {
if (self.BasketItemList.count == 0) {
// tableView is empty. You can set a backgroundView for it.
let label = UILabel(frame: CGRect(x: 5, y: 0, width: self.tableviewbasket.bounds.size.width, height:self.tableviewbasket.bounds.size.height))
label.text = "The best preparation for tomorrow \nis doing your best today"
label.textColor = UIColor.black;
label.textAlignment = .center
label.numberOfLines = 2
label.sizeToFit()
label.font = UIFont(name: "AvenirNext-Regular", size: 16.0)
self.tableviewbasket.backgroundView = label;
self.tableviewbasket.separatorStyle = .none;
}
HUD.hide()
}
})
}
Can someone help me understand what is wrong with my code? Thanks!
Edit: I have referred this thread without any luck: Getting duplicate cells with UITableViewController cellForRowAtIndexPath
Edit 2: Also, when I come out of that view and go to the same view, the duplicate values are vansihed.
Edit 3: Tried the answer without any success.
Follow below steps:
When you'r getting data from firebase db, first remove your array all objects that you'r using in the cellForRow method. In your case i think it should be array of Bucket (not sure).
Assign data to your object
reload tableview.
Reason of replication of data.
let your bucket have 2 values and it is stored inDB. When you fetch data from DB it gives you all the values i.e. 1,2,3. Now you adds these now your array will be 1,2,1,2,3.
Thats what happening in your case.

How to solve Command failed due to signal: Segmentation fault: 11

I was searching for this issue here, and found out that this issue is not common one.
Everyone had different approaches to solve it. I'm using Firebase and Gifu framework. Actually for the last one - i copied all the files to my project, but that didn't helped either.
Here is my source code:
import FirebaseDatabase
import FirebaseAuth
import Firebase
import UIKit
import Gifu
class ViewController: UIViewController {
#IBOutlet weak var userImage: AnimatableImageView!
var displayedUserId = ""
var AcceptedOrRejected = ""
override func viewDidLoad() {
super.viewDidLoad()
let urlArray = ["http://i.imgur.com/VAWlQ0S.gif", "http://i.imgur.com/JDzGqvE.gif", "http://67.media.tumblr.com/4cd2a04b60bb867bb4746d682aa60020/tumblr_mjs2dvWX6x1rvn6njo1_400.gif", "https://media.giphy.com/media/TlK63ELk5OPDzpb6Tao/giphy.gif", "http://i3.photobucket.com/albums/y90/spicestas/GeriHalliwell-Calling-new1.gif", "http://media.tumblr.com/tumblr_lnb9aozmM71qbxrlp.gif"]
var counter = 1
for url in urlArray {
let nsUrl = NSURL(string: url)
let girls = ProfileClass()
girls.profilePhotoUrl = url
girls.profileGender = "female"
girls.profileName = "girlsname\(counter)"
girls.profileSurname = "girlsurname\(counter)"
girls.interest = "men"
girls.uid = "\(randomStringWithLength(45))"
counter++
girls.SaveUser()
}
//----setting variables
let label = UILabel(frame: CGRectMake(self.view.bounds.width / 2 - 100, self.view.bounds.height / 2 - 50, 300, 100))
//label.text = "Drag me!"
//label.textAlignment = NSTextAlignment.Center
self.view.addSubview(label)
let gesture = UIPanGestureRecognizer(target: self, action: Selector("wasDragged:"))
userImage.addGestureRecognizer(gesture)
userImage.userInteractionEnabled = true
//----getting access to database
let thisUserRef = URL_BASE.childByAppendingPath("profile")
thisUserRef.queryOrderedByChild("Interest").queryEqualToValue("men").observeEventType(.Value, withBlock: {
snapshot in
for child in snapshot.children{
self.displayedUserId = (child.value["uid"] as? String)!
let imageURL = child.value["photo"] as? String
let imURL = NSURL(string: imageURL!)
//print(imageURL)
if self.AcceptedOrRejected != "" {
let AcceptedArray = child.value[AcceptedOrRejected] as? Array
AcceptedArray.append(displayedUserId)
}
if let picData = NSData(contentsOfURL: imURL!) {
self.userImage.animateWithImageData(picData)
//self.userImage.image = UIImage(data: picData)
}
}
})
}
//-----Dragging function-----------
func wasDragged(gesture: UIPanGestureRecognizer) {
//set traslations
let translation = gesture.translationInView(self.view)
let label = gesture.view
//set center position
label!.center = CGPoint(x: self.view.bounds.width / 2 + translation.x, y: self.view.bounds.height / 2 - translation.y )
let xfromCenter = (label?.center.x)! - self.view.bounds.width / 2
let scale = min(100 / abs(xfromCenter),1)
var rotation = CGAffineTransformMakeRotation(xfromCenter / 200)
var strech = CGAffineTransformScale(rotation, scale, scale)
label?.transform = strech
if gesture.state == UIGestureRecognizerState.Ended {
if label?.center.x < 100 {
self.AcceptedOrRejected = "Accepted"
} else if label?.center.x > self.view.bounds.width / 100 {
self.AcceptedOrRejected = "Rejected"
}
rotation = CGAffineTransformMakeRotation(0)
strech = CGAffineTransformScale(rotation, 1, 1)
label?.transform = strech
label?.center = CGPoint(x: self.view.bounds.width / 2 , y: self.view.bounds.height / 2 )
}
}
//---Function for generating randomn userid
func randomStringWithLength (len : Int) -> NSString {
let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let randomString : NSMutableString = NSMutableString(capacity: len)
for (var i=0; i < len; i += 1){
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
}
return randomString
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "LogOutSegue" {
try! FIRAuth.auth()!.signOut()
}
}
}
And I get this error
1. While emitting SIL for 'viewDidLoad' at /Users/zkid18/Desktop/wrk/Bloom/Bloom/ViewController.swift:23:14
2. While silgen closureexpr SIL function #_TFFC5Bloom14ViewController11viewDidLoadFT_T_U_FCSo15FIRDataSnapshotT_ for expression at [/Users/zkid18/Desktop/wrk/Bloom/Bloom/ViewController.swift:68:114 - line:107:9] RangeText="{
snapshot in
for child in snapshot.children{
self.displayedUserId = (child.value["uid"] as? String)!
let imageURL = child.value["photo"] as? String
let imURL = NSURL(string: imageURL!)
//print(imageURL)
if self.AcceptedOrRejected != "" {
let AcceptedArray = child.value[AcceptedOrRejected] as? Array
AcceptedArray.append(displayedUserId)
}
if let picData = NSData(contentsOfURL: imURL!) {
self.userImage.animateWithImageData(picData)
//self.userImage.image = UIImage(data: picData)
}
}
}"
I don't really know what to do with that
I just attempted a conversion to Swift 3 to get a jump on fixing issues in my code. I have similar error but I just integrated Firebase into all of my project. I found that by removing the pod and framework from the app and commenting out all firebase code fixed this compile issue.

How to release memory for UIImageView (Swift)

I got a problem with UIImage. I've manually added UIImageView objects to a scroll view. The problem is : when I have more than 50 images, memory will increase to around 200MB, and the app will be crash on iphone 4 or 4s. I want to release memory for images that is not in visible part when I receive Memory Warning to prevent crashing but I don't know how to release them with Swift. Help me please.
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadImage(index:Int){
if self.imgPaths.count == 0 {
println("Has not data")
actInd.stopAnimating()
return
}
var imgURL: NSURL = NSURL(string: self.imgPaths[index].stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet()))!
let width:CGFloat = self.view.bounds.width
let height:CGFloat = self.view.bounds.height
var view:UIView = UIView(frame: CGRectMake(0, 0, width, height));
if let imgObj = self.dicData[index] {
}
else
{
println("imgURL \(imgURL)")
let request: NSURLRequest = NSURLRequest(URL: imgURL)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void in
if error == nil {
let imgItem = UIImage(data: data)!
var te :Float = self.imgPaths.count > 0 ? Float(index + 1) / Float(self.imgPaths.count) : 1
self.progressView.setProgress(te, animated: true)
if let imgObj = self.dicData[index] {
if index < self.imgPaths.count - 1
{
var nextIndex:Int = index + 1
self.loadImage(nextIndex)
}
if(index == self.imgPaths.count - 1)
{
if self.currentImageIndex > 0
{
self.isAddedFirstImg = true
}
if !self.isAddedFirstImg
{
self.scrollViews[0].zoomScale = self.zoomScales[0]
self.view.insertSubview(self.scrollViews[0], belowSubview: self.tabBar.viewWithTag(77)!)
self.isAddedFirstImg = true
}
self.actInd.stopAnimating()
println("loaded image")
}
}
else
{
self.dicData[index] = UIImageView(image: imgItem)
self.dicData[index]?.frame = CGRect(origin: CGPointMake(0.0, 0.0), size:imgItem.size)
// 2
self.scrollViews[index].addSubview(self.dicData[index]!)
self.scrollViews[index].contentSize = imgItem.size
// 3
var doubleTapRecognizer = UITapGestureRecognizer(target: self, action: "scrollViewDoubleTapped:")
doubleTapRecognizer.numberOfTapsRequired = 2
doubleTapRecognizer.numberOfTouchesRequired = 1
self.scrollViews[index].addGestureRecognizer(doubleTapRecognizer)
var singleTapRecognizer = UITapGestureRecognizer(target: self, action: "scrollViewSingleTapped:")
singleTapRecognizer.numberOfTapsRequired = 1
singleTapRecognizer.numberOfTouchesRequired = 1
self.scrollViews[index].addGestureRecognizer(singleTapRecognizer)
var swipeRight = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
self.scrollViews[index].addGestureRecognizer(swipeRight)
var swipeLeft = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeLeft.direction = UISwipeGestureRecognizerDirection.Left
self.scrollViews[index].addGestureRecognizer(swipeLeft)
// 4
var scrollViewFrame = self.scrollViews[index].frame
var scaleWidth = scrollViewFrame.size.width / self.scrollViews[index].contentSize.width
var scaleHeight = scrollViewFrame.size.height / self.scrollViews[index].contentSize.height
var minScale = min(scaleWidth, scaleHeight)
self.zoomScales[index] = minScale
self.scrollViews[index].minimumZoomScale = minScale
// 5
self.scrollViews[index].maximumZoomScale = 1.0
self.scrollViews[index].delegate = self
// 6
self.centerScrollViewContents(index)
dispatch_async(dispatch_get_main_queue(), {
println("downloaded image index: \(index) CH.\(self.chapterID)")
if(index == 0)
{
self.scrollViews[0].zoomScale = self.zoomScales[0]
self.view.insertSubview(self.scrollViews[0], belowSubview: self.tabBar.viewWithTag(77)!)
self.actInd.stopAnimating()
}
if index < self.imgPaths.count - 1 && !self.stopDownload
{
var nextIndex:Int = index + 1
self.loadImage(nextIndex)
}
if(index == self.imgPaths.count - 1)
{
if self.currentImageIndex > 0
{
self.isAddedFirstImg = true
}
if !self.isAddedFirstImg
{
self.scrollViews[0].zoomScale = self.zoomScales[0]
self.view.insertSubview(self.scrollViews[0], belowSubview: self.tabBar.viewWithTag(77)!)
self.isAddedFirstImg = true
}
self.actInd.stopAnimating()
println("loaded image")
}
})
}
}
else {
println("Error: \(error.localizedDescription)")
}
})
}
}
Swift uses ARC (Automatic Reference Counting) to manage memory. To free something from memory, you must remove all references to that object. ARC maintains a count of the number of places that hold a reference to the object, and when that count reaches 0, the memory is freed.
In your case, your imageViews are stored in self.dicData[index] and they are added as subviews of self.scrollViews[index]. You will need to remove the imageView from its superview and from self.dicData. Once you do that, the memory will be freed.
If you have the index of the imageView you want to free:
self.dicData[index]?.removeFromSuperview()
self.dicData[index] = nil
in swift there is really good tool called "lazy"
you might wanted to study about lazy var its very handy when it comes down to the images and tableview (for your instance collectionview)
you will see a huge difference when its used from custom cell.
create a imageview e.g. lazy var imageViewer:UIImageView
my app was at about 150mb 200mb memory now its at 40~60mb try it!

Resources