Reputation: 23
I'm making a Today widget for my app. My widget contains a UITableView with 10 cells. (Each cell's height is 50pt.) Function is simple. If I touch up a button on cell, reload DB from sqlite and show them on cells. It works very well on simulator and iPhone 4s, 5, 5s, 6 except only iPhone6+. I did remove widget and add again over 10 times, but It's not helpful for me. I did check memory and zombie. but that is stabilized under ~10M and no leaks. How can I solve my problem?
Upvotes: 2
Views: 5812
Reputation: 171
Edit the extension scheme, Choose Run action, In the Info section, Set Executable to 'Ask on Launch'
This seems to fix the problem and extension runs every single time, no idea how it works but this gets the work going for me.
Upvotes: 0
Reputation: 35372
I like jeeeyul answer's, but many time the extension going to crash (unable to load) just because self.preferredContentSize is not set correctly.
I've solve it by putting a variable "currentHeight" at the TodayViewController class:
var currentHeight : CGFloat = 0.0
@IBOutlet var containerView: UIView! (the storyboard today extension viewcontroller view)
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
... (load custom xib inside my containerView)
self.currentHeight = containerView.frame.size.height
self.preferredContentSize = CGSizeMake(self.view.frame.size.width,currentHeight)
}
func widgetPerformUpdateWithCompletionHandler(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
... (do whatever you want in order to update)
self.preferredContentSize = CGSizeMake(self.view.frame.size.width,currentHeight)
completionHandler(NCUpdateResult.NewData)
...
}
Upvotes: 3
Reputation: 3787
Okay, guys, You don't like my previous answer. I will retry.
Consider below condition:
+-------------------+
| Table View |
|+-----------------+|
|| Cell ||
||+---------------+||
||| UILabel |||
||+---------------+||
|+-----------------+|
+-------------------+
At first the logical width of the table is:
And the content scale factors are:
Actual pixels for 1pt by 1pt are:
So what if a UILabel
fit to entire device width and it's height is 44(minimum tappable height by Apple's HIG), therefore, actual pixels are:
As a result, iPhone6+ requires 3 more times larger buffer than to iPhone5 to draw UILabel.
However, The memory error will be occurred when memory usage of the widget exceed 10MB(Estimated by countless experiments). This same limitation is applies to both device. This limitation is not documented by Apple.
Please remember, you can use only 1% of device memory when you developing iOS8 extensions due to prevent killing background apps. This is the main reason for that there are few apps that support photo editing extension.
Anyway, As a result, Extensions that requires UI are crash easily on iPhone 6+ since the required amount of the memory for each UI element depend on size and content scale.
Custom drawing causes same problem since it requires buffer to draw to optimize animations and rendering. And the resolution and size of the buffer is much bigger on iPhone6+.
In addition, there are bugs(leak) for Notification Center itself, even just Hello World widget(comes with Xcode template) keeps growing memory consumption per each showing and hiding. When eventually it reaches 10MB, it will crash and will be reloaded. It is the reason for that widgets are sometimes flashing. What if some widget crashes 3 times continuously, iOS permanently disable the widget and shows "Unable to Load".
So, what can we do about this problem with such harsh conditions like this, I made some rules for this problem.
[drawRect:]
except when it is extremely small size.This is pretty common problem for Widget that is related memory error, So I'm writing about this also:
All views in widget hierarchy tend to have transparent background(UIClearColor
), it means that making cell tappable is pretty hard. Because entire hit testing for widget will not be occurred when user touch empty area. (custom hit testing only can be applied when there is not transparent one superview at least) There are some solutions for it:
[drawRect:]
on custom cell. DONT, This is pretty easy solution for tapping transparent control, however it requires drawing buffer. Remember the buffer size will be different for each devices.The only solution that I could make it works without additional memory consumption is that the setting widget background color as the black color with 0.01 alpha. (It makes hit-testing works)
+-------------------+
| Table View |- backgorund-color: (0, 0, 0, 0.01)
|+-----------------+|
|| Cell ||
||+---------+ ||
||| UILabel +------++- make it small as possible as you can
||+---------+ ||
|+-----------------+|
+-------------------+
Remember that the container view with just background color will not occupy buffer memory.
Upvotes: 18
Reputation: 3787
iPhone 6+ very large screen, so widget's width is also large. And the max height of widget is much bigger than iPhone5.
As a result,
Widgets on iPhone6+ uses 3~4 more times video memory than iPhone5 due to it's resolution. With some animations, it will be increased much more.
However, iOS allows small amount of memory to widgets due to keep alive apps while shows widgets. (Actual limitations is not documented).
In my experiment, Using custom view that implements drawRect
100% kills widgets on iPhone6+ even it does nothing. (empty implementation)
I think that this is bug. And another my inference is that the entire rect will be cached to be used in core animation, It consumes memory. then iOS kills it.
The real problem is that iPhone6+ has same amount of the RAM with iPhone5.
It's simple:
I can sure that this is hardware design failure of Apple.
Most sad thing is that there will be iPhone6+ users for many years. And developers can't provide rich widgets due to iPhone 6+ users.
Upvotes: -1