i create button to add student , i make method handle that by showing pop menu(alert view)
then get the code entered in variable called result (NSString) then called web service get required data from my web service
- (IBAction)add_button:(id)sender {
[self addStudent];
}
- (void) addStudent {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Add Student" message:#"Enter Connection Code" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:#"Add", nil];
[alert setAlertViewStyle:UIAlertViewStylePlainTextInput];
[alert show];
}
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
result = [[alertView textFieldAtIndex:0] text];
NSLog(#"the result connection code %#",result);
WebService *web = [[WebService alloc]init];
[web retriveDataWithCodeAndUrl:result Andurl:STUDENT_URL];
}
in web service class
after finish loading and get required data
i need back my tableview and refresh it with new data
i try protocol but it doent work so i try make instance of my tableview class
, i try also make notification to handle it and refresh view
(webservice class)
-(void) connectionDidFinishLoading :(NSURLConnection *) connection{
NSLog(#"data finish loading ");
School_TableViewController *home = [[School_TableViewController alloc]init];
[home didFinishWithData:respone];
[[self delegate]didFinishLoadingwithData:respone];
[[NSNotificationCenter defaultCenter]
postNotificationName:#"TestNotification"
object:self];
}
back to my table view class to handle notification and refresh table
- (void) receiveTestNotification:(NSNotification *) notification
{
if ([[notification name] isEqualToString:#"TestNotification"])
NSLog (#"Successfully received the test notification!");
[self.tableView reloadData];
}
but it dosnt work , i need nice way to communicate between singleton and tableview
and method to refresh view
thank you in advance
Certainly It doen't work because you didn't update data for your tableView
and I wonder why you didn't use the delegate didFinishLoadingwithData
use delegate:
-In School_TableViewController.h:
#interface School_TableViewController : UITableViewController <YourWebServiceDelegate>
-In School_TableViewController.m:
-(void) didFinishLoadingwithData:(NSData*) data {
// Do parse respone data method and update yourTableViewData
yourtableViewData = notification.object
[self.tableView reloadData];
}
or try
-In service class
-(void) connectionDidFinishLoading :(NSURLConnection *) connection{
NSLog(#"data finish loading ");
/* remove this code you don't need alloc School_TableViewController
School_TableViewController *home = [[School_TableViewController alloc]init];
[home didFinishWithData:respone];
*/
[[self delegate]didFinishLoadingwithData:respone];
[[NSNotificationCenter defaultCenter]
postNotificationName:#"TestNotification"
object:response];
}
-In your tableView
- (void) receiveTestNotification:(NSNotification *) notification
{
if ([[notification name] isEqualToString:#"TestNotification"])
NSLog (#"Successfully received the test notification!");
// Do parse respone data method and update yourTableViewData
yourtableViewData = notification.object
[self.tableView reloadData];
}
Related
I am trying to establish voip call through two different apps. Lets assume one is seller and another is customer. Seller app can only call, and customer app can only receive call. I have setup two apps with sinch applicationKey, secret, userID etc. As I want to receive call in customer app, I have generated VOIP certificate in Apple Dev Account for customer app's bundle id. And I have uploaded that certificate(p12) in Sinch Dashboard. I am using Managed Push in customer app.
But I am unable to receive push or calls in customer app.
I tried changing the bundle id of the two apps. When I keep the bundle id same for the two apps, it works like charm.
My question is, How can I make voip calls between two different apps with different bundle ids?
Here is my AppDelegate.m file codes, which works as it should when the bundle id is same:
#import "SINCallKitProvider.h"
#import "CallViewController.h"
#interface AppDelegate () <SINClientDelegate, SINCallClientDelegate, SINManagedPushDelegate>
#property (nonatomic, readwrite, strong) id<SINManagedPush> push;
#property (nonatomic, readwrite, strong) SINCallKitProvider *callKitProvider;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"didFinishLaunchingWithOptions:");
[Sinch setLogCallback:^(SINLogSeverity severity, NSString *area, NSString *message, NSDate *timestamp) {
NSLog(#"[%#] %#", area, message);
}];
self.push = [Sinch managedPushWithAPSEnvironment:SINAPSEnvironmentAutomatic];
self.push.delegate = self;
[self.push setDesiredPushType:SINPushTypeVoIP];
self.callKitProvider = [[SINCallKitProvider alloc] init];
void (^onUserDidLogin)(NSString *) = ^(NSString *userId) {
[self initSinchClientWithUserId:userId];
};
[[NSNotificationCenter defaultCenter]
addObserverForName:#"UserDidLoginNotification"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
NSString *userId = note.userInfo[#"userId"];
[[NSUserDefaults standardUserDefaults] setObject:userId forKey:#"userId"];
[[NSUserDefaults standardUserDefaults] synchronize];
onUserDidLogin(userId);
}];
[[NSNotificationCenter defaultCenter] addObserverForName:#"UserDidLogoutNotification"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
_client = nil;
}];
return YES;
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
id<SINCall> call = [_callKitProvider currentEstablishedCall];
// If there is one established call, show the callView of the current call when
// the App is brought to foreground. This is mainly to handle the UI transition
// when clicking the App icon on the lockscreen CallKit UI.
if (call) {
UIViewController *top = self.window.rootViewController;
while (top.presentedViewController) {
top = top.presentedViewController;
}
// When entering the application via the App button on the CallKit lockscreen,
// and unlocking the device by PIN code/Touch ID, applicationWillEnterForeground:
// will be invoked twice, and "top" will be CallViewController already after
// the first invocation.
if (![top isMemberOfClass:[CallViewController class]]) {
[top performSegueWithIdentifier:#"callView" sender:call];
}
}
}
#pragma mark -
- (void)initSinchClientWithUserId:(NSString *)userId {
if (!_client) {
_client = [Sinch clientWithApplicationKey:#"<My key>"
applicationSecret:#"<My secret>"
environmentHost:#"clientapi.sinch.com"
userId:userId];
_client.delegate = self;
_client.callClient.delegate = self;
[_client setSupportCalling:YES];
[_client enableManagedPushNotifications];
_callKitProvider.client = _client;
[_client start];
// [_client startListeningOnActiveConnection];
}
}
- (void)handleRemoteNotification:(NSDictionary *)userInfo {
if (!_client) {
NSString *userId = [[NSUserDefaults standardUserDefaults] objectForKey:#"userId"];
if (userId) {
[self initSinchClientWithUserId:userId];
}
}
[self.client relayRemotePushNotification:userInfo];
}
#pragma mark - SINManagedPushDelegate
- (void)managedPush:(id<SINManagedPush>)managedPush
didReceiveIncomingPushWithPayload:(NSDictionary *)payload
forType:(NSString *)pushType {
NSLog(#"didReceiveIncomingPushWithPayload: %#", payload.description);
// Since iOS 13 the application must report an incoming call to CallKit if a
// VoIP push notification was used, and this must be done within the same run
// loop as the push is received (i.e. GCD async dispatch must not be used).
// See https://developer.apple.com/documentation/pushkit/pkpushregistrydelegate/2875784-pushregistry .
[self.callKitProvider didReceivePushWithPayload:payload];
dispatch_async(dispatch_get_main_queue(), ^{
[self handleRemoteNotification:payload];
[self.push didCompleteProcessingPushPayload:payload];
});
}
#pragma mark - SINCallClientDelegate
- (void)client:(id<SINCallClient>)client didReceiveIncomingCall:(id<SINCall>)call {
// Find MainViewController and present CallViewController from it.
UIViewController *top = self.window.rootViewController;
while (top.presentedViewController) {
top = top.presentedViewController;
}
[top performSegueWithIdentifier:#"callView" sender:call];
}
- (void)client:(id<SINClient>)client willReceiveIncomingCall:(id<SINCall>)call {
[self.callKitProvider willReceiveIncomingCall:call];
}
#pragma mark - SINClientDelegate
- (void)clientDidStart:(id<SINClient>)client {
NSLog(#"Sinch client started successfully (version: %#)", [Sinch version]);
}
- (void)clientDidFail:(id<SINClient>)client error:(NSError *)error {
NSLog(#"Sinch client error: %#", [error localizedDescription]);
}
#end
I’m trying to adapt the original Sharekit demo app so that it allows me to authenticate dropbox on a single button press (instead of appearing a new view etc. like it does in the demo).
To do this I have wired up a button with the following method as the IBAction (in the initial ViewController it launches into on Storyboard):
-(IBAction)assignDropbox:(id)sender
{
[SHK setRootViewController:self];
Class sharerClass = NSClassFromString(#"SHKDropbox");
BOOL isiOSSharer = [sharerClass isSubclassOfClass:[SHKiOSSharer class]];
if ([sharerClass isServiceAuthorized]) {
if (isiOSSharer) {
[sharerClass getUserInfo];
UIAlertView *iosSharerAlert = [[UIAlertView alloc] initWithTitle:#"iOS Social.framework sharer"
message:#"You can deauthorize this kind of sharer in settings.app, not here. By tapping this button you have refetched user info data only."
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:#"OK", nil];
[iosSharerAlert show];
} else {
[sharerClass logout];
//[self.tableView reloadData];
}
} else {
SHKSharer *sharer = [[sharerClass alloc] init];
[sharer authorize];
if (isiOSSharer) {
UIAlertView *iosSharerAlert = [[UIAlertView alloc] initWithTitle:#"iOS Social.framework sharer"
message:#"You can authorize this kind of sharer in settings.app, not here."
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:#"OK", nil];
[iosSharerAlert show];
}
}
if ([sharerClass isServiceAuthorized]) {
NSLog(#"After Logging in Username: %#", [sharerClass username]);
} else {
NSLog(#"After Logging in Username: %#", [sharerClass username]);
}
}
I’ve added the following notification code ViewDidLoad of the ViewController:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(authDidFinish:)
name:#"SHKAuthDidFinish"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sendDidCancel:)
name:#"SHKSendDidCancel"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sendDidStart:)
name:#"SHKSendDidStartNotification"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sendDidFinish:)
name:#"SHKSendDidFinish"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sendDidFailWithError:)
name:#"SHKSendDidFailWithError"
object:nil];
With the following code within the actual main (to make the notifications actually work - as per setup):
- (void)authDidFinish:(NSNotification*)notification
{
NSDictionary *userInfo = notification.userInfo;
NSNumber *success = [userInfo objectForKey:#"success"];
if (NO == [success boolValue]) {
NSLog(#"authDidFinish: NO");
} else {
NSLog(#"authDidFinish: YES");
NSLog(#"userInfo: %#", userInfo);
}
}
- (void)sendDidCancel:(NSNotification*)notification
{
NSLog(#"sendDidCancel:");
}
- (void)sendDidStart:(NSNotification*)notification
{
NSLog(#"sendDidStart:");
}
- (void)sendDidFinish:(NSNotification*)notification
{
NSLog(#"sendDidFinish:");
}
- (void)sendDidFailWithError:(NSNotification*)notification
{
NSLog(#"sendDidFailWithError:");
}'
It launches the web view in the app, and I can authenticate (I get notifications from dropbox saying another device has logged on), however the save authentication/session code in ‘SHKDropbox.m’ is never called.
Method under:
- (void)restClient:(DBRestClient*)client loadedAccountInfo:(DBAccountInfo*)info
I’ve done a lot of comparison work to see what the differences are between the projects, but can’t see any difference in settings.
Have you got any storyboard/button presses sample code as described above. Or have you got any idea on why this isn’t working on ShareKit?
I am pretty stuck with this and hoping someone can show me some light about this.
I need help to figure out how to refresh the table list on the main view from the slide-in menu.
IN MAIN VIEW
So basically, I have a main view that has a list of events. I use this function to retrieve data from the database:
[self loadEvents:eventCat sortEvent:nil searchDate:dateSelected];
Inside that function, it has the script that gets data, determines if there is content and then reloads the table:
- (void)loadEvents:(NSString*)searchType sortEvent:(NSString*)sortType searchDate:(NSString *)dateSelect{
NSString *url = [NSString stringWithFormat: #"http://www.url.com/eventList.php];
NSURL *eventURL = [NSURL URLWithString: url];
NSLog(#"%#", eventURL);
NSData *jsonData = [NSData dataWithContentsOfURL: eventURL];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error: &error];
self.eventList = [NSMutableArray array];
NSArray *eventArray = [dataDictionary objectForKey:#"fitpass"];
//NSString *eventFound = [dataDictionary objectForKey:#"notfound"];
//if nothing is found
if ([dataDictionary objectForKey:#"notfound"]){
tableView.hidden = YES;
noEvent.hidden = NO;
NSLog(#"123");
}else{
noEvent.hidden = YES;
tableView.hidden = NO;
NSLog(#"RELOADDATA");
for(NSDictionary *eventDictionary in eventArray){
Event *event = [Event blogPostWithTitle:[eventDictionary objectForKey:#"name"]];
event.eventTime = [eventDictionary objectForKey:#"event_time"];
[self.eventList addObject:event];
[tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
}
}
I tried using the NSNotificationCenter method to refresh the data. So I have this in the viewDidLoad Method:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(refreshTableWithNotification:) name:#"RefreshTable" object:nil];
Then this function right after ViewDidLoad Method:
- (void)refreshTableWithNotification:(NSNotification *)notification
{
[self.tableView reloadData];
}
IN THE SLIDE MENU VIEW
In the side menu, I have a table list to populate the different categories, and when use click a category, it should refresh the event list in the main view:
//on direct press, trigger segue
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//get current value and set the eventCategory ID in userDefault
NSDictionary *catPicked = [self.catList objectAtIndex:indexPath.row];
NSString *eventCat =[catPicked objectForKey:#"ID"];
NSLog(#"%#Picked:", eventCat);
[userDefaults setObject:eventCat forKey:kEventCat];
[userDefaults synchronize];
NSLog(#"%#entered", [userDefaults objectForKey:kEventCat]);
//redirect back to eventList;
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier: #"eventListViewController"];
//refresh data
EventLists *destinationController = [[EventLists alloc] init];
[destinationController loadEvents:eventCat sortEvent:nil searchDate:nil];
//send notofication over
[[NSNotificationCenter defaultCenter] postNotificationName:#"RefreshTable" object:nil userInfo:nil];
[destinationController.view setNeedsDisplay];
[[SlideNavigationController sharedInstance] popToRootAndSwitchToViewController:vc
withSlideOutAnimation:self.slideOutAnimationEnabled
andCompletion:nil];
return;
}
What I am stuck is that I can see the data (eventList) is updated, but the view does not refresh...
Any help would be very much appreciated!!!
Rory!!!
Thank you so much for your help!! I finally figured it out with your hint.
So basically I thought it was passing he data because of my log. But it was just merely running the function. No data was passed.
And the solution was actually rather simple. Since the data was not really being passed over, refreshing the table in the notification function will not work. The data needs to be reloaded. In other word, I just needed to change the notification function in the Main View to:
- (void)refreshTableWithNotification:(NSNotification *)notification
{
[self loadEvents:[userDefaults objectForKey:kEventCat] sortEvent:nil searchDate:dateSelected];
}
Then my Side Menu View is now much simpler since all I needed was the Notification call and view switch:
//redirect back to eventList;
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier: #"eventListViewController"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"RefreshTable" object:nil userInfo:nil];
And yes! I needed to move the notification in the Main view to ViewDidAppear:
- (void)viewDidAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(refreshTableWithNotification:) name:#"RefreshTable" object:nil];
}
Thank you so much for your help!!
My First View is a UIViewController i have a UITable View in it and it works just fine.
From the first view i push another view, in that view i select a group name then the view dismiss, what i want is when i select the group name from the second view the first view loads the values of that group name to the table view, this is the code i use and its not working
the second view code
- (IBAction)sendNames:(id)sender {
if (!keyValue) {
NSLog(#"Didnt Select Any Group To Send");
return;
}
ViewController *theInstance = [[ViewController alloc] init];
[theInstance setGroupName:keyValue];
[theInstance ReceivedGroup:nil];
[self dismissViewControllerAnimated:YES completion:nil];
//tried that option and didnt work too, i added the rest of the code in the viewDidLoad
//[[NSNotificationCenter defaultCenter] postNotificationName:#"RG" object:nil];
}
keyValue is NSString that been set on tableView didSelectRowAtIndexPath
the first view
- (IBAction)ReceivedGroup:(id)sender {
NSString *path = [self dataFilePath];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *tempArray = [dict objectForKey:groupName];
nameArray = [[NSMutableArray alloc] init];
[nameArray addObjectsFromArray:tempArray];
[nameTable reloadData];
NSLog(#"Group Name : %#",groupName);
NSLog(#"Array : %#",nameArray);
}
groupName is NSString
In the log i get the groupName and the nameArray printed
but the tableView is empty.
EDIT: I fixed the problem and posted my answer
Your viewcontroller "theInstance" will be deallocated immediately after calling sendNames: so nothing's gonna happen. You should rather pass a pointer of your first viewcontroller to your second viewcontroller (e.g. set it as a property) and perform all operations on this viewcontroller.
subclass UITableViewController
#interface SecondViewController : UITableViewController
#property (nonatomic, strong) ViewController *firstViewController;
#end
if using storyboard segues implement in your first viewcontroller :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
((SecondViewController *) segue.destinationViewController).firstViewController = self;
}
sendNames: should then look like this:
- (IBAction)sendNames:(id)sender {
if (!keyValue) {
NSLog(#"Didnt Select Any Group To Send");
return;
}
ViewController *theInstance = self.firstViewController;
[theInstance setGroupName:keyValue];
[theInstance ReceivedGroup:nil];
[self dismissViewControllerAnimated:YES completion:nil];
//tried that option and didnt work too, i added the rest of the code in the viewDidLoad
//[[NSNotificationCenter defaultCenter] postNotificationName:#"RG" object:nil];
}
I Fixed it by sending the keyValue using NSNotificationCenter
Here is my code now
For The Second View
- (IBAction)sendNames:(id)sender {
if (!keyValue) {
NSLog(#"Didnt Select Any Group To Send");
return;
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"RG" object:keyValue];
[self dismissViewControllerAnimated:YES completion:nil];
}
Then On The First View
- (void)receiveNotification:(NSNotification *)notification {
NSString *Key = [notification object];
nameArray = [[NSMutableArray alloc] init];
[nameArray removeAllObjects];
NSString *path = [self dataFilePath];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *tempArray = [dict objectForKey:Key];
[nameArray addObjectsFromArray:tempArray];
[self.nameTable reloadData];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[nameTable numberOfRowsInSection:0] - 1 inSection:0];
[nameTable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receiveNotification:) name:#"RG" object:nil];
}
Been looking for a solution for a long while now, but still no success, perhaps someone here can help me.
I created an application that runs a thread that communicates with a webserver in the background. Occasionally the thread receives information that I'd like to display in a UITableView. Because of the dynamic nature of the content I decided a NSMutableArray should be sufficient to store the information from the webserver.
Whenever I receive information from the webservice my AppDelegate sends a notification. My UITableView registers to receive certain kinds of information which I intend to show in the UITableView.
The initWithStyle method of the UITableViewController contains the following code:
- (void)addContact:(NSNotification *)note {
NSLog(#"%#", [note object]);
NSString *message = (NSString *)[note object];
NSString *name = [[message componentsSeparatedByString:#":"] objectAtIndex:2];
contact = name;
[array addObject:contact];
}
- (void)viewDidLoad {
[super viewDidLoad];
array = [[NSMutableArray alloc] initWithObjects:#"test1", #"test2", nil];
tv.dataSource = self;
tv.delegate = self;
self.tableView = tv;
}
The array in AddContact contains the data displayed in the TableView. All data I manually add to the array in ViewDidLoad: will be shown in the table, but it doesn't happen for the data added in the AddContact: method.
Anyone got an idea what I'm doing wrong?
Is the update happening on the main thread?
You can use this sort of refresh function to make sure it does.
- (void)refresh {
if([NSThread isMainThread])
{
[self.tableView reloadData];
[self.tableView setNeedsLayout];
[self.tableView setNeedsDisplay];
}
else
{
[self performSelectorOnMainThread:#selector(refresh) withObject:nil waitUntilDone:YES];
}
}