I have 5 tabs in UITabbar when I switching 1 > 2 on first time, It slow because in 2 have so much complex view and setup on viewDidLoad().
How can I make it faster or better ? Can I preload 2 when I open 1 ? or Can I show loading indicator when it loading view ?
There is too little context about you problem. The only thing which I can recomend you is to research problem using "Time profiler" instrument in XCode
(For XCode 12.5)
Press XCode -> Open Developer Tool -> Instruments
Then. Press "Time Profiler"
For ViewController with such code
import UIKit
class DelayViewController: UIViewController {
var i = 0
override func viewDidLoad() {
while i < 100000000 {
print("i is \(i)")
i += 1
}
}
}
We can see in "Time profiler" how much time takes print method
You might have too much tasks running on main queue. You should be only doing updating of UI on main queue. Are you fetching something from database, downloading pictures etc. in the method DispatchQueue.main.async { } ? If yes, try fetching these things from database on some other queue (for example DispatchQueue.global). You can also use UIActivityIndicator until your setup is done, and then update it on main queue.
Related
How to minimize the app memory consumption in ARKit Scene after clicking on the back button?
Because every time when I open an ARview in my App, the memory usage is increasing.
When I go back then it does not free the memory and after opening an ARview again, the memory usages increases even further.
class ARViewController: UIViewController, ARSCNViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
setupFocusSquare()
}
func setupScene() {
sceneView.delegate = self
sceneView.session = session
sceneView.antialiasingMode = .multisampling4X
sceneView.automaticallyUpdatesLighting = false
sceneView.preferredFramesPerSecond = 60
sceneView.contentScaleFactor = 1.3
enableEnvironmentMapWithIntensity(25.0)
if let camera = sceneView.pointOfView?.camera {
camera.wantsHDR = true
camera.wantsExposureAdaptation = true
camera.exposureOffset = -1
camera.minimumExposure = -1
camera.maximumExposure = 3
}
}
func setupFocusSquare() {
focusSquare?.isHidden = true
focusSquare?.removeFromParentNode()
focusSquare = FocusSquare()
sceneView.scene.rootNode.addChildNode(focusSquare!)
textManager.scheduleMessage("TRY MOVING LEFT OR RIGHT", inSeconds: 5.0, messageType: .focusSquare)
}
}
The attached source code is not enough to answer how exactly resolve memory leak. I will describe steps how to detect leaks. So, you can add such information to question or maybe resolve an issue by yourself.
Xcode has several instrument to detect memory leaks:
Debug Memory Graph. Launch the app in debug mode. Navigate to the screen and back several times so memory growth. Then tap "Debug Memory Graph" button at debug toolbar.
So, you will see current memory graph of your app. Try to detect some anomaly at left bar:
Maybe you will see few View Controllers or Scene Views. Try to understand what retain this objects and use weak attribute if needed.
Use instruments by click Product -> Profile:
2.1. Select Leaks instrument:
Run the app by tap Record button (red circle) and make several navigations to screen with issue and back. At the bottom you will see some leaks if any. Sort them by size and make attention at Responsible Library. There should be your app name.
If you find something interesting you can select the row and see responsible stack trace.
2.2 Use Allocations instrument:
Run the app by tap Record button (red circle). Navigate to the screen with issue and tap back once. Then click Mark Generation button:
Navigate to the screen with issue and back once more. And click "Mark Generation" once more. Repeat this steps once more and you should see three generations at the bottom:
So you will see which objects are stay alive between back and forward. You can expand for example Generation B and see which object is retained. By click to some row your will see responsible code.
Depending on results at previous steps you may understand where problem is and add some code to resolve retain cycle or unnecessary retain of some object.
Ive been able to distill a problem seen in an app I've written, and have reproduced it in a simple example.
Given these classes:
class Thing {
var name:String = ""
var price:Double = 0.0
var changed:Double = 0.0
var percentChanged:Double = 0.0
}
class TestUIViewController: UIViewController {
}
class ViewController: TestUIViewController {
var thing:Thing?
#IBAction func clicked(_ sender: AnyObject) {
self.thing = Thing()
}
}
I created a UIView with a button, that when pressed, a thing is instantiated. With the Instruments profiler up, I can see memory leaks occurring.
However, if the ViewController class extends from UIViewController, there are no issues.
This was all reproduced from a quick test app, so there are no other external forces at play here that i can think of.
Here is the example code - https://www.dropbox.com/s/ooqh77lhpzbvpv1/ArcTest.zip?dl=0
You may have found a bug in the leak detector, and it could be quite an interesting bug, so you should report it to Apple. But there is in fact no leak. I downloaded and ran your project under Instruments and clicked the button 10 times. This is what I saw in Instruments allocations template:
That is the expected result. There are 9 transient Things, and only one persistent Thing — the one currently assigned to the property. A leak would be if there were more than one persistent Thing, and there isn't.
Also, this is what the memory gauge looks like in Xcode:
We get a little rise (a kind of "mesa") when I repeatedly tap the button, but then we settle back down to the base level again.
I have just recently learned about Unit Testing in Xcode. Now I am trying out Xcode 7 and I see there is a new group for UI Tests when I create a new project.
I watched the WWDC 2015 video and it was pretty good, but do you have a super simple example that I could go through myself? The video examples were a little too complex for me.
Notes
The answer below is my attempt to figure this out, but I welcome any better answers.
I have read these SO questions about UI Testing in Xcode but they are different: docs, reloading, App vs UI, ViewController, multiple, values and properties, pre XCode 7 projects.
Use Unit Tests to test the validity of methods in your classes. You use them to test the code you have written. (See my other example for setting up a simple Unit Test in Xcode.)
Use UI Tests to check the validity of the User Interface. Think of it like having your own robot to go through and do all the normal interactions with your app that a normal user would. This saves you the time of doing it yourself.
At the time of this writing, it is difficult to access many of the properties of the UI components, but just having a test go through tapping them and swiping them confirms that they are there.
Example
This is about the simplest setup and UI test that I could think of: a button that when pressed changes the text of a label.
Set up
Create a new project in Xcode 7+ for iOS 9.0+.
Make sure that Include UI Tests is checked
If you are adding UI tests to a project created before Xcode 7, see this answer. (File > New > Target > Test > Cocoa Touch UI Testing Bundle)
Add a UILabel and a UIButton to the storyboard
Create an #IBOutlet and #IBAction in the ViewController and make the label text change when the button is pressed.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
#IBAction func button(sender: AnyObject) {
label.text = "Hello"
}
}
Do the test
Open the YourProjectUITests file.
Put your curser in the testExample() method. (You can delete the comments)
Press the red Record button
In the app, (1) tap the label, (2) tap the button, and then (3) tap the label again. (4) Press the Record button again to stop recording. The following code should have been automatically generated for you:
func testExample() {
let app = XCUIApplication()
app.staticTexts["Label"].tap()
app.buttons["Button"].tap()
app.staticTexts["Hello"].tap()
}
Use the staticText lines as a starting point for making an XCTAssert. Now you should have:
func testExample() {
let app = XCUIApplication()
XCTAssert(app.staticTexts["Label"].exists)
app.buttons["Button"].tap()
XCTAssert(app.staticTexts["Hello"].exists)
}
Press the diamond on the left to run the UI Test. It should turn green when it passes.
That's it! This showed that the UIButton and UILabel exist and that the text of the label changed. If you want to see it fail (a good idea), you can change "Hello" to something else.
Further study
UI Testing in Xcode
Exploring the New UI Testing Features of Xcode 7
Xcode 7 UI testing, a first look
UI Testing in Xcode 7
#Suragch +1 for the answer. One thing I observed and want to share that every function inside the UI Test case must start with "test". You can append extra name after that. Only this way the button(for clicking to start the test) appears.
I have the following situation: I do a check when user touches screen, to check if it matches some bounds if menuButton.frame.contains(coordinates) {
Then, I try to push a segue like this performSegueWithIdentifier(menuButton.whichButton(menuButton.tag), sender: self) My problem is that the first time the segue performs, it has a huge delay (about 3-4 sec). Afterwards, everything runs as it should. I did check for main thread and I am in the main thread. Can you please help me?
I found the answer, as strange as it may appear, it was related with the fonts. I added some fonts, selected them in interface builder, but of course I didn't check the target membership. So the system was looking for them, I think, before reverting to default font, thus creating the lag. I hope it helps someone at some point.
Have you tried to run on a device or only in the simulator? Just to make sure...
You can try this too:
dispatch_async(dispatch_get_main_queue(),{
self.performSegueWithIdentifier(mysegueIdentifier, self)
})
I have a Today Widget for my app, however I have been told about an issue with it.
Basically, what seems to be happening (I can't test this for myself) is that the widget will sometimes just display 'unable to load' and other times it will just display with a height of 0.
I can't really see why this is happening. I've tested it out on my device and the simulator for weeks now and have never ran into this issue.
I was wondering if it could possibly be down to the refresh code:
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
// Perform any setup necessary in order to update the view.
var defaults = NSUserDefaults(suiteName: "group.AffordIt")
var newCheck = defaults.boolForKey("new")
if newCheck == true {
completionHandler(NCUpdateResult.NewData)
} else {
completionHandler(NCUpdateResult.NoData)
}
}
'newCheck' is true whenever something changes within my app that needs to be displayed in the widget.
Does anyone know what the possible causes of these issues are?
"unable to load" message appears if your extension crashes often. You can try to re-enable it by removing and adding the extension again.
Are you using your own view controller and xib instead of using storyboard? If yes, it is probably that you didn't set the preferredContentSize in your view controller.
try to put the following code in the init function of ur view controller:
self.preferredContentSize = CGSizeMake(320, 100);
I have just began the extension programming today so I am not sure is it really helpful for u or not. Here is the result in my own widget:
Press Edit button in today extensions
Remove your extension
Add your extension again.