I need to remove all annotations from PDF document using PDFKit.
Here is my solution:
This solution doesn't work for me, because in one case im getting exception when mutating array while iteration on it.
func removeAllAnnotations() {
guard let documentCheck = document else { return }
for i in (0..<documentCheck.pageCount) {
if let page = documentCheck.page(at: i) {
for annotation in page.annotations {
page.removeAnnotation(annotation)
}
}
}
}
If you want to avoid the “mutate while iterating” problem, just create your own local copy of the array, and iterate through that:
func removeAllAnnotations() {
guard let document = document else { return }
for i in 0..<document.pageCount {
if let page = document.page(at: i) {
let annotations = page.annotations
for annotation in annotations {
page.removeAnnotation(annotation)
}
}
}
}
But, no, I don’t know of any better way to remove all annotations.
This is the objective-C solution, I came up with. This function will not encounter the “mutate while iterating” crash! Hope this will be helpful to someone.
- (void)removeAllAnnotations {
if (self.pdfDocument) {
for (int i = 0; i < self.pdfDocument.pageCount; i++) {
PDFPage *page = [self.pdfDocument pageAtIndex:i];
PDFAnnotation *annotation = page.annotations.lastObject;
while (annotation) {
[page removeAnnotation:annotation];
annotation = page.annotations.lastObject;
}
}
}
}
Related
I am trying to create adding to favorite button, I'am able to add object to an array but for some reason I cannot delete it from the array. How to remove it from the array? .Here is my code. thanks
func didClickFavoriteButton(item: Item) {
// removing from favorite (not working)
if user.favoritCar.contains(item.id!) {
let index = user.favoritCar.firstIndex(of:item.id!)
user.favoritCar.remove(at: index!)
FirebaseReference(.User).document(kFAVORIT).updateData([kFAVORIT :
FieldValue.arrayRemove(user.favoritCar)])
} else {
// Adding to favorite
user.favoritCar.append(item.id!)
FirebaseReference(.User).document(Auth.auth().currentUser!.uid).updateData([kFAVORIT : FieldValue.arrayUnion(user.favoritCar)])
}
Can you try this code:
if let temp = user.favoritCar.first(where: {$0.id == item.id}) {
if let index = user.favoritCar.firstindex(of: temp) {
user.favoritCar.remove(at: index)
}
}
Instead of this code:
if user.favoritCar.contains(item.id!) {
let index = user.favoritCar.firstIndex(of:item.id!)
user.favoritCar.remove(at: index!)
I have an array of dictionary with custom object in swift.
Now I am comparing the object for add & update.
The logic is as simple to add the data if not exist and update if any change in dictionary.
User is custom object type:
#objc public class User: NSObject , Mappable
from the getUserID i can able to get userID
The below code is execute in for loop from where i am passing User object.
var peopleList = [User]()
if self.peopleList.count > 0 {
if self.peopleList.contains(where: {$0.getUserID() == users.getUserID()})
{
// check for any update in dist
if let index = self.peopleList.index(of: users)
{
if users.isEqual(self.peopleList[index])
{
print("equal no updates")
}
else
{
print("need to updates objects..")
}
}
//already exist room
}
else
{
self.peopleList.append(users)
}
}
I know it may be related to equatable
so I am using below fuction
func isEqual<T: Equatable>(type: T.Type, a: Any, b: Any) -> Bool? {
guard let a = a as? T, let b = b as? T else { return nil }
return a == b
}
But I am getting index = nil.
Is there any idea or suggestion to solve it.
If any other way to do it efficiently them most welcome.
I think this simplified version should work
if self.peopleList.isEmpty, let user = self.peopleList.first(where: { $0.getUserID() == users.getUserID() }) {
if user == users {
// is equal
} else {
// do update
}
} else {
self.peopleList.append(users)
}
I am creating a wizard using UICollectionView with an array of CollectionViewCells:
var viewCells:[BaseCVCell] = [createEventSubjectSearch(), createEventEventForm()]
This array is dynamically added to based on a series of UISwitch's that the user controls. I can add to the array fine using the code below, however I can't seem to remove an item when a user turns the switch off.
func switchToggled(sender : UISwitch) {
if sender == createDiarySwitch {
if sender.isOn {
parentClass?.viewCells.append(createEventDeferEvent())
} else {
if let i = parentClass?.viewCells.index(where: { $0 == createEventDeferEvent() }) {
parentClass?.viewCells.remove(at: i)
}
}
}
if sender == createDeferredSwitch {
if sender.isOn {
parentClass?.viewCells.append(createEventDiariseEvent())
} else {
if let i = parentClass?.viewCells.index(where: { $0 == createEventDiariseEvent() }) {
parentClass?.viewCells.remove(at: i)
}
}
}
parentClass?.wizardCollectionView.reloadData()
}
I have tried the above code, as well as:
if let index = parentClass?.viewCells.index(of: createEventDiariseEvent()) {
parentClass?.viewCells.remove(at: index)
}
Neither approach works (no errors, the code just never returns a value). I'd like to try and avoid naming elements where possible. Is there a way to do this?
Thanks for your answers, DonMag
I've achieved the desired functionality by instanciating the two dynamic cells in the main class:
let diariseCell : createEventDiariseEvent()
and then in the loop calling as thus:
if sender == createDiarySwitch {
if sender.isOn {
parentClass?.viewCells.append((parentClass?.diariseCell)!)
} else {
if let i = parentClass?.viewCells.index(where: { $0 == parentClass?.diariseCell }) {
print("Found cell reference at index \(i)")
parentClass?.viewCells.remove(at: i)
}
}
}
Works a charm now. Amazing what another pair of eyes can pick out!
I have a
class Fancy:UIButton
and I want to find all the sibling views which are the same class.
I do this
for v:UIView in superview!.subviews
{
if v.isKindOfClass(Fancy)
{
// you may want... if (v==self) continue
print("found one")
(v as! Fancy).someProperty = 7
(v as! Fancy).someCall()
}
}
it seems to work reliably in testing (no siblings, many, etc)
But there's a lot of "!" in there.
Is this the right way in Swift?
BTW here's a cool way to do it with extensions based on the great answers below
Pass in a type to a generic Swift extension, or ideally infer it
What about using functional programming?
self.superview?
.subviews
.flatMap { $0 as? Fancy }
.filter { $0 != self }
.forEach { fancy in
fancy.someProperty = 4
fancy.someMethod()
}
What about:
for v in superview!.subviews
{
if let f = v as? Fancy{
print("found one")
f.someProperty = 7
f.someCall()
}
}
Or this:
if let views = superview?.subviews
{
for aView in views
{
if let fancyView = aView as? Fancy
{
fancyView.someProperty = 7
fancyView.someCall()
}
}
}
#RobMayoff has a good point about excluding self. The code really should be:
if let views = superview?.subviews
{
for aView in views
{
if let fancyView = aView as? Fancy where fancyView != self
{
fancyView.someProperty = 7
fancyView.someCall()
}
}
}
I'm using SwityJSON to iterate through my JSON data and parse it. It's working fine, but I would like to make sure I'm using the syntax correctly and efficiently. Please review my code below:
if let itemDict = json[0]["artists"].dictionaryValue {
for item in itemDict {
if let artist: Dictionary? = item.1.dictionaryValue {
// artist id
if let artistId = artist?["id"] {
if artistId.stringValue != nil {
// add value to object
}
}
// title
if let title = artist?["title"] {
if title.stringValue != nil {
// add value to object
}
}
// subtitle
if let subtitle = artist?["subtitle"] {
if subtitle.stringValue != nil {
// add value to object
}
}
// image url
if let imageURL = artist?["imageURL"] {
if imageURL.stringValue != nil {
// add value to object
}
}
}
}
}
This is new for all but Ray Wenderlich has provided good tutorial. Try to learn from it. It helped me a lot.