I'm using Xcode 8.0, Swift 3.
I'm making today extension showing text and image, but frequently cause this message and today extension does not work.
rarely work.
Program ended with exit code: 0
I saved data in realm, and today extension using the data(string, image)
is it cause a memory limit? so, how can i derease memory about today extension using??
My extension code:
class Information: Object {
dynamic var Name = ""
dynamic var Image : NSData?
override class func primaryKey() -> String {
return "Name"
}
}
class TodayViewController: UIViewController, NCWidgetProviding {
var realm : Realm?
var results : Results<Information>?
var index = 0
#IBOutlet var NameLabel: UILabel!
#IBOutlet var ImageView: UIImageView!
#IBAction func leftAction(_ sender: UIButton) {
guard index == 0 else {
index -= 1
loadData(index: index)
return
}
}
#IBAction func rightAction(_ sender: UIButton) {
guard index == (results?.count)! - 1 else {
index += 1
loadData(index: index)
return
}
}
override func viewDidLoad() {
super.viewDidLoad()
setRealmFileURL()
if #available(iOSApplicationExtension 10.0, *) {
extensionContext?.widgetLargestAvailableDisplayMode = .expanded
}else{
preferredContentSize = CGSize(width: 0, height: 250)
}
// Do any additional setup after loading the view from its nib.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
realm = try! Realm()
results = try! Realm().objects(Information.self)
loadData(index: index)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
private func widgetPerformUpdate(completionHandler: ((NCUpdateResult) -> Void)) {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResult.Failed
// If there's no update required, use NCUpdateResult.NoData
// If there's an update, use NCUpdateResult.NewData
loadData(index: index)
completionHandler(NCUpdateResult.newData)
}
func loadData(index: Int){
guard results?.count == 0 else {
let objects = results?[index]
NameLabel.text = objects?.Name
ImageView.image = UIImage(data: (objects?.Image)! as Data, scale: 0.1)
return
}
}
#available(iOSApplicationExtension 10.0, *)
func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) {
preferredContentSize = CGSize(width: 0, height: 250)
}
func setRealmFileURL(){
var config = Realm.Configuration(encryptionKey: getKey() as Data)
let directory = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.xxx")
let realmPath = directory?.appendingPathComponent("xxx.realm")
config.fileURL = realmPath
Realm.Configuration.defaultConfiguration = config
}
}
mostly it is a problem with memory. The Widget will get cut off if it consumes to much.
Unless something in the app needs to change, don't use
completionHandler(NCUpdateResult.NewData)
instead use
completionHandler(NCUpdateResult.noData)
Related
I don't use storyboards.
I want to send protocol data using #objc button action.
However, the sent view controller does not run the protocol function.
May I know what the reason is?
In fact, there's a lot more code.
Others work, but only protocol functions are not executed.
The didUpdataChampion function is
Data imported into a different protocol.
I have confirmed that there is no problem with this.
protocol MyProtocolData {
func protocolData(dataSent: String)
func protocolCount(dataInt: Int)
}
class PickViewController: UIViewController,ChampionManagerDelegate{
static let identifier = "PickViewController"
var count = 0
var urlArray = [URL]()
var pickDelegate : MyProtocolData?
override func viewDidLoad() {
super.viewDidLoad()
champions.riot(url: "myURL")
}
#objc func topHand(){
pickDelegate?.protocolData(dataSent: "top")
print(count)
pickDelegate?.protocoCount(dataInt: count)
let cham = ChampViewController()
cham.modalPresentationStyle = .fullScreen
present(cham, animated: true, completion: nil)
}
//Data imported to another protocol
func didUpdataChampion(_ championManager: ChampionManager, champion: [ChampionRiot]) {
print(#function)
count = champion.count
for data in champion {
let id = data.id
guard let url = URL(string: "https://ddragon.leagueoflegends.com/cdn/11.16.1/img/champion/\(id).png") else { return }
urlArray.append(url)
count = urlArray.count
}
}
func didFailWithError(error: Error) {
print(error)
}
}
class ChampViewController: UIViewController,MyProtocolData {
var pickData = ""
var arrayCount = 0
override func viewDidLoad() {
super.viewDidLoad()
}
func protocolData(dataSent: String) {
print(#function)
pickData = dataSent
print(pickData)
}
func protocoCount(dataInt: Int) {
print(#function)
arrayCount = dataInt
print(arrayCount)
}
}
i don't see full code, for instance how you call bind to topHand(), my advice is:
check that topHand - is called
check that pickDelegate isn't nil inside topHand
Create Object fo your PickViewController class and set its delegate to self.
var yourObj = PickViewController()
override func viewDidLoad() {
super.viewDidLoad()
yourObj.delegate = self
}
I have been trying to create an app that randomly prints a new word after a certain amount of time, i.e five seconds.
import UIKit
class ViewController: UIViewController {
var myTimer : Timer!
var theValue = 0
#IBOutlet weak var textLabel: UILabel!
#IBOutlet weak var InspireLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib
}
override func viewDidDisappear(_ animated: Bool) {
self.myTimer.invalidate()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#objc func updateMyLabel() {
theValue += 1
self.textLabel.text = String(theValue)
}
func randomText() -> String {
if theValue > 5 {
let words = ["Place", "Cat", "House"]
return words.randomElement() ?? "" //Use default method to get random element from Array
}
return "string if theValue < 5 or equal to 5"
}
#IBAction func ResetButton(_ sender: Any) {
self.myTimer.invalidate()
theValue = 0
self.textLabel.text = String(theValue)
}
#IBAction func PauseButton(_ sender: Any) {
self.myTimer.invalidate()
}
#IBAction func PlayButton(_ sender: Any) {
self.myTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateMyLabel), userInfo: nil, repeats: true)
}
}
This is all the code I have right now. As you can probably tell I'm new too StackExchange and so please excuse any breach in etiquette.
it's giving an error because you forgot to add else part in your code.
func randomText() -> String {
if theValue > 5 {
let words = ["Place", "Cat", "House"]
return words.randomElement() ?? "" //Use default method to get random element from Array
}
return "string if theValue < 5 or equal to 5"
}
I am trying to upload an image in a UIImageView to Dropbox using SwiftyDropbox and Swift 3.0. When I press the button nothing happens after the first print statement. What am I doing wrong.
import UIKit
import SwiftyDropbox
class ViewController: UIViewController {
let client = DropboxClientsManager.authorizedClient
#IBOutlet weak var myPhotoView: UIImageView!
#IBAction func logInAction(_ sender: Any) {
myButtonPressed()
}
#IBAction func sendPhotoAction(_ sender: Any) {
print("Button Pressed")
let fileData = UIImageJPEGRepresentation(myPhotoView.image!, 1.0)
//let compressedJPGImage = UIImage(data: fileData!)
let path = "/"
client?.files.upload(path: path, mode: .overwrite, autorename: true, clientModified: nil, mute: false, input: fileData!).response{ response, error in
if let _ = response { // to enable use: if let metadata = response {
print("OK")
} else {
print("Error at end")
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func myButtonPressed(){
DropboxClientsManager.authorizeFromController(UIApplication.shared, controller: self, openURL: {(url:URL) -> Void in UIApplication.shared.openURL(url)
})
}
}
if your client is nil, then you aren't logged in. Try logging in and doing it again. Otherwise it should work fine.
https://dropbox.github.io/SwiftyDropbox/api-docs/latest/index.html#configure-your-project
When developing an iOS app I come across random (sometimes occurring, sometimes not) EXC_BAD_ACCESS error in the following code:
import UIKit
class OrderTripDetailsController: UIViewController, OrderAware {
var order: Order?
var orderService = OrderService()
// MARK: Properties
#IBOutlet weak var driverName: UILabel!
#IBOutlet weak var autoColor: UILabel!
#IBOutlet weak var autoPlates: UILabel!
#IBOutlet weak var autoBrandModel: UILabel!
#IBOutlet weak var map: YMKMapView!
// MARK: Actions
// MARK: Navigation
override func viewDidLoad() {
if let cab = order?.orderCab {
autoColor.text = cab.cab.auto.color.name
autoPlates.text = cab.cab.auto.plates
driverName.text = cab.cab.driver.fullname
autoBrandModel.text = "\(cab.cab.auto.brand) \(cab.cab.auto.model)"
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
orderService.controllerDelegate = self
orderService.startSync()
}
override func viewWillDisappear(animated: Bool) {
orderService.stop() // <-- this is the line that fails
super.viewWillDisappear(animated)
}
// MARK: Order Aware
func setOrder(order: Order){
self.order = order
}
}
OrderService
Order Service is a class that starts timer and stops it. After stop is called, sometimes EXC_BAD_ACCESS occurs
import Locksmith
import RealmSwift
class OrderService {
// MARK: delegates
var controllerDelegate: UIViewController?
// Get the default Realm
let realm = try! Realm()
var timer = NSTimer()
//MARK: Domain actions
//repeat every n time if any dfound
#objc func initOrderSync(timer:NSTimer) {
func onRemoteReceived (order: Order) -> Void {
debugPrint("remote received", order.id)
if let o = realm.objectForPrimaryKey(OrderPo.self, key: order.orderHash) {
if o.orderStatus != order.orderStatus {
debugPrint("order status updated", order.id, order.orderStatus)
OrderUtils.navigateToOrderStatus(order,
viewController: controllerDelegate!)
}
try! realm.write {
o.orderStatus = order.orderStatus
}
}
}
if let authToken = AuthUtils.getToken() {
let orders = getOrdersByStatuses(OrderUtils.activeStatuses)
if orders.count > 0 {
for o in orders {
OrderRemoteService().getOrderFromRemote(o.id!, token: authToken, callback: onRemoteReceived)
}
} else {
debugPrint("invalidating timer; no orders")
stop()
}
} else {
debugPrint("invalidating timer; no auth")
stop()
}
}
func startSync() {
if !self.timer.valid {
debugPrint("starting order sync", controllerDelegate?.restorationIdentifier)
self.timer = NSTimer.scheduledTimerWithTimeInterval(20, target: self, selector: Selector("initOrderSync:"), userInfo: nil, repeats: true)
} else {
debugPrint("sync is already started", controllerDelegate?.restorationIdentifier)
}
}
func stop() {
dispatch_async(GlobalMainQueue, {
if self.timer.valid {
self.timer.invalidate()
debugPrint("invalidated timer", self.controllerDelegate?.restorationIdentifier)
} else {
debugPrint("sync is already stopped", self.controllerDelegate?.restorationIdentifier)
}
})
}
// MARK: orders
func getOrders() -> Results<OrderPo> {
return try! realm.objects(OrderPo.self).sorted("orderTime")
}
func getOrdersByStatuses(statuses: [String]) -> Results<OrderPo> {
var qString = "'\(statuses.first!)'"
if statuses.count > 1 {
for s in 1...statuses.count-1 {
qString += ",'\(statuses[s])'"
}
}
return try! realm.objects(OrderPo.self).filter("orderStatus IN {\(qString)}").sorted("orderTime")
}
}
Could anyone help with any ideas why it might happen?
Update 20.08.2016
Found out that OrderService is being deinitialised after 10 seconds for some reason.
I'm currently encountering a problem within my app. I have a view on which I can search and select a place with the GoogleMaps / GooglePlaces SDK. I'm also using Google Autocomplete for completing the search string.
The problem: When I visit the first view, everything is still fine, but after I have entered a search string and press search, my memory usage increases for about 10-20 MB. When I unwind the view and save it, the memory won't be released and is still in my total memory. Therefore if I save a couple of places I'll get an overflow and the App will crash.
Do you guys know where my problem is in the code? I'm already searching for hours...
I looked for Database request which sets up listeners but in fact nothing happens regarding this in these classes. Maybe it has something to do with Googlemaps, that it keeps up the connection?
I attached 2 screenshots from my app and the 2 classes for these are the following:
import UIKit
import GoogleMaps
class AddNewPlaceViewController: UIViewController, UISearchBarDelegate, LocateOnTheMap {
//Outlets
#IBOutlet weak var googleMapsContainer: UIView!
//Variables
var googleMapsView: GMSMapView!
var searchResultController: SearchResultsController!
var resultsArray = [String]()
//Result
var locationAsCoords = [String:Double]()
var locationAdress = String()
//Error
var alerts = Alerts()
var alertActions = AlertActions()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
self.googleMapsView = GMSMapView(frame: self.googleMapsContainer.frame)
self.view.addSubview(self.googleMapsView)
searchResultController = SearchResultsController(view: self)
searchResultController.delegate = self
showSearchBar()
}
#IBAction func saveButtonTapped(sender: AnyObject) {
if self.locationAdress.isEmpty {
// Error message if no address has been searched
NSLog("Event address ist empty.")
let alert = alerts.alertNoLocationAddress
let alertCancel = alertActions.alertActionCancel
if(alert.actions.count == 0){
alert.addAction(alertCancel)
}
self.presentViewController(alert, animated: true, completion: nil)
} else {
// exits with the saveAndUnwind segue
self.performSegueWithIdentifier("saveAndUnwind", sender: self)
}
}
/**
action for search location by address
- parameter sender: button search location
*/
#IBAction func searchWithAddress(sender: AnyObject) {
showSearchBar()
}
/**
Locate map with latitude and longitude after search location on UISearchBar
- parameter lon: longitude location
- parameter lat: latitude location
- parameter title: title of address location
*/
func locateWithLongitude(lon: Double, andLatitude lat: Double, andTitle title: String) {
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.googleMapsView.clear()
let position = CLLocationCoordinate2DMake(lat, lon)
let marker = GMSMarker(position: position)
let camera = GMSCameraPosition.cameraWithLatitude(lat, longitude: lon, zoom: 15)
self.googleMapsView.camera = camera
marker.title = "\(title)"
marker.map = self.googleMapsView
}
}
func showSearchBar(){
let searchController = UISearchController(searchResultsController: searchResultController)
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.delegate = self
self.presentViewController(searchController, animated: true, completion: nil)
}
/**
Searchbar when text change
- parameter searchBar: searchbar UI
- parameter searchText: searchtext description
We can use filters here in the autocompleteQuery
*/
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
let placeClient = GMSPlacesClient()
placeClient.autocompleteQuery(searchText, bounds: nil, filter: nil) { (results, error: NSError?) -> Void in
self.resultsArray.removeAll()
if results == nil {
return
}
for result in results! {
if let result = result as? GMSAutocompletePrediction {
self.resultsArray.append(result.attributedFullText.string)
}
}
self.searchResultController.reloadDataWithArray(self.resultsArray)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "saveAndUnwind"){
//Pushing the data to the other view controller
let destViewControllerCreateEventTable = segue.destinationViewController as! CreateEventTableViewController
destViewControllerCreateEventTable.locationAsCoords["latitude"] = self.locationAsCoords["latitude"]
destViewControllerCreateEventTable.locationAsCoords["longitude"] = self.locationAsCoords["longitude"]
destViewControllerCreateEventTable.locationAdress = self.locationAdress
destViewControllerCreateEventTable.locationLabel.text = self.locationAdress
destViewControllerCreateEventTable.locationLabel.textColor = UIColor.darkGrayColor()
}
}
}
//
import UIKit
protocol LocateOnTheMap{
func locateWithLongitude(lon:Double, andLatitude lat:Double, andTitle title: String)
}
class SearchResultsController: UITableViewController {
var searchResults: [String]!
var delegate: LocateOnTheMap!
var addNewPlaceReference = AddNewPlaceViewController()
init(view: AddNewPlaceViewController ){
super.init(style: UITableViewStyle.Plain)
addNewPlaceReference = view
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.searchResults = Array()
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cellIdentifier")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.searchResults.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier", forIndexPath: indexPath)
cell.textLabel?.text = self.searchResults[indexPath.row]
return cell
}
override func tableView(tableView: UITableView,
didSelectRowAtIndexPath indexPath: NSIndexPath){
// 1
self.dismissViewControllerAnimated(true, completion: nil)
// 2
let correctedAddress:String! = self.searchResults[indexPath.row].stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.symbolCharacterSet())
let url = NSURL(string: "https://maps.googleapis.com/maps/api/geocode/json?address=\(correctedAddress)&sensor=false")
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) -> Void in
// 3
do {
if data != nil{
let dic = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableLeaves) as! NSDictionary
let lat = dic["results"]?.valueForKey("geometry")?.valueForKey("location")?.valueForKey("lat")?.objectAtIndex(0) as! Double
let lon = dic["results"]?.valueForKey("geometry")?.valueForKey("location")?.valueForKey("lng")?.objectAtIndex(0) as! Double
// 4
self.delegate.locateWithLongitude(lon, andLatitude: lat, andTitle: self.searchResults[indexPath.row])
self.addNewPlaceReference.locationAdress = self.searchResults[indexPath.row]
self.addNewPlaceReference.locationAsCoords["latitude"] = lat
self.addNewPlaceReference.locationAsCoords["longitude"] = lon
}
}catch {
print("Error")
}
}
// 5
task.resume()
}
func reloadDataWithArray(array:[String]){
self.searchResults = array
self.tableView.reloadData()
}
}