Method swizzle not working on iOS 10.1 - ios

I want to swizzle the method #property string in UIPasteboard:
+ (void) load {
....
[UIPasteboard jr_swizzleMethod:#selector(string) withMethod:#selector(stringSwizzle) error:nil];
[UIPasteboard jr_swizzleMethod:#selector(setString:) withMethod:#selector(setStringSwizzle:) error:nil];
....
}
When I called [[UIPasteboard generalPasteboard] setString:#"test"]; it enter my swizzle method. It works on iOS 7, iOS 8, and iOS 9. However, it failed on iOS 10.
The assembly is differnt of a test method:
- (void) pasteboradTest {
[aUIPasteboard setString:#"test"];
}
on iOS 9:
0xced0a <+0>: push {r7, lr}
0xced0c <+2>: mov r7, sp
0xced0e <+4>: sub sp, #0x8
0xced10 <+6>: movw r2, #0xa51c
0xced14 <+10>: movt r2, #0x0
0xced18 <+14>: add r2, pc
0xced1a <+16>: movw r3, #0xa2e2
0xced1e <+20>: movt r3, #0x0
0xced22 <+24>: add r3, pc
0xced24 <+26>: ldr r3, [r3]
0xced26 <+28>: movw r9, #0xbc8e
0xced2a <+32>: movt r9, #0x0
0xced2e <+36>: add r9, pc
0xced30 <+38>: movw r12, #0xc298
0xced34 <+42>: movt r12, #0x0
0xced38 <+46>: add r12, pc
0xced3a <+48>: str r0, [sp, #0x4]
0xced3c <+50>: str r1, [sp]
0xced3e <+52>: ldr.w r0, [r12]
0xced42 <+56>: ldr.w r1, [r9]
0xced46 <+60>: blx r3
0xced48 <+62>: add sp, #0x8
0xced4a <+64>: pop {r7, pc}
on iOS 10:
0x10008f78c <+0>: stp x29, x30, [sp, #-16]!
0x10008f790 <+4>: mov x29, sp
0x10008f794 <+8>: sub sp, sp, #16 ; =16
0x10008f798 <+12>: adrp x8, 9
0x10008f79c <+16>: add x8, x8, #592 ; =592
0x10008f7a0 <+20>: adrp x9, 11
0x10008f7a4 <+24>: add x9, x9, #3480 ; =3480
0x10008f7a8 <+28>: adrp x10, 12
0x10008f7ac <+32>: add x10, x10, #1776 ; =1776
0x10008f7b0 <+36>: str x0, [sp, #8]
0x10008f7b4 <+40>: str x1, [sp]
0x10008f7b8 <+44>: ldr x10, [x10]
0x10008f7bc <+48>: ldr x1, [x9]
0x10008f7c0 <+52>: mov x0, x10
0x10008f7c4 <+56>: mov x2, x8
0x10008f7c8 <+60>: bl 0x100094cb8 ; symbol stub for: objc_msgSend
0x10008f7cc <+64>: mov sp, x29
0x10008f7d0 <+68>: ldp x29, x30, [sp], #16
0x10008f7d4 <+72>: ret

UIPasteboard become a class cluster in iOS 10. The easiest way to notice that is to stop on breakpoint in your app and perform following command in lldb:
(lldb) po [UIPasteboard generalPasteboard]
<_UIConcretePasteboard: 0x6000000087a0>
That's the reason why swizzling doesn't work - you change implementation in UIPasteboard class, but your application invokes implementation of _UIConcretePasteboard private subclass.
You may try to workaround this issue with following code:
+ (void) load {
// ....
[[[UIPasteboard generalPasteboard] class] jr_swizzleMethod:#selector(string) withMethod:#selector(stringSwizzle) error:nil];
[[[UIPasteboard generalPasteboard] class] jr_swizzleMethod:#selector(setString:) withMethod:#selector(setStringSwizzle:) error:nil];
// ....
}
Of course, it's not the safe way to implement swizzling for class cluster - there is no any guarantee that you will not encounter any other private UIPasteboard subclass in runtime.

Related

app crashed when popoverPresentationController and keyboard dismiss

I have a UIViewController, which add a UITableView, a UISearchController. I present this ViewController as UIModalPresentationPopover style.If i only dismiss the ViewController, that's no problem.But when searching text and keyboard showed, then dismiss the ViewController, it crashed! It don't crash when i tap the area outside the popover view.
[Self dismissViewControllerAnimated:YES completion:nil];//dismiss
it'll crash when dismiss like this pic below.
enter image description here
enter image description here
Thread 1 > 19 UIApplicationMain
UIKit`UIApplicationMain:
0x11119d549 <+0>: pushq %rbp
0x11119d54a <+1>: movq %rsp, %rbp
0x11119d54d <+4>: pushq %r15
0x11119d54f <+6>: pushq %r14
0x11119d551 <+8>: pushq %r13
0x11119d553 <+10>: pushq %r12
0x11119d555 <+12>: pushq %rbx
0x11119d556 <+13>: pushq %rax
0x11119d557 <+14>: movq %rcx, %rbx
0x11119d55a <+17>: movq %rsi, -0x30(%rbp)
0x11119d55e <+21>: movl %edi, %r12d
0x11119d561 <+24>: movq 0x115d090(%rip), %r13 ; (void *)0x0000000114a1dc50: objc_retain
0x11119d568 <+31>: movq %rdx, %rdi
0x11119d56b <+34>: callq *%r13
0x11119d56e <+37>: movq %rax, %r14
0x11119d571 <+40>: movq %rbx, %rdi
0x11119d574 <+43>: callq *%r13
0x11119d577 <+46>: movq %rax, %r15
0x11119d57a <+49>: leaq 0x158700b(%rip), %r13 ; _UIApplicationLinkedOnVersion
0x11119d581 <+56>: movl (%r13), %eax
0x11119d585 <+60>: testl %eax, %eax
0x11119d587 <+62>: jne 0x11119d597 ; <+78>
0x11119d589 <+64>: cmpq $-0x1, 0x157fc7f(%rip) ; WebKitSetIsClassic + 7
0x11119d591 <+72>: jne 0x11119d60a ; <+193>
0x11119d593 <+74>: movl (%r13), %eax
0x11119d597 <+78>: cmpl $0x20100, %eax ; imm = 0x20100
0x11119d59c <+83>: jb 0x11119d5c2 ; <+121>
0x11119d59e <+85>: callq 0x11200f0a8 ; symbol stub for: objc_autoreleasePoolPush
0x11119d5a3 <+90>: movq %rax, %r13
0x11119d5a6 <+93>: movl %r12d, %edi
0x11119d5a9 <+96>: movq -0x30(%rbp), %rsi
0x11119d5ad <+100>: movq %r14, %rdx
0x11119d5b0 <+103>: movq %r15, %rcx
0x11119d5b3 <+106>: callq 0x11119d622 ; _UIApplicationMainPreparations
0x11119d5b8 <+111>: movq %r13, %rdi
0x11119d5bb <+114>: callq 0x11200f0a2 ; symbol stub for: objc_autoreleasePoolPop
0x11119d5c0 <+119>: jmp 0x11119d5d4 ; <+139>
0x11119d5c2 <+121>: movl %r12d, %edi
0x11119d5c5 <+124>: movq -0x30(%rbp), %rsi
0x11119d5c9 <+128>: movq %r14, %rdx
0x11119d5cc <+131>: movq %r15, %rcx
0x11119d5cf <+134>: callq 0x11119d622 ; _UIApplicationMainPreparations
0x11119d5d4 <+139>: movq 0x1586ef5(%rip), %rdi ; UIApp
0x11119d5db <+146>: movq 0x14d2b06(%rip), %rsi ; "_run"
0x11119d5e2 <+153>: callq *0x115d000(%rip) ; (void *)0x0000000114a20940: objc_msgSend
0x11119d5e8 <+159>: movq 0x115d001(%rip), %rbx ; (void *)0x0000000114a1dcc0: objc_release
0x11119d5ef <+166>: movq %r15, %rdi
0x11119d5f2 <+169>: callq *%rbx
0x11119d5f4 <+171>: movq %r14, %rdi
0x11119d5f7 <+174>: callq *%rbx
0x11119d5f9 <+176>: xorl %eax, %eax
0x11119d5fb <+178>: addq $0x8, %rsp
0x11119d5ff <+182>: popq %rbx
0x11119d600 <+183>: popq %r12
0x11119d602 <+185>: popq %r13
0x11119d604 <+187>: popq %r14
0x11119d606 <+189>: popq %r15
0x11119d608 <+191>: popq %rbp
0x11119d609 <+192>: retq
0x11119d60a <+193>: leaq 0x157fbff(%rip), %rdi ; _UIApplicationLinkedOnVersionOnce
0x11119d611 <+200>: leaq 0x1160910(%rip), %rsi ; __block_literal_global.1491
0x11119d618 <+207>: callq 0x11200edf6 ; symbol stub for: dispatch_once
0x11119d61d <+212>: jmp 0x11119d593 ; <+74>
First, cancel the searchController
[self searchBarCancelButtonClicked:yourSearchBar];
or
[self.searchDisplayController setActive:NO animated:YES];
and then dismiss the view controller.
[self dismissViewControllerAnimated:YES completion:nil];
This will help.
Try this
[self.view endEditing:YES];
[self dismissViewControllerAnimated:YES completion:nil];

Crash when calling dispatch_source_create() two times in a row

Consider the following code:
#interface ViewController ()
#property (nonatomic, strong) dispatch_source_t source;
#end
#implementation ViewController
-(void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_resume(self.source);
dispatch_source_set_timer(self.source, dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), 0.2 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(self.source, ^{
NSLog(#"%s",__func__);
});
}
#end
If I use dispatch_source_create to create the same DISPATCH_SOURCE_TYPE_TIMER twice, the app will crash. Why?
Is there any difference between creating a dispatch source once and twice like in above example?
libdispatch.dylib`_dispatch_xref_dispose:
0x10015e174 <+0>: ldr w8, [x0, #48]
0x10015e178 <+4>: cmp w8, #2 ; =2
0x10015e17c <+8>: b.hs 0x10015e184 ; <+16>
0x10015e180 <+12>: ret
0x10015e184 <+16>: stp x20, x21, [sp, #-16]!
0x10015e188 <+20>: adrp x20, 41
0x10015e18c <+24>: add x20, x20, #3849 ; =3849
0x10015e190 <+28>: adrp x21, 46
0x10015e194 <+32>: add x21, x21, #2440 ; =2440
0x10015e198 <+36>: str x20, [x21]
0x10015e19c <+40>: ldp x20, x21, [sp], #16
-> 0x10015e1a0 <+44>: brk #0x1
As they say, a picture is worth a thousand words:
Basically you're releasing a suspended dispatch object, which seems to be prohibited by CGD.
Resuming the first timer will make the crash go away:
self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_resume(self.source);
self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_resume(self.source);

iOS app crashes after deleting Main.storyboard

I wanted to switch to xib so I deleted Main.storyboard. Now the app crashed with no output log in didFinishLaunchingWithOptions when [self.window makeKeyAndVisible] is called. I have already cleared Main Interface in Target - General - Deployment Info. Is the crash related to some links that should be removed when I deleted the Main.storyboard?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
MainViewController *mvc = [[MainViewController alloc] init];
UINavigationController *nvc = [[UINavigationController alloc] initWithRootViewController:mvc];
self.window.rootViewController = nvc;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return [[AWSMobileClient sharedInstance] didFinishLaunching:application withOptions:launchOptions];
}
Breakpoint on 0x10759e180:
UIKit`-[UIWindow makeKeyAndVisible]:
0x10759e156 <+0>: pushq %rbp
0x10759e157 <+1>: movq %rsp, %rbp
0x10759e15a <+4>: pushq %rbx
0x10759e15b <+5>: pushq %rax
0x10759e15c <+6>: movq %rdi, %rbx
0x10759e15f <+9>: movq 0xc62182(%rip), %rsi ; "isHidden"
0x10759e166 <+16>: callq *0xce6074(%rip) ; (void *)0x0000000108f97800: objc_msgSend
0x10759e16c <+22>: testb %al, %al
0x10759e16e <+24>: je 0x10759e182 ; <+44>
0x10759e170 <+26>: movq 0xc63a11(%rip), %rsi ; "_orderFrontWithoutMakingKey"
0x10759e177 <+33>: movq %rbx, %rdi
0x10759e17a <+36>: callq *0xce6060(%rip) ; (void *)0x0000000108f97800: objc_msgSend
0x10759e180 <+42>: jmp 0x10759e194 ; <+62>
0x10759e182 <+44>: movq 0xc66a2f(%rip), %rsi ; "_updateLayerOrderingAndSetLayerHidden:"
0x10759e189 <+51>: xorl %edx, %edx
0x10759e18b <+53>: movq %rbx, %rdi
0x10759e18e <+56>: callq *0xce604c(%rip) ; (void *)0x0000000108f97800: objc_msgSend
0x10759e194 <+62>: cmpq %rbx, 0xce0045(%rip) ; _UIKeyWindow
0x10759e19b <+69>: je 0x10759e1b3 ; <+93>
0x10759e19d <+71>: movq 0xc66bfc(%rip), %rsi ; "makeKeyWindow"
0x10759e1a4 <+78>: movq %rbx, %rdi
0x10759e1a7 <+81>: addq $0x8, %rsp
0x10759e1ab <+85>: popq %rbx
0x10759e1ac <+86>: popq %rbp
0x10759e1ad <+87>: jmpq *0xce602d(%rip) ; (void *)0x0000000108f97800: objc_msgSend
0x10759e1b3 <+93>: addq $0x8, %rsp
0x10759e1b7 <+97>: popq %rbx
0x10759e1b8 <+98>: popq %rbp
0x10759e1b9 <+99>: retq
I finally found out that my newly added xib is missing a link from View to the the ViewController. In File's Owner - Connections Inspector - Outlets I dragged view outlet to the xib's view and then problem is solved.

Facing Issue with Share Extension from Sqlite database

I have an iOS App which has a sqlite DB and I am trying to implement Share extension. Hence, I have this DB shared by the main App as well as the share extension.
Following is my implementation
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *AppGroupId = #"XXXX";
NSURL *groupContainerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:AppGroupId];
NSString *sharedDirectory = [groupContainerURL path];
sqliteDb = [sharedDirectory stringByAppendingPathComponent:#"MYDB.sqlite"];
success = [fileManager fileExistsAtPath:sqliteDb];
NSLog(#"path : %#", sqliteDb);
If I put my DB in NSDocument directory (without implementing share extension), everything works fine .
However, if I move it to shared directory and implement sharing extension, the app starts to crash when it goes in background.
Following are the logs and unfortunately I have not been able to debug why this is happening. Any help would be truly appreciated
The Crash log differ very time
like following
libsystem_kernel.dylib`mach_msg_trap:
0x31ae8504 <+0>: mov r12, sp
0x31ae8508 <+4>: push {r4, r5, r6, r8}
0x31ae850c <+8>: ldm r12, {r4, r5, r6}
0x31ae8510 <+12>: mvn r12, #30
0x31ae8514 <+16>: svc #0x80
-> 0x31ae8518 <+20>: pop {r4, r5, r6, r8}
0x31ae851c <+24>: bx lr
Foundation`-[NSConcreteMapTable dealloc]:
0x245b6f68 <+0>: push {r4, r5, r6, r7, lr}
0x245b6f6a <+2>: add r7, sp, #0xc
0x245b6f6c <+4>: push.w {r8, r10}
0x245b6f70 <+8>: sub sp, #0x8
0x245b6f72 <+10>: mov r4, r0
0x245b6f74 <+12>: movw r0, #0xa10
0x245b6f78 <+16>: movt r0, #0xd9f
0x245b6f7c <+20>: movw r1, #0xa0e
0x245b6f80 <+24>: add r0, pc
0x245b6f82 <+26>: movt r1, #0xd9f
0x245b6f86 <+30>: add r1, pc
0x245b6f88 <+32>: ldr.w r8, [r0]
0x245b6f8c <+36>: ldr r5, [r1]
0x245b6f8e <+38>: ldr.w r10, [r4, r8]
0x245b6f92 <+42>: adds r6, r4, r5
0x245b6f94 <+44>: mov r0, r6
0x245b6f96 <+46>: mov r1, r10
0x245b6f98 <+48>: bl 0x24644e10 ; empty
0x245b6f9c <+52>: ldr r0, [r4, r5]
0x245b6f9e <+54>: mov r1, r10
0x245b6fa0 <+56>: ldr r2, [r6, #0x30]
0x245b6fa2 <+58>: blx r2
0x245b6fa4 <+60>: movw r0, #0x9e4
0x245b6fa8 <+64>: mov.w r10, #0x0
0x245b6fac <+68>: movt r0, #0xd9f
0x245b6fb0 <+72>: str.w r10, [r4, r5]
0x245b6fb4 <+76>: add r0, pc
0x245b6fb6 <+78>: ldr.w r8, [r4, r8]
0x245b6fba <+82>: ldr r5, [r0]
0x245b6fbc <+84>: adds r6, r4, r5
0x245b6fbe <+86>: mov r1, r8
0x245b6fc0 <+88>: mov r0, r6
0x245b6fc2 <+90>: bl 0x24644e10 ; empty
-> 0x245b6fc6 <+94>: ldr r0, [r4, r5]
etc
NSString * const DataBaseName = #"MYDB.sqlite";
-(BOOL) createDataBase
{
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:DataBaseName];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) return success;
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:DataBaseName];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error!!!" message:#"Failed to create writable database..." delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
}
return success;
}

iOS NSArray objectAtIndex beyond bounds

I have a UITableView that is populated from an array of data that is parsed from an XML feed. Im struggling to find the cause of this error and was wondering if anyone can help me. The error does not occur very often. It only occurs when the array count is large, for example 10-15 objects and then once refreshed, they array is then a lower number, like 3 - 4 objects. Normally the error is thrown on this line: FCCall *currentCall = [[dataController callsArray] objectAtIndex:((indexPath.row - 1 ) / 2)]; I added an exception breakpoint to break On Throw for All Exception and below is what it returned. I understand what the error is saying but cannot find the origin and it is very difficult to re-produce.
CoreFoundation`-[__NSArrayM objectAtIndex:]:
0x329cce54: push {r4, r5, r7, lr}
0x329cce56: add r7, sp, #8
0x329cce58: sub sp, #8
0x329cce5a: movw r1, #62216
0x329cce5e: mov r4, r2
0x329cce60: movt r1, #2113
0x329cce64: add r1, pc
0x329cce66: ldr r1, [r1]
0x329cce68: ldr r1, [r0, r1]
0x329cce6a: cmp r1, r4
0x329cce6c: bhi 0x329ccef8 ; -[__NSArrayM objectAtIndex:] + 164
0x329cce6e: movw r0, #49640
0x329cce72: cmp r1, #0
0x329cce74: movt r0, #2111
0x329cce78: add r0, pc
0x329cce7a: ldr r0, [r0]
0x329cce7c: ldr r0, [r0]
0x329cce7e: beq 0x329cce9c ; -[__NSArrayM objectAtIndex:] + 72
0x329cce80: movw r2, #17054
0x329cce84: subs r5, r1, #1
0x329cce86: movt r2, #2113
0x329cce8a: movw r3, #61062
0x329cce8e: movt r3, #16
0x329cce92: add r2, pc
0x329cce94: add r3, pc
0x329cce96: strd r4, r5, [sp]
0x329cce9a: b 0x329cceb2 ; -[__NSArrayM objectAtIndex:] + 94
0x329cce9c: movw r2, #17044
0x329ccea0: movt r2, #2113
0x329ccea4: movw r3, #61034
0x329ccea8: movt r3, #16
0x329cceac: add r2, pc
0x329cceae: str r4, [sp]
0x329cceb0: add r3, pc
0x329cceb2: movs r1, #0
0x329cceb4: bl 0x329dce60 ; CFStringCreateWithFormat
0x329cceb8: bl 0x329c897c ; CFMakeCollectable
0x329ccebc: mov r1, r0
0x329ccebe: movs r0, #0
0x329ccec0: bl 0x329ffa8c ; _CFAutoreleasePoolAddObject
0x329ccec4: movw r2, #50122
0x329ccec8: mov r3, r0
0x329cceca: movt r2, #2111
0x329ccece: movw r1, #25010
0x329cced2: add r2, pc
0x329cced4: movt r1, #2112
0x329cced8: movw r0, #26280
0x329ccedc: ldr r2, [r2]
0x329ccede: add r1, pc
0x329ccee0: movt r0, #2112
0x329ccee4: ldr r1, [r1]
0x329ccee6: movs r4, #0
0x329ccee8: add r0, pc
0x329cceea: str r4, [sp]
0x329cceec: ldr r0, [r0]
0x329cceee: ldr r2, [r2]
0x329ccef0: blx 0x32abfeec ; symbol stub for: -[NSMutableOrderedSet removeObjectsInRange:inOrderedSet:]
0x329ccef4: blx 0x32abfe8c ; symbol stub for: -[NSMutableOrderedSet removeObjectsAtIndexes:]
0x329ccef8: movw r1, #62064
0x329ccefc: movt r1, #2113
0x329ccf00: movw r3, #62048
0x329ccf04: add r1, pc
0x329ccf06: movt r3, #2113
0x329ccf0a: movw r2, #62048
0x329ccf0e: ldr r1, [r1]
0x329ccf10: add r3, pc
0x329ccf12: movt r2, #2113
0x329ccf16: ldr r3, [r3]
0x329ccf18: add r2, pc
0x329ccf1a: ldr r2, [r2]
0x329ccf1c: ldr r1, [r0, r1]
0x329ccf1e: ldr r3, [r0, r3]
0x329ccf20: ldr r0, [r0, r2]
0x329ccf22: add.w r2, r4, r1, lsr #2
0x329ccf26: sub.w r1, r2, r3, lsr #2
0x329ccf2a: lsrs r3, r3, #2
0x329ccf2c: cmp r3, r2
0x329ccf2e: it hi
0x329ccf30: movhi r1, r2
0x329ccf32: ldr.w r0, [r0, r1, lsl #2]
0x329ccf36: add sp, #8
0x329ccf38: pop {r4, r5, r7, pc}
0x329ccf3a: nop
0x329ccf3c: nop
0x329ccf3e: nop
Code:
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Returns the cell for the given indexPath
static NSString *cellidentifier1 = #"cell1";
static NSString *cellidentifier2 = #"cell2";
self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"dark-background.jpg"]];
self.tableView.separatorColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"dark-background.jpg"]];
// Invisible Cell
if (indexPath.row % 2 == 0) {
UITableViewCell * cell2 = [theTableView dequeueReusableCellWithIdentifier:cellidentifier2];
if (cell2 == nil) {
cell2 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier2];
[cell2.contentView setAlpha:0];
[cell2 setUserInteractionEnabled:NO];
[cell2 setBackgroundColor:[UIColor clearColor]];
}
return cell2;
}
// Standard Cell
SideSwipeTableViewCell *cell = (SideSwipeTableViewCell *)[theTableView dequeueReusableCellWithIdentifier:cellidentifier1];
if (cell == nil) {
cell = [[SideSwipeTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier1];
}
if ([dataController numberOfCalls] >= 1) {
FCCall *currentCall = [[dataController callsArray] objectAtIndex:((indexPath.row - 1 ) / 2)];
cell.callLabel.text = currentCall.call;
cell.locationLabel.text = currentCall.location;
cell.wcccaNumberLabel.text = currentCall.wcccaNumber;
cell.callNumberLabel.text = currentCall.callnumber;
// Remove leading white space from units string
NSString *units = [currentCall.units stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
cell.unitsLabel.text = units;
cell.stationLabel.text = currentCall.station;
}
return cell;
}
Method that refreshes the array:
- (void)refreshData:(id)object success:(void (^)(NSURLRequest *request, NSURL *url, NSArray *calls))success failure:(void (^)(NSURLRequest *request, NSURL *url, NSError *error))failure
{
NSLog(#"Refresh Started");
// Start the network activity indicator
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
// Check to make sure we can even make an HTTP request
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.wccca.com/PITS"]];
AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Reachable");
// Get the URL we are going to use to parse with
[FCDataController parserURL:[NSURL URLWithString:#"http://www.wccca.com/PITS"] completion:^(NSURL *url) {
NSURLRequest *parserRequest = [NSURLRequest requestWithURL:url];
AFXMLRequestOperation *operation = [AFXMLRequestOperation XMLParserRequestOperationWithRequest:parserRequest success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) {
// Remove all data from our previous calls aray
[self performSelectorOnMainThread:#selector(removeCallsFromArray) withObject:nil waitUntilDone:YES];
// Set the delegate for the XMLParser and start the parse operation
XMLParser.delegate = self;
BOOL successful = [XMLParser parse];
// Determine if the parse operation was a success or not
if (!successful) {
// Return the failure block because the parser failed
failure(request, url, [FCErrors parserError]);
// Stop the network activity indicator
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
else {
// Return the success block
success(request, url, calls);
// Stop the network activity indicator
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
NSLog(#"Refresh Finished");
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLParser *XMLParser) {
NSLog(#"AFXMLOperation Error: %#", error.localizedDescription);
// Remove all data from our previous calls aray
[self performSelectorOnMainThread:#selector(removeCallsFromArray) withObject:nil waitUntilDone:YES];
failure(parserRequest, url, [FCErrors badURLError]);
// Stop the network activity indicator
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(#"Refresh Finished");
}];
[operation start];
}];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Unreachable. AFHTTPRequestOperation Error: %#", error.localizedDescription);
// Remove all data from our previous calls aray
[self performSelectorOnMainThread:#selector(removeCallsFromArray) withObject:nil waitUntilDone:YES];
failure(request, nil, [FCErrors networkError]);
// Stop the network activity indicator
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(#"Refresh Finished");
}];
[requestOperation start];
}
If your underlying data model has changed (such as refreshing your data that the table needs to display), you need to call reloadData on the tableView, otherwise it might request data for a row that no longer exists.

Resources