EXC_BAD_ACCESS when loading UIImage in Swift - ios

I'm quite new to the iOS platform, but am already an experimented Android dev.
I'm experiencing a weird issue in Swift, we cannot reproduce in Objectice-C. We are designing our interfaces by hand, without using the Interface Builder, to have more flexibility.
We are getting a EXC_BAD_ACCESS on the mentioned line in our custom UIViewController. While the question seems to have been asked many times on StackOverflow, I either haven't found a solution written in Swift or a solution which was working properly and a really similar problem.
override func viewDidLoad() {
super.viewDidLoad()
var logo:UIImage = UIImage(named: "sgLogo")! --> EXC_BAD_ACCESS
var sgLogo:UIImageView = UIImageView(image: logo)
// other UI elements, + constraints
[...]
}
The only element I get is a stack trace, the debugger view in the bar below Xcode is empty. According to that stack trace, the UIImage seems to be instantiated: presence of a memory address.
The sgLogo image is a png image located in the project folder structure not in Images.xcassets. I tried to specify it in the images assets, but I'm still experimenting the same issue. Specifying the extension or not does not help either.
I can provide more code snippets if you want.

It seems that your image can not be found. Check the picture's target. For now you can fix the issue by removing the exclamation mark. If you force unwrap like this and the image is not there, your app will crash. So you can do something like this:
override func viewDidLoad() {
super.viewDidLoad()
var logo = UIImage(named: "sgLogo")
if let logo = logo {
let imgView = UIImageView(image: logo)
} else {
//image is nil
}
// other UI elements, + constraints
[...]
}

I succeeded to solve the issue. I was overriding the loadView method of my UIViewController, but not calling the parent method. Problem solved.

Related

Why does my screen start at the centre of the scroll view? IOS

I have a large title navigation bar set up like this
private func navigationSetUp(){
navigationController?.navigationBar.prefersLargeTitles = true
title = "Dashboard"
}
My problem is whenever I start the app it doesn't start the screen on the top of the page. However, when I scroll it works perfectly fine. I am using auto layout but I doubt it has anything to do with it.
Found my problem that no else would've possibly solved because lack of information in my question.
But I had the scrollviews setting up in the
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
instead of adding it here
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
I have added the same code which you write but for me this is coming perfectly fine did you check your constraints? If yes kindly reverify cause I think its due to your constraints.Check the attach image below:
After scrolling, you can see it is coming fine:
Thanks, hope this will help you.

Autolayout constraints on custom UITableViewCell failing at runtime

My app uses a table view controller to display a custom prototype table view cell containing image views and labels embedded in stack views. Unfortunately, at run time, the primary imageView (on the left) seems to abandon its constraints and display the image in an unanticipated manner.
While I have successfully implemented essentially the same configuration of components embedded in stack views in a view on the prior view controller (top), this same configuration doesn't seem to work in the custom table view cell (bottom).
This is how it appears in XCode:
This is how it appears in simulator:
In first diagnosing the issue, my debugger suggested I set up a symbolic breakpoint by adding a UIViewAlertForUnsatisfiableConstraint, since it was "attempting to recover by breaking a constraint", as described here: How to trap on UIViewAlertForUnsatisfiableConstraints?
That error disappeared after a few attempts at fixing the problem, and was replaced by what appears to be an Apple bug:
Is there a way around this latter bug or am I doing something to trigger it that I can fix?
FYI: I am mostly using IB to lay out constraints since the views are somewhat dense.
You are using UITableViewCell's default UIImageView.
You have to create Outlet connection for ImageView which is in UITableViewCell
Your Code:
class TableViewCell: UITableViewCell {
#IBOutlet weak var thumbImgVw: UIImageView!
}
if let url = URL(string: location.imageUrl) {
if let imageData = try? Data(contentsOf: url) {
let image = UIImage(data: imageData)
cell.thumbImgVw?.layer.cornerRadius = 10
cell.thumbImgVw?.clipsToBounds = true
cell.thumbImgVw?.image = image
}
}

UIView doesn't change at runtime

I've had this working in other variations but something seems to elude me in the change from objective-c to swift as well as moving some of the setup into it's own class.
So i have:
class ViewController: UIViewController, interfaceDelegate, scrollChangeDelegate{
let scrollControl = scrollMethods()
let userinterface = interface()
override func viewDidLoad(){
super.viewDidLoad()
loadMenu("Start")
}
func loadMenu(menuName: String) {
userinterface.delegate = self
userinterface.scrollDelegate = self
userinterface.removeFromSuperview() //no impact
scrollControl.removeFromSuperview() //no impact
userinterface.configureView(menuName)
view.addSubview(scrollControl)
scrollControl.addSubview(userinterface)
}
}
This sets everything up correctly but the problem occurs when I change loadMenu() at runtime. So if the user calls loadMenu("AnotherMenu") it won't change the UIView. It will call the right functions but it won't update the view. Although if I call loadMenu("AnotherMenu") at the start, the correct menu will display. Or if I call loadMenu("Start") and then loadMenu("AnotherMenu") then the menu displayed will be "AnotherMenu". As in:
override func viewDidLoad(){
super.viewDidLoad()
loadMenu("Start")
loadMenu("AnotherMenu")
}
When I list all the subviews each time loadMenu() is called, they look correct. Even during runtime. But the display is not updated. So something isn't getting the word. I've tried disabling Auto Layout after searching for similar issues but didn't see a difference.
Try adding setNeedsDisplay() to loadMenu
Eg
func loadMenu(menuName: String) {
userinterface.delegate = self
userinterface.scrollDelegate = self
userinterface.removeFromSuperview() //no impact
scrollControl.removeFromSuperview() //no impact
userinterface.configureView(menuName)
view.addSubview(scrollControl)
scrollControl.addSubview(userinterface)
view.setNeedsDisplay()
}
setNeedsDisplay() forces the view to reload the user interface.
I didn't want to post the whole UIView class as it is long and I thought unrelated. But Dan was right that he would need to know what was going on in those to figure out the answer. So I created a dummy UIView class to stand in and intended to update the question with that. I then just put a button on the ViewController's UIView. That button was able to act on the view created by the dummy. So the problem was in the other class. Yet it was calling the methods of the ViewController and seemingly worked otherwise. So then the issue must be that its acting on an instanced version? The way the uiview class worked, it uses performSelector(). But in making these methods into their own class, I had just lazily wrote
(ViewController() as NSObjectProtocol).performSelector(selector)
when it should have been
(delegate as! NSObjectProtocol).performSelector(selector)
so that was annoying and I wasted the better part of a day on that. But thanks again for the help.

Swift2 override of highlighted/selected doesn't work

I'm creating a custom UIButton class and i'm trying to override the highlighted/selected methods but they aren't called. After a bit of searching i found that this code should be working:
override var highlighted: Bool {
didSet {
if highlighted {
self.backgroundColor = UIColor.whiteColor()
} else {
self.backgroundColor = UIColor.blackColor()
}
}
}
I did the same for selected. I also tried using willSet but no luck. I'm using swift2.0. Could that make the difference? Anyone knows why it isn't called?
You're going about this all wrong. No need to subclass. Just call setBackgroundImage:forState: with a black image for one state and a white image for the other.
Issue fixed. Due to the fact that i'm wokrking on an SDK shared library, I had to define the Module of my view controller and the Module of my button class. Once I did those, everything was working fluently.

#IBDesignable error: IB Designables: Failed to update auto layout status: Interface Builder Cocoa Touch Tool crashed

I have a very simple subclass of UITextView that adds the "Placeholder" functionality that you can find native to the Text Field object. Here is my code for the subclass:
import UIKit
import Foundation
#IBDesignable class PlaceholderTextView: UITextView, UITextViewDelegate
{
#IBInspectable var placeholder: String = "" {
didSet {
setPlaceholderText()
}
}
private let placeholderColor: UIColor = UIColor.lightGrayColor()
private var textColorCache: UIColor!
override init(frame: CGRect) {
super.init(frame: frame)
self.delegate = self
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.delegate = self
}
func textViewDidBeginEditing(textView: UITextView) {
if textView.text == placeholder {
textView.text = ""
textView.textColor = textColorCache
}
}
func textViewDidEndEditing(textView: UITextView) {
if textView.text == "" && placeholder != "" {
setPlaceholderText()
}
}
func setPlaceholderText() {
if placeholder != "" {
if textColorCache == nil { textColorCache = self.textColor }
self.textColor = placeholderColor
self.text = placeholder
}
}
}
After changing the class for the UITextView object in the Identity Inspector to PlaceholderTextView, I can set the Placeholder property just fine in the Attribute Inspector. The code works great when running the app, but does not display the placeholder text in the interface builder. I also get the following non-blocking errors (I assume this is why it's not rendering at design time):
error: IB Designables: Failed to update auto layout status: Interface Builder Cocoa Touch Tool crashed
error: IB Designables: Failed to render instance of PlaceholderTextView: Rendering the view took longer than 200 ms. Your drawing code may suffer from slow performance.
I'm not able to figure out what is causing these errors. The second error doesn't make any sense, as I'm not even overriding drawRect(). Any ideas?
There are crash reports generated when Interface Builder Cocoa Touch Tool crashes. Theses are located in ~/Library/Logs/DiagnosticReports and named IBDesignablesAgentCocoaTouch_*.crash. In my case they contained a useful stack-trace that identified the issue in my code.
I have had the same issue a couple of times. Both times it started when I was loading an IBDesignable nib onto the storyboard when the nib was not able to fit on the view (ie I had a button off of the UIView but still in the nib). Once I fixed that Xcode still gave me errors so I restarted Xcode until it randomly stopped giving me the error.
I hope this helps.
UPDATE: I just killed all processes named "Interface Builder Cocoa Touch Tool", restarted Xcode and the error went away. Don't know if this will always work or not.
In my case, I was doing the next in the initWithFrame/initWithCoder methods to create the view:
className = NSStringFromClass([self class]);
self.view = [[[NSBundle mainBundle] loadNibNamed:className owner:self options:nil] firstObject];
It looks like I was Not supposed to use the Main Bundle, but instead the bundle of the class. So I replaced that code for the following and it worked:
bundle = [NSBundle bundleForClass:[self class]];
className = NSStringFromClass([self class]);
self.view = [[bundle loadNibNamed:className owner:self options:nil] firstObject];
I thought maybe this might help somebody.
You could select your custom view in Interface Builder and then use
Editor, Debug Selected Views. It will launch so-called IBDesignableAgentCocoaTouch debug session when all breakpoints (including exception breakpoints) work and you could exactly identify the place your view crashes.
For Xcode 8 - Swift
Adding optional value as default value on #IBInspectable causing issue for me.
This won't work:
#IBInspectable var repeatImage: UIImage = UIImage(named:"myImage")!{
didSet {
// configureView
}
}
This should work:
#IBInspectable var repeatImage: UIImage = RepeatImageView.getDefaultImage() {
didSet {
// configureView()
}
}
class func getDefaultImage() -> UIImage {
if let defaultImage = UIImage(named: "myImage") {
return defaultImage
} else {
return UIImage()
}
}
I was experiencing the similar Interface Builder issues rendering designables.
Using the technique suggested in this answer I was able to track down the issue to the use of image literals.
Rendering crash
self.backgroundImage.image = #imageLiteral(resourceName: "rectangleCenter")
No rendering crash
self.backgroundImage.image = UIImage(named: "rectangleCenter")
Actually if you have some old user defined attributes (which is not valid for current view) at any view in your storyboard, that may cause your agent to crash.
Besides, sometimes it happens just because of a nasty bug of Xcode. To check it out, when you're at storyboard uncheck Editor > Automatically Refresh Views, then move to another file, clean and restart your project. After you entered storyboard again, you can click Editor > Refresh Views and check automatic one again. That one also solved my problem once.
If both didn't work, then probably you have done something wrong about your IBDesignable view, so choose your crashed views in storyboard and debug by clicking Editor > Debug Views
This is not the case for this question, but maybe I will help someone else.
I had a similar problem when in my #IBDesignable class I did not implemented both:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// custom setup
}
override init(frame: CGRect) {
super.init(frame: frame)
// custom setup
}
I had the same issue and I solved it by adding the 'use_frameworks!' to my project's Podfile.
Hope it helps you.
In my case, it was a problem with OneSignal. Apparently, they have a bug within the version 2.2.0 and above. Switched to 2.1.6 and everything's great again!
Check out this.
In my case it was somehow related to a carthage framework that I was using. I had to add $(PROJECT_DIR)/Carthage/Build/iOS to the Runpath Search Paths build setting
When i debugged this i found out there are some classes which are modifying UI. Typically marquelabel which is a subclass of UILabel or any other class subclassing UIView and drawing ui at run time and colliding with Autolayout engine. Try giving fixed width or height for these custom views. If it doesn't solve your problem try Following solutions:-
Solution 1:- Uncomment #use_frameworks inside your pod file.
Solution 2:- Try deleting derived data. 1. Close Editor window of your Xcode and quit simulator -> 2. Go to Xcode Preferences -> Locations -> 3. Click small grey arrow showing derived data path -> 4. Select your project -> 5. Delete all the folders inside -> 6. Quit Xcode and reopen
Add it to the bottom of your Podfile and run pod install
# Workaround for Cocoapods issue #7606
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
config.build_settings.delete('CODE_SIGNING_ALLOWED')
config.build_settings.delete('CODE_SIGNING_REQUIRED')
end
end
Add this script at the end of my Podfile and performed pod install again.
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
config.build_settings.delete('CODE_SIGNING_ALLOWED')
config.build_settings.delete('CODE_SIGNING_REQUIRED')
end
end
A major issue is when you are creating #IBDesignable make sure the cocoapod file isn't included in the UITests or else it will cause this crash.
I find the reason is your xib is not the same size as the design in storyboard. Make sure the xib has the same height and width.
I was just missing this line of code
platform :ios, '7.0'
and problem was solved. Just this line in your pod file and update your pod issue will be resolved.
For me it was a missing signing certificate, because I never ran the app, so Xcode did not yet create a certificate. Once I ran the app, the IBDesignable rendering worked fine.
It's like if you got Code from other Developer and you get this error.
Just run
pod install
This worked for me.
Hope It helps.
Make sure that you are not directly initialising UIImage or UIFont using assets or fonts added in your project.
I always create a private func setUp() in my #IBDesignable custom UI classes.
which is called from init(frame: CGRect), init?(coder aDecoder: NSCoder). So I finally updated the setup() as the following.
private func setUp() {
//... Doing initial configurations
// iconImageView.image = UIImage(named: "IconImageName")! // Causing the Crash, use if let OR guard let instead
if let icon = UIImage(named: "IconImageName") {
iconImageView.image = icon
iconImageView.frame.size = icon.size
}
// nameLabel.font = UIFont(name: "Calibri-Light", size: 15.0) // Causing the Crash, use if let OR guard let instead
if let font = UIFont(name: "Calibri-Light", size: size) {
nameLabel.font = font
} else {
nameLabel.font = UIFont.systemFont(ofSize: size)
}
// Doing other stuffs
}
I did everything and it did not work till I restarted MAC. Try restarting MAC. Worked for me.
Just let it to build and run on simulator if you have error in somewhere else in project just comment it out and run designable first to update designable and uncomment the other codes.
It works for me.

Resources